merge with ns-3-dev
authorTom Henderson <tomh@tomh.org>
Fri, 03 Aug 2007 08:29:24 -0700
changeset 1119 520de3dc31a9
parent 1118 e30a3af9e9a5 (current diff)
parent 1022 87e4fb08e8b4 (diff)
child 1120 050454d7d028
merge with ns-3-dev
build.py
doc/build-waf.txt
examples/wscript
src/core/assert.cc
src/internet-node/header-utils.cc
src/internet-node/header-utils.h
src/internet-node/internet-node.cc
src/internet-node/wscript
src/node/ipv4-address.cc
src/node/ipv4-address.h
src/wscript
--- a/.hgignore	Fri Aug 03 08:23:23 2007 -0700
+++ b/.hgignore	Fri Aug 03 08:29:24 2007 -0700
@@ -7,3 +7,5 @@
 doc/html.*
 doc/latex.*
 .lock-wscript
+.waf*
+waf
--- a/.hgtags	Fri Aug 03 08:23:23 2007 -0700
+++ b/.hgtags	Fri Aug 03 08:29:24 2007 -0700
@@ -2,3 +2,4 @@
 7ac5a4b0969b255c4824c926c2b37ef450136ce9 release ns-3.0.2
 0dc81e76166c56aaae64da48b673b62155943aad packet-history-working
 38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3
+5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4
--- a/README	Fri Aug 03 08:23:23 2007 -0700
+++ b/README	Fri Aug 03 08:29:24 2007 -0700
@@ -71,17 +71,13 @@
 
 To build the set of default libraries and the example
 programs included in this package, you need to use the
-tool 'scons'. Detailed information on how to install
-and use scons is included in the file doc/build.txt
+tool 'waf'. Detailed information on how to install
+and use waf is included in the file doc/build.txt
 
 However, the real quick and dirty way to get started is to
-type the command "scons" the the directory which contains
+type the command "./waf" the the directory which contains
 this README file. The files built will be copied in the
-build-dir/dbg-shared/bin and build-dir/dbg-shared/lib
-directories. build-dir/dbg-shared/bin will contain
-one binary for each of the sample code in the 'samples'
-directory and one binary for each of the detailed examples
-found in the 'examples' directory.
+build/debug or build/optimized.
 
 The current codebase is expected to build and run on the
 following set of platforms:
@@ -106,12 +102,7 @@
 should be easy to run the sample programs with the
 following command:
 
-./build-dir/dbg-shared/bin/simple-p2p
-
-or:
-
-cd build-dir/dbg-shared/bin
-./simple-p2p
+./waf --run simple-p2p
 
 That program should generate a simple-p2p.tr text 
 trace file and a set of simple-p2p-xx-xx.pcap binary
@@ -152,7 +143,7 @@
     file in http://code.nsnam.org/docs
 
   - the doxygen documentation is generated from the doc/doxygen.conf
-    configuration file. The command "scons doc" will generate it
+    configuration file. The command "./waf --doxygen" will generate it
     as doc/html/index.html if you have installed the doxygen tools 
     (see http://www.doxygen.org)
 
--- a/RELEASE_NOTES	Fri Aug 03 08:23:23 2007 -0700
+++ b/RELEASE_NOTES	Fri Aug 03 08:29:24 2007 -0700
@@ -3,6 +3,21 @@
 
 This file contains ns-3 release notes (most recent releases first).
 
+Release 3.0.5 (2007/08/XX)
+========================
+
+  - Add CSMA/CD model (Emmanuelle Laprise)
+  - Modularize ipv4 routing support (Gustavo Carneiro)
+  - Add mobility framework and basic mobility models
+
+Release 3.0.4 (2007/07/15)
+========================
+
+  - Enable waf as the default build system.
+  - Per-packet metadata:  a system to track which headers and trailers 
+    are added to a packet
+  - Simplifications to point-to-point devices and channel
+
 Release 3.0.3 (2007/06/15)
 ========================
 
--- a/VERSION	Fri Aug 03 08:23:23 2007 -0700
+++ b/VERSION	Fri Aug 03 08:29:24 2007 -0700
@@ -1,1 +1,1 @@
-3.0.3
+3.0.4
--- a/build.py	Fri Aug 03 08:23:23 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,561 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-# 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>
-
-
-
-import os
-import os.path
-import shutil
-from SCons.Environment import Environment
-from SCons.Builder import Builder
-from SCons.Action import Action
-import SCons
-
-# hack stolen from wengo
-# to get an ARGUMENTS defined correctly
-try:
-    ARGUMENTS = SCons.Script.ARGUMENTS
-    COMMAND_LINE_TARGETS = SCons.Script.COMMAND_LINE_TARGETS
-except AttributeError:
-    from SCons.Script.SConscript import Arguments
-    from SCons.Script.SConscript import CommandLineTargets
-    ARGUMENTS = Arguments
-    COMMAND_LINE_TARGETS = CommandLineTargets
-
-class Ns3Module:
-    def __init__(self, name, dir):
-        self.sources = []
-        self.inst_headers = []
-        self.headers = []
-        self.extra_dist = []
-        self.deps = []
-        self.external_deps = []
-        self.config = []
-        self.name = name
-        self.dir = dir
-        self.executable = False
-        self.library = True
-        self.ldflags = []
-        self.header_inst_dir = ''
-    def set_library(self):
-        self.library = True
-        self.executable = False
-    def set_executable(self):
-        self.library = False
-        self.executable = True
-    def add_config(self, config_fn):
-        self.config.append(config_fn)
-    def add_extra_dist(self, dist):
-        self.extra_dist.append(dist)
-    def add_external_dep(self, dep):
-        self.external_deps.append(dep)
-    def add_dep(self, dep):
-        self.deps.append(dep)
-    def add_deps(self, deps):
-        self.deps.extend(deps)
-    def add_source(self, source):
-        self.sources.append(source)
-    def add_sources(self, sources):
-        self.sources.extend(sources)
-    def add_header(self, header):
-        self.headers.append(header)
-    def add_headers(self, headers):
-        self.headers.extend(headers)
-    def add_inst_header(self, header):
-        self.inst_headers.append(header)
-    def add_inst_headers(self, headers):
-        self.inst_headers.extend(headers)
-    def add_ldflags (self, ldflags):
-        self.ldflags.extend (ldflags)
-    def add_ldflag (self, ldflag):
-        self.add_ldflags ([ldflag])
-    def set_header_inst_dir (self, inst_dir):
-        self.header_inst_dir = inst_dir
-        
-
-def MyCopyAction(target, source, env):
-    try:
-        if len(target) == len(source):
-            for i in range(len(target)):
-                shutil.copy(source[i].path, target[i].path)
-            return 0
-        else:
-            return 'invalid target/source match'
-    except:
-        print
-        return 'exception'
-def MyCopyActionPrint(target, source, env):
-    if len(target) == len(source):
-        output = ''
-        for i in range(len(target)):
-            output = output + 'copy \'' + source[i].path + '\' to \'' + target[i].path + '\''
-            if i < len(target) - 1:
-                output = output + '\n'
-        return output
-    else:
-        return 'error in copy'
-def GcxxEmitter(target, source, env):
-    if os.path.exists(source[0].path):
-        return [target, source]
-    else:
-        return [[], []]
-def MyRmTree(target, source, env):
-    shutil.rmtree(env['RM_DIR'])
-    return 0
-def MyRmTreePrint(target, source, env):
-    return ''
-def print_cmd_line(s, target, src, env):
-    print 'Building ' + (' and '.join([str(x) for x in target])) + '...'
-
-class Ns3BuildVariant:
-    def __init__(self):
-        self.static = False
-        self.gcxx_deps = False
-        self.gcxx_root = ''
-        self.build_root = ''
-        self.env = None
-
-class Ns3:
-    def __init__(self):
-        self.__modules = []
-        self.extra_dist = []
-        self.build_dir = 'build'
-        self.version = '0.0.1'
-        self.name = 'noname'
-        self.distname = 'noname'
-        self.doxygen_config = ''
-    def add(self, module):
-        self.__modules.append(module)
-    def add_extra_dist(self, dist):
-        self.extra_dist.append(dist)
-    def __get_module(self, name):
-        for module in self.__modules:
-            if module.name == name:
-                return module
-        return None
-    def get_mod_output(self, module, variant):
-        if module.executable:
-            suffix = variant.env.subst(variant.env['PROGSUFFIX'])
-            filename = os.path.join(variant.build_root, 'bin', 
-                                    module.name + suffix)
-        else:
-            if variant.static:
-                prefix = variant.env['LIBPREFIX']
-                suffix = variant.env['LIBSUFFIX']
-            else:
-                prefix = variant.env['SHLIBPREFIX']
-                suffix = variant.env['SHLIBSUFFIX']
-            prefix = variant.env.subst(prefix)
-            suffix = variant.env.subst(suffix)
-            filename = os.path.join(variant.build_root, 'lib', 
-                                     prefix + module.name + suffix)
-        return filename
-    def get_obj_builders(self, variant, module):
-        env = variant.env.Copy ()
-        objects = []
-        hash = {}
-        self.get_internal_deps (module, hash)
-        for dep in hash.values ():
-            if dep.header_inst_dir != '':
-                inc_dir = os.path.join(variant.build_root, 'include', 
-                                       self.name, dep.header_inst_dir)
-                env.Append (CPPPATH = [inc_dir])
-                
-        if len(module.config) > 0:
-            src_config_file = os.path.join(self.build_dir, 'config', module.name + '-config.h')
-            tgt_config_file = os.path.join(variant.build_root, 'include', 
-                                           self.name, module.name + '-config.h')
-
-        for source in module.sources:
-            obj_file = os.path.splitext(source)[0] + '.o'
-            tgt = os.path.join(variant.build_root, module.dir, obj_file)
-            src = os.path.join(module.dir, source)
-            if variant.static:
-                obj_builder = env.StaticObject(target = tgt, source = src)
-            else:
-                obj_builder = env.SharedObject(target = tgt, source = src)
-            if len(module.config) > 0:
-                config_file = env.MyCopyBuilder(target = [tgt_config_file], 
-                                                    source = [src_config_file])
-                env.Depends(obj_builder, config_file)
-            if variant.gcxx_deps:
-                gcno_tgt = os.path.join(variant.build_root, module.dir, 
-                                        os.path.splitext(source)[0] + '.gcno')
-                gcda_tgt = os.path.join(variant.build_root, module.dir, 
-                                        os.path.splitext(source)[0] + '.gcda')
-                gcda_src = os.path.join(variant.gcxx_root, module.dir, 
-                                        os.path.splitext(source)[0] + '.gcda')
-                gcno_src = os.path.join(variant.gcxx_root, module.dir, 
-                                        os.path.splitext(source)[0] + '.gcno')
-                gcno_builder = env.CopyGcxxBuilder(target = gcno_tgt, source = gcno_src)
-                gcda_builder = env.CopyGcxxBuilder(target = gcda_tgt, source = gcda_src)
-                env.Depends(obj_builder, gcda_builder)
-                env.Depends(obj_builder, gcno_builder)
-            objects.append(obj_builder)
-        return objects
-    def get_internal_deps(self, module, hash):
-        for dep_name in module.deps:
-            dep = self.__get_module(dep_name)
-            hash[dep_name] = dep
-            self.get_internal_deps(dep, hash)
-    def get_external_deps(self, module):
-        hash = {}
-        self.get_internal_deps(module, hash)
-        ext_hash = {}
-        for mod in hash.values():
-            for ext_dep in mod.external_deps:
-                ext_hash[ext_dep] = 1
-        return ext_hash.keys()
-    def get_sorted_deps(self, module):
-        h = {}
-        self.get_internal_deps(module, h)
-        modules = []
-        for dep in h.keys():
-            deps_copy = []
-            mod = h[dep]
-            deps_copy.extend(mod.deps)
-            modules.append([mod, deps_copy])
-        sorted = []
-        while len(modules) > 0:
-            to_remove = []
-            for item in modules:
-                if len(item[1]) == 0:
-                    to_remove.append(item[0].name)
-            for item in to_remove:
-                for i in modules:
-                    if item in i[1]:
-                        i[1].remove(item)
-            new_modules = []
-            for mod in modules:
-                found = False
-                for i in to_remove:
-                    if i == mod[0].name:
-                        found = True
-                        break
-                if not found:
-                    new_modules.append(mod)
-            modules = new_modules
-            sorted.extend(to_remove)
-        sorted.reverse()
-        # append external deps
-        ext_deps = self.get_external_deps(module)
-        for dep in ext_deps:
-            sorted.append(dep)
-        return sorted
-
-    def gen_mod_dep(self, variant):
-        build_root = variant.build_root
-        cpp_path = os.path.join(variant.build_root, 'include')
-        env = variant.env
-        env.Append(CPPPATH = [cpp_path])
-        header_dir = os.path.join(build_root, 'include', self.name)
-        lib_path = os.path.join(build_root, 'lib')
-        env.Append (LIBPATH = [lib_path])
-        module_builders = []
-        for module in self.__modules:
-            my_env = env.Copy ();
-            objects = self.get_obj_builders(variant, module)
-            libs = self.get_sorted_deps(module)
-            my_env.Append (LIBS = libs)
-            my_env.Append (LINKFLAGS = module.ldflags)
-
-            filename = self.get_mod_output(module, variant)
-            if module.executable:
-                module_builder = my_env.Program(target=filename, source=objects)
-            else:
-                if variant.static:
-                    module_builder = my_env.StaticLibrary(target=filename, source=objects)
-                else:
-                    module_builder = my_env.SharedLibrary(target=filename, source=objects)
-
-            for dep_name in module.deps:
-                dep = self.__get_module(dep_name)
-                my_env.Depends(module_builder, self.get_mod_output(dep, variant))
-
-            for header in module.inst_headers:
-                if module.header_inst_dir != '':
-                    tgt = os.path.join(header_dir, module.header_inst_dir, header)
-                else:
-                    tgt = os.path.join(header_dir, header)
-                src = os.path.join(module.dir, header)
-                #builder = env.Install(target = tgt, source = src)
-                header_builder = my_env.MyCopyBuilder(target=tgt, source=src)
-                my_env.Depends(module_builder, header_builder)
-
-            module_builders.append(module_builder)
-        return module_builders
-    def gen_mod_config(self, env):
-        config_dir = os.path.join(self.build_dir, 'config')
-        for module in self.__modules:
-            if len(module.config) > 0:
-                config_file = os.path.join(config_dir, module.name + '-config.h')
-                config_file_guard = module.name + '_CONFIG_H'
-                config_file_guard.upper()
-                if not os.path.isfile(config_file):
-                    if not os.path.isdir(config_dir):
-                        os.makedirs(config_dir)
-                    outfile = open(config_file, 'w')
-                    outfile.write('#ifndef ' + config_file_guard + '\n')
-                    outfile.write('#define ' + config_file_guard + '\n')
-                    config = env.Configure()
-                    for fn in module.config:
-                        output = fn(env, config)
-                        for o in output:
-                            outfile.write(o)
-                            outfile.write('\n')
-                    outfile.write('#endif /*' + config_file_guard + '*/\n')
-                    config.Finish()
-    def generate_dependencies(self):
-        inheritenv = (ARGUMENTS.get('inheritenv', 'n') in 'yY1')
-        if inheritenv:
-            env = Environment(ENV=os.environ)
-        else:
-            env = Environment()
-        self.gen_mod_config(env)
-        cc = env['CC']
-        cxx = env.subst(env['CXX'])
-        if cc == '':
-            print "Missing C compiler."
-            env.Exit (1);
-        if cxx == '':
-            print "Missing C++ compiler."
-            env.Exit (1);
-        common_flags = ARGUMENTS.get('cflags', '').split(' ')
-        cxxflags = ARGUMENTS.get('cxxflags', '').split(' ')
-        ldflags = ARGUMENTS.get('ldflags', '').split(' ')
-        if cc == 'cl' and cxx == 'cl':
-            env = Environment(tools=['mingw'])
-            cc = env['CC']
-            cxx = env.subst(env['CXX'])
-        if cc == 'gcc' and cxx == 'g++':
-            common_flags.extend(['-g3', '-Wall', '-Werror'])
-            debug_flags = []
-            opti_flags = ['-O3']
-        elif cc == 'cl' and cxx == 'cl':
-            env = Environment(ENV=os.environ)
-            debug_flags = ['-W1', '-GX', '-EHsc', '-D_DEBUG', '/MDd']
-            opti_flags = ['-O2', '-EHsc', '-DNDEBUG', '/MD']
-        cc = ARGUMENTS.get ('cc', '')
-        cxx = ARGUMENTS.get ('cxx', '')
-        if cc != '':
-            env.Replace (CC = cc)
-        if cxx != '':
-            env.Replace (CXX = cxx)
-        env.Append(CCFLAGS = common_flags, 
-                    CPPDEFINES = ['RUN_SELF_TESTS'], 
-                    TARFLAGS = '-c -z', 
-                    CPPFLAGS = cxxflags, 
-                    LINKFLAGS = ldflags)
-        if env['PLATFORM'] == 'posix':
-            env.Append(LINKFLAGS = ' -z origin')
-            env.Append(RPATH=env.Literal(os.path.join('\\$$ORIGIN', os.pardir, 'lib')))
-        verbose = ARGUMENTS.get('verbose', 'n')
-        if verbose == 'n':
-            env['PRINT_CMD_LINE_FUNC'] = print_cmd_line
-        header_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint))
-        env.Append(BUILDERS = {'MyCopyBuilder':header_builder})
-        gcxx_builder = Builder(action = Action(MyCopyAction, strfunction=MyCopyActionPrint), 
-                                emitter = GcxxEmitter)
-        env.Append(BUILDERS = {'CopyGcxxBuilder':gcxx_builder})
-        variant = Ns3BuildVariant()
-        builders = []
-
-
-        gcov_env = env.Copy()
-        gcov_env.Append(CFLAGS = ['-fprofile-arcs', '-ftest-coverage'], 
-                         CXXFLAGS = ['-fprofile-arcs', '-ftest-coverage'], 
-                         LINKFLAGS = ['-fprofile-arcs'])
-        # code coverage analysis
-        variant.static = False
-        variant.env = gcov_env
-        variant.build_root = os.path.join(self.build_dir, 'gcov')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            gcov_env.Alias('gcov', builder)
-        gcov_env.Alias('lcov-report')
-        if 'lcov-report' in COMMAND_LINE_TARGETS:
-            lcov_report_dir = os.path.join(self.build_dir, 'lcov-report')
-            create_dir_command = "rm -rf " + lcov_report_dir
-            create_dir_command += " && mkdir " + lcov_report_dir + ";"
-            gcov_env.Execute(create_dir_command)
-            info_file = os.path.join(lcov_report_dir, self.name + '.info')
-            lcov_command = "utils/lcov/lcov -c -d . -o " + info_file
-            lcov_command += " --source-dirs=" + os.getcwd()
-            lcov_command += ":" + os.path.join(os.getcwd(), 
-                                                variant.build_root, 
-                                                'include')
-            gcov_env.Execute(lcov_command)
-            genhtml_command = "utils/lcov/genhtml -o " + lcov_report_dir
-            genhtml_command += " " + info_file
-            gcov_env.Execute(genhtml_command)
-
-
-
-        opt_env = env.Copy()
-        opt_env.Append(CFLAGS=opti_flags, 
-                        CXXFLAGS=opti_flags, 
-                        CPPDEFINES=['NDEBUG'])
-        # optimized static support
-        variant.static = True
-        variant.env = opt_env
-        variant.build_root = os.path.join(self.build_dir, 'opt-static')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            opt_env.Alias('opt-static', builder)
-
-
-        opt_env = env.Copy()
-        opt_env.Append(CFLAGS = opti_flags, 
-                        CXXFLAGS = opti_flags, 
-                        CPPDEFINES = ['NDEBUG'])
-        # optimized shared support
-        variant.static = False
-        variant.env = opt_env
-        variant.build_root = os.path.join(self.build_dir, 'opt-shared')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            opt_env.Alias('opt-shared', builder)
-
-
-        arc_env = env.Copy()
-        arc_env.Append(CFLAGS=opti_flags, 
-                        CXXFLAGS=opti_flags, 
-                        CPPDEFINES=['NDEBUG'])
-        arc_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-generate'], 
-                        CXXFLAGS=['-frandom-seed=0', '-fprofile-generate'], 
-                        LINKFLAGS=['-frandom-seed=0', '-fprofile-generate'])
-        # arc profiling
-        variant.static = False
-        variant.env = arc_env
-        variant.build_root = os.path.join(self.build_dir, 'opt-arc')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            arc_env.Alias('opt-arc', builder)
-
-
-        arcrebuild_env = env.Copy()
-        arcrebuild_env.Append(CFLAGS=opti_flags, 
-                               CXXFLAGS=opti_flags, 
-                               CPPDEFINES=['NDEBUG'])
-        arcrebuild_env.Append(CFLAGS=['-frandom-seed=0', '-fprofile-use'], 
-                               CXXFLAGS=['-frandom-seed=0', '-fprofile-use'], 
-                               LINKFLAGS=['-frandom-seed=0', '-fprofile-use'])
-        # arc rebuild
-        variant.static = False
-        variant.env = arcrebuild_env
-        variant.gcxx_deps = True
-        variant.gcxx_root = os.path.join(self.build_dir, 'opt-arc')
-        variant.build_root = os.path.join(self.build_dir, 'opt-arc-rebuild')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            arcrebuild_env.Alias('opt-arc-rebuild', builder)
-        variant.gcxx_deps = False
-
-
-
-
-        dbg_env = env.Copy()
-        dbg_env.Append(CFLAGS = debug_flags, 
-                       CXXFLAGS = debug_flags,
-                       CPPDEFINES = ['NS3_DEBUG_ENABLE',
-                                     'NS3_ASSERT_ENABLE'])
-        # debug static support
-        variant.static = True
-        variant.env = dbg_env
-        variant.build_root = os.path.join(self.build_dir, 'dbg-static')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            dbg_env.Alias('dbg-static', builder)
-
-        dbg_env = env.Copy()
-        dbg_env.Append(CFLAGS=debug_flags, 
-                       CXXFLAGS=debug_flags,
-                       CPPDEFINES = ['NS3_DEBUG_ENABLE',
-                                     'NS3_ASSERT_ENABLE'])
-        # debug shared support
-        variant.static = False
-        variant.env = dbg_env
-        variant.build_root = os.path.join(self.build_dir, 'dbg-shared')
-        builders = self.gen_mod_dep(variant)
-        for builder in builders:
-            dbg_env.Alias('dbg-shared', builder)
-
-        env.Alias('dbg', 'dbg-shared')
-        env.Alias('opt', 'opt-shared')
-        env.Default('dbg')
-        env.Alias('all', ['dbg-shared', 'dbg-static', 'opt-shared', 'opt-static'])
-
-
-        # dist support
-        dist_env = env.Copy()
-        if dist_env['PLATFORM'] == 'posix' or dist_env['PLATFORM'] == 'darwin':
-            dist_list = []
-            for module in self.__modules:
-                for f in module.sources:
-                    dist_list.append(os.path.join(module.dir, f))
-                for f in module.headers:
-                    dist_list.append(os.path.join(module.dir, f))
-                for f in module.inst_headers:
-                    dist_list.append(os.path.join(module.dir, f))
-                for f in module.extra_dist:
-                    dist_list.append(os.path.join(module.dir, f))
-            for f in self.extra_dist:
-                dist_list.append(f)
-            dist_list.append (self.doxygen_config)
-            dist_list.append('SConstruct')
-            dist_list.append('build.py')
-
-            targets = []
-            basename = self.distname + '-' + self.version
-            for src in dist_list:
-                tgt = os.path.join(basename, src)
-                targets.append(dist_env.MyCopyBuilder(target=tgt, source=src))
-            tar = basename + '.tar.gz'
-            zip = basename + '.zip'
-            tmp_tar = os.path.join(self.build_dir, tar)
-            tmp_zip = os.path.join(self.build_dir, zip)
-            dist_tgt = [tar, zip]
-            dist_src = [tmp_tar, tmp_zip]
-            dist_env.Tar(tmp_tar, targets)
-            dist_env.Zip(tmp_zip, targets)
-            dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
-            dist_env.Alias('dist', dist_builder)
-            dist_env.Append(RM_DIR=basename)
-            dist_env.AddPostAction(dist_builder, dist_env.Action(MyRmTree, 
-                                                                 strfunction=MyRmTreePrint))
-            dist_builder = dist_env.MyCopyBuilder(target=dist_tgt, source=dist_src)
-            dist_env.Alias('fastdist', dist_tgt)
-
-            # distcheck
-            distcheck_list = []
-            for src in dist_list:
-                tgt = os.path.join(self.build_dir, basename, src)
-                distcheck_list.append(tgt)
-            untar = env.Command(distcheck_list, tar, 
-                                ['cd ' + self.build_dir + ' && tar -zxf ../' + tar])
-            scons_dir = os.path.join(self.build_dir, basename)
-            distcheck_builder = env.Command('x', distcheck_list, 
-                                            ['cd ' + scons_dir + ' && scons'])
-            env.AlwaysBuild(distcheck_builder)
-            env.Alias('distcheck', distcheck_builder)
-        if self.doxygen_config != '':
-            doxy = env.Command('doc/html/*', self.doxygen_config, 
-                               ['doxygen ' + self.doxygen_config])
-            env.AlwaysBuild(doxy)
-            env.Alias('doc', doxy)
--- a/doc/build-waf.txt	Fri Aug 03 08:23:23 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-The main ns-3 build system is SCons.  Read the file build.txt
-for SCons instructions.
-
-Waf is an alternative build system, similar to SCons.  ns-3 now is
-able to build with Waf, in parallel to SCons.
-
-(http://www.freehackers.org/~tnagy/waf.html)
-
-Note: the Waf build scripts are experimental at this stage.
-Gustavo Carneiro (gjcarneiro@gmail.com) is the maintainer.
-
-=== Building with Waf ===
-
-To build ns-3 with waf type the commands:
- 1. ./waf configure [options]
- 2. ./waf
-
-[ Note: if ./waf does not exist, see the section "Note for developers" below ]
-
-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.
-
-The resulting binaries are placed in build/<debuglevel>/srcpath.
-
-Other waf usages include:
-
- 1. ./waf check
-    Runs the unit tests
-
- 2. ./waf --doxygen
-    Run doxygen to generate documentation
-
- 3. ./waf --lcov-report
-    Run code coverage analysis (assuming the project was configured
-with --enable-gcov)
-
- 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.
-
- 5. ./waf --shell
-    Starts a nested system shell with modified environment to run ns3 programs.
-
-
-=== Extending ns-3 ===
-
-To add new modules:
-  1. Create the module directory under src (or src/devices, or whatever);
-  2. Add the source files to it;
-  3. Add a 'wscript' describing it;
-  4. Add the module subdirectory name to the all_modules list in src/wscript.
-
-A module's wscript file is basically a regular Waf script.  A ns-3
-module is created as a cpp/shlib object, like this:
-
-def build(bld):
-    obj = bld.create_obj('cpp', 'shlib')
-
-    ## set module name; by convention it starts with ns3-
-    obj.name = 'ns3-mymodule'
-    obj.target = obj.name 
-
-    ## list dependencies to other modules
-    obj.uselib_local = ['ns3-core'] 
-
-    ## list source files (private or public header files excluded)
-    obj.source = [
-        'mymodule.cc',
-    ]
-
-    ## list module public header files
-    headers = bld.create_obj('ns3header')
-    headers.source = [
-        'mymodule-header.h',
-    ]
-
-
-=== Note for developers ===
-
-The ns-3 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 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/build.txt	Fri Aug 03 08:23:23 2007 -0700
+++ b/doc/build.txt	Fri Aug 03 08:29:24 2007 -0700
@@ -1,186 +1,115 @@
-If you want to build ns3, you need to install scons (see
-http://www.scons.org). scons takes care of building
-the whole source tree using your system compiler. scons
-0.91.1 and 0.91.96 have been tested and are known to 
-work on linux FC5, Mac os X and MinGW.
+The Waf build system is used to build ns-3.  Waf is a Python-based
+build system (http://www.freehackers.org/~tnagy/waf.html)
+
+=== Installing Waf ===
 
-To start a build, you can just type 'scons' which
-will generate a debug shared build by default, located
-in the directory 'build-dir/dbg-shared/bin' and
-'build-dir/dbg-shared/lib'.
+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:
 
-All builds are built with debugging symbols. Debugging
-builds enable asserts while optimized builds disable them.
-On platforms which support it, rpath is used which means that
-the executable binaries generated link explicitely against
-the right libraries. This saves you the pain of having to
-setup environment variables to point to the right libraries.
+  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 ]
 
-(Note:  An alternative build system (Waf) is being
-evaluated in the development branch of ns-3-dev on our server
-only (i.e., not in the release tarballs)-- see doc/build-waf.txt)
+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).
 
-1) Options
-----------
+=== Building with Waf ===
 
-- verbose: if you have installed scons 0.91.96 or higher, 
-  the default build output is terse. To get a more verbose 
-  output, you need to set the 'verbose' variable to 'y'.
-Example: scons verbose=y
-- cflags: flags for the C compiler.
-Example: scons cflags="-O3 -ffast-math"
-- cxxflags: flags for the C++ compiler.
-Example: scons cxxflags="-O3 -ffast-math"
-- ldflags: flags for the linker:
-Example: scons ldflags="-L/foo -L/bar"
-- cc: the C compiler to use:
-Example: scons cc=gcc-4.0
-- cxx: the C++ compiler to use:
-Example: scons cxx=g++-4.0
-- high-precision-as-double: set to 'y' to make sure that the
-  high-precision arithmetics performed by the Time class on
-  behalf of the user will use doubles. By default, the code
-  uses 128 integers.
-Example: scons high-precision-as-double=y
-- inheritenv: set to 'y' if you want to make your compiler
-  execute within the same environment (env vars) as your own
-  shell. This is typically used to make colorgcc work.
-Example: scons inheritenv=y
+To build ns-3 with waf type the commands:
+ 1. waf configure [options]
+ 2. waf
 
-2) Targets
-----------
-
-- doc: build the doxygen documentation.
-Example: scons doc
+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
+also possible to change the flags used for compilation with (e.g.):
+CXXFLAGS="-O3" waf configure.
 
-- dbg-shared: a debug build using shared libraries.
-  The files are built in 'build-dir/dbg-shared/'.
-Example: scons dbg-shared
-
-- dbg-static: a debug build using static libraries
-  The files are built in 'build-dir/dbg-static/'.
-Example: scons dbg-static
+[ 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" ]
 
-- opt-shared: an optimized build using shared libraries.
-  The files are built in 'build-dir/opt-shared/'.
-Example: scons opt-shared
+The resulting binaries are placed in build/<debuglevel>/srcpath.
 
-- opt-static: an optimized build using static libraries.
-  The files are built in 'build-dir/opt-static/'.
-Example: scons opt-static
+Other waf usages include:
 
-- dbg: an alias for dbg-shared
-Example: scons dbg
-
-- opt: an alias for opt-shared
-Example: scons opt
+ 1. waf check
+    Runs the unit tests
 
-- all: alias for dbg-shared, dbg-static, opt-shared 
-  and opt-static
-Example: scons all
+ 2. waf --doxygen
+    Run doxygen to generate documentation
 
-- gcov: code coverage analysis. Build a debugging version of
-  the code for code coverage analysis in 'build-dir/gcov'. Once
-  the code has been built, you can run various applications to
-  exercise the code paths. To generate an html report from
-  the gcov data, use the lcov-report target
-
-- lcov-report: generate html report of gcov data. The output
-  is stored in 'build-dir/lcov-report/'.
+ 3. waf --lcov-report
+    Run code coverage analysis (assuming the project was configured
+with --enable-gcov)
 
-- dist: generate a release tarball and zipfile from the 
-  source tree. The tarball and zipfile name are generated
-  according to the version number stored in the SConstruct
-  file.
-Example in SConstruct:
-ns3 = Ns3 ()
-ns3.name = 'foo'
-ns3.version = '0.0.10'
-Example command: scons dist
-Example output files:
-foo-0.0.10.tar.gz
-foo-0.0.10.zip
+ 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.
 
-- distcheck: generate a release tarball and zipfile and 
-  attempt to run the 'all' target for the release tarball.
-Example: scons distcheck
+ 4.1 waf --run programname --command-template "... %s ..."
 
-3) How the build system works
------------------------------
+    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:
 
-The current build system defines what are called "ns3 modules": each module
-is a set of source files, normal header files and installable header
-files. Each module also depends on a set of other modules. We build
-modules automatically in the correct order. That is, we always start
-from the module which does not depend on any other module (core) and
-proceed with the other modules and make sure that when a module is
-built, all the modules it depends upon have already been built.
+         waf --run run-tests --command-template "valgrind %s"
+
+ 5. waf --shell
+    Starts a nested system shell with modified environment to run ns3 programs.
+
+ 6. waf distclean
+    Cleans out the entire build/ directory
 
-To build a module, we:
-1) generate the .o files
-2) link the .o files together 
-3) install the installable headers in the common directory
-top_build_dir/include/ns3.
+ 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 ~).
 
-This means that if you want to use a header from your own module, you
-should just include it: #include "foo.h" but if you want to include a
-header from another module, you need to include it with #include
-"ns3/bar.h". This allows you to make sure that our "public" ns3 headers
-do not conflict with existing system-level headers.   For instance,
-if you were to define a header called queue.h, you would include
-ns3/queue.h rather than queue.h, when including from a separate module,
-since many systems provide a queue.h system include file.  
 
-4) How to add files to a module ?
----------------------------------
+=== Extending ns-3 ===
 
-In the main SConstruct file, you can add source code
-to the add_sources method. For example, to add a foo.cc
-file to the core module, we coud do this:
-core.add_sources ('foo.cc')
-Of course, if this file implements public API, its 
-header should be installable:
-core.add_inst_headers ('foo.h')
+To add new modules:
+  1. Create the module directory under src (or src/devices, or whatever);
+  2. Add the source files to it;
+  3. Add a 'wscript' describing it;
+  4. Add the module subdirectory name to the all_modules list in src/wscript.
 
-5) How to create a new module ?
--------------------------------
+A module's wscript file is basically a regular Waf script.  A ns-3
+module is created as a cpp/shlib object, like this:
+
+def build(bld):
+    obj = bld.create_obj('cpp', 'shlib')
 
-# create a new module. First arg is the name of
-# the new module. Second arg is the directory in
-# which all source files for this module reside.
-my_module = build.Ns3Module ('my', 'src/my_dir')
-# add it to build system
-ns3.add (my_module)
-# specify module dependencies. Here, depends
-# on the 'ipv4' and 'core' modules
-my_module.add_deps (['core', 'ipv4']) 
-# add source code to build located in 
-# src/my_dir
-my_module.add_sources ([
-	'my_a.cc',
-	'my_b.cc',
-	'my_c.cc'
-])
-my_module.add_sources ([
-	'my_d.cc'
-])
-# add headers which are not public
-my_module.add_headers ([
-	'my_a.h',
-	'my_c.h'
-])
-# add headers which are public
-my_module.add_inst_headers ([
-	'my_b.h'
-])
-my_module.add_inst_headers ([
-	'my_d.h'
-])
-# if you need to link against an external library,
-# you must add 'external' dependencies. Here, the 
-# pthread library
-my_module.add_external_dep ('pthread')
-# by default, a module is conceptually a library. If you
-# want to generate an executable from a module you need to:
-my_module.set_executable ()
+    ## set module name; by convention it starts with ns3-
+    obj.name = 'ns3-mymodule'
+    obj.target = obj.name 
+
+    ## list dependencies to other modules
+    obj.uselib_local = ['ns3-core'] 
 
+    ## list source files (private or public header files excluded)
+    obj.source = [
+        'mymodule.cc',
+    ]
+
+    ## list module public header files
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'mymodule-header.h',
+    ]
+
--- a/doc/release_steps.txt	Fri Aug 03 08:23:23 2007 -0700
+++ b/doc/release_steps.txt	Fri Aug 03 08:29:24 2007 -0700
@@ -5,15 +5,23 @@
    - revise and check in RELEASE_NOTES
    - update and check in VERSION to the latest release number
 2. make a new "architecture.pdf" document and place it in the doc/ directory
-3. scons dist
-4. test tarball on release platforms (run-tests and simple-p2p)
-5. tag ns-3-dev with "release ns-3.0.X"
-6. clone the ns-3-dev and place it on the repository
-7. upload "ns-3.0.x.tar.gz" to the releases/ directory on the server
-8. update web page
+3. add current version of waf script from subversion:
+   - svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
+   - build waf script and put it into top of ns-3-dev
+4. cd ns-3-dev; ./waf configure; ./waf dist
+5. test tarball on release platforms (run-tests and simple-p2p)
+6. tag ns-3-dev with "release ns-3.0.X"
+  - hg tag "release ns-3.0.x"
+  - hg push 
+7. 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
+8. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
+9. update web page
    - add link to news.html
    - update download.html
    - update roadmap.html
    - build and update Doxygen directory on the server
    - update and upload software architecture document (PDF, HTML)
-9. announce to ns-developers, with summary of release notes
+10. announce to ns-developers, with summary of release notes
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-cd-one-subnet.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,172 @@
+/* -*- 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
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - CBR/UDP flows from n0 to n1, and from n3 to n0
+// - 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 "csma-cd-one-subnet.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/debug.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/csma-cd-channel.h"
+#include "ns3/csma-cd-net-device.h"
+#include "ns3/csma-cd-topology.h"
+#include "ns3/csma-cd-ipv4-topology.h"
+#include "ns3/mac-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/onoff-application.h"
+
+#include "ns3/ascii-trace.h"
+
+#include "ns3/trace-context.h"
+#include "ns3/trace-root.h"
+
+
+using namespace ns3;
+
+
+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 
+  DebugComponentEnable("CsmaCdNetDevice");
+  DebugComponentEnable("Ipv4L3Protocol");
+  DebugComponentEnable("NetDevice");
+  DebugComponentEnable("Channel");
+  DebugComponentEnable("CsmaCdChannel");
+  DebugComponentEnable("PacketSocket");
+#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
+  Bind ("Queue", "DropTailQueue");
+
+  // 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.
+  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
+  Ptr<CsmaCdChannel> channel0 = 
+    CsmaCdTopology::CreateCsmaCdChannel(
+      DataRate(5000000), MilliSeconds(2));
+
+  uint32_t n0ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, 
+                                         MacAddress("10:54:23:54:23:50"));
+  uint32_t n1ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0,
+                                         MacAddress("10:54:23:54:23:51"));
+  uint32_t n2ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0,
+                                         MacAddress("10:54:23:54:23:52"));
+  uint32_t n3ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0,
+                                         MacAddress("10:54:23:54:23:53"));
+
+  // Later, we add IP addresses.  
+  CsmaCdIpv4Topology::AddIpv4Address (
+      n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0"));
+
+  CsmaCdIpv4Topology::AddIpv4Address (
+      n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0"));
+
+  CsmaCdIpv4Topology::AddIpv4Address (
+      n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaCdIpv4Topology::AddIpv4Address (
+      n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0"));
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  // from n0 to n1
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    Ipv4Address("10.1.1.2"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    Ipv4Address("10.1.1.1"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+ 
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the csma-cd-one-subnet.tr file
+  AsciiTrace asciitrace ("csma-cd-one-subnet.tr");
+  asciitrace.TraceAllNetDeviceRx ();
+  asciitrace.TraceAllQueues ();
+
+  // 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 ("csma-cd-one-subnet.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-point-to-point.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,193 @@
+/* -*- 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 <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#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/mac-address.h"
+#include "ns3/ipv4-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"
+
+using namespace ns3;
+
+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 
+  DebugComponentEnable("Object");
+  DebugComponentEnable("Queue");
+  DebugComponentEnable("DropTailQueue");
+  DebugComponentEnable("Channel");
+  DebugComponentEnable("PointToPointChannel");
+  DebugComponentEnable("PointToPointNetDevice");
+#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
+  Bind ("Queue", "DropTailQueue");
+
+  Bind ("OnOffApplicationPacketSize", "210");
+  Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //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.
+  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
+  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.  
+  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
+  PointToPointTopology::AddIpv4Routes(n0, n2, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  PointToPointTopology::AddIpv4Routes(n2, n3, channel2);
+
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    Ipv4Address("10.1.3.2"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n1, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    Ipv4Address("10.1.2.1"), 
+    80, 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+
+  // Here, finish off packet routing configuration
+  // This will likely set by some global StaticRouting object in the future
+  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
+  AsciiTrace asciitrace ("simple-point-to-point.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.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- a/examples/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/examples/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -9,9 +9,8 @@
         obj.source = source
         return obj
         
-    obj = create_ns_prog('simple-p2p', 'simple-p2p.cc',
-                         deps=['p2p', 'internet-node'])
-
     obj = create_ns_prog('simple-global-routing', 'simple-global-routing.cc',
                          deps=['p2p', 'internet-node', 'routing'])
+    obj = create_ns_prog('simple-point-to-point', 'simple-point-to-point.cc', deps=['point-to-point', 'internet-node'])
+    obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', deps=['csma-cd', 'internet-node'])
 
--- a/samples/main-default-value.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/samples/main-default-value.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -14,8 +14,8 @@
 // value of the default parameter.  Then as other code require the values of 
 // the defaults, they query them with GetValue() to get the present value.
 static BooleanDefaultValue defaultTestBool1 ("testBool1", "helpBool", true);
-static IntegerDefaultValue<int> defaultTestInt1 ("testInt1", "helpInt1", 33);
-static IntegerDefaultValue<uint32_t> defaultTestInt2 ("testInt2", "helpInt2", 47);
+static NumericDefaultValue<int> defaultTestInt1 ("testInt1", "helpInt1", 33);
+static NumericDefaultValue<uint32_t> defaultTestInt2 ("testInt2", "helpInt2", 47);
 
 // 
 // This test class demonstrates the declaration of variables that
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-grid-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,49 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+
+#include "ns3/ptr.h"
+#include "ns3/grid-topology.h"
+#include "ns3/static-mobility-model.h"
+#include "ns3/internet-node.h"
+#include "ns3/command-line.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+  CommandLine::Parse (argc, argv);
+
+  std::vector<Ptr<Object> > nodes;
+
+  // create an array of empty nodes for testing purposes 
+  for (uint32_t i = 0; i < 120; i++)
+    {
+      nodes.push_back (Create<InternetNode> ());
+    }
+
+  // setup the grid itself: objects are layed out
+  // started from (-100,-100) with 20 objects per row, 
+  // the x interval between each object is 5 meters
+  // and the y interval between each object is 20 meters
+  GridTopology grid (-100, -100, 20, 5, 20);
+
+  // each object will be attached a static position.
+  grid.SetMobilityModel (StaticMobilityModel::cid);
+
+  // finalize the setup by attaching to each object
+  // in the input array a position and initializing
+  // this position with the calculated coordinates.
+  grid.LayoutRowFirst (nodes.begin (), nodes.end ());
+
+  // iterate our nodes and print their position.
+  for (std::vector<Ptr<Object> >::const_iterator j = nodes.begin ();
+       j != nodes.end (); j++)
+    {
+      Ptr<Object> object = *j;
+      Ptr<MobilityModel> position = object->QueryInterface<MobilityModel> (MobilityModel::iid);
+      NS_ASSERT (position != 0);
+      Position pos = position->Get ();
+      std::cout << "x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z << std::endl;
+    }
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-random-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,53 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include <vector>
+
+#include "ns3/ptr.h"
+#include "ns3/mobility-model.h"
+#include "ns3/mobility-model-notifier.h"
+#include "ns3/static-mobility-model.h"
+#include "ns3/random-topology.h"
+#include "ns3/default-value.h"
+#include "ns3/command-line.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+
+using namespace ns3;
+
+static void 
+CourseChange (Ptr<const MobilityModel> position)
+{
+  Position pos = position->Get ();
+  std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
+            << ", z=" << pos.z << std::endl;
+}
+
+int main (int argc, char *argv[])
+{
+  Bind ("RandomDiscPositionX", "100");
+  Bind ("RandomDiscPositionY", "50");
+  Bind ("RandomDiscPositionRho", "Uniform:0:30");
+
+  Bind ("RandomTopologyPositionType", "RandomDiscPosition");
+  Bind ("RandomTopologyMobilityType", "StaticMobilityModel");
+
+  CommandLine::Parse (argc, argv);
+
+  RandomTopology topology;
+
+  std::vector<Ptr<Object> > objects;
+  for (uint32_t i = 0; i < 10000; i++)
+    {
+      Ptr<MobilityModelNotifier> notifier = Create<MobilityModelNotifier> ();
+      notifier->RegisterListener (MakeCallback (&CourseChange));
+      objects.push_back (notifier);
+    }
+
+  topology.Layout (objects.begin (), objects.end ());
+
+  Simulator::StopAt (Seconds (100.0));
+
+  Simulator::Run ();
+  
+  return 0;
+}
--- a/samples/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/samples/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -18,7 +18,11 @@
     obj = create_ns_prog('main-test', 'main-test.cc')
     obj = create_ns_prog('main-simple', 'main-simple.cc',
                          deps=['node', 'internet-node', 'applications'])
-    #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'p2p'])
+    #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'point-to-point'])
     obj = create_ns_prog('main-default-value', 'main-default-value.cc',
-                         deps=['core', 'simulator', 'node', 'p2p'])
+                         deps=['core', 'simulator', 'node', 'point-to-point'])
+    obj = create_ns_prog('main-grid-topology', 'main-grid-topology.cc',
+                         deps=['core', 'simulator', 'mobility', 'internet-node'])
+    obj = create_ns_prog('main-random-topology', 'main-random-topology.cc',
+                         deps=['core', 'simulator', 'mobility'])
 
--- a/src/applications/onoff-application.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/applications/onoff-application.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -41,7 +41,7 @@
 static DataRateDefaultValue g_defaultRate ("OnOffApplicationDataRate", 
                                            "The data rate in on state for OnOffApplication",
                                            DataRate ("500kb/s"));
-static IntegerDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize", 
+static NumericDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize", 
                                                     "The size of packets sent in on state for OnOffApplication",
                                                     512, 1);
 // Constructors
--- a/src/applications/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/applications/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -1,10 +1,5 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
-
-def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-applications')
-
-
 def build(bld):
     obj = bld.create_obj('cpp', 'shlib')
     obj.name = 'ns3-applications'
--- a/src/common/buffer.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/buffer.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -31,6 +31,15 @@
 uint32_t Buffer::m_maxTotalAddStart = 0;
 uint32_t Buffer::m_maxTotalAddEnd = 0;
 
+Buffer::BufferDataList::~BufferDataList ()
+{
+  for (BufferDataList::iterator i = begin ();
+       i != end (); i++)
+    {
+      Buffer::Deallocate (*i);
+    }
+}
+
 struct Buffer::BufferData *
 Buffer::Allocate (uint32_t reqSize, uint32_t reqStart)
 {
@@ -440,6 +449,7 @@
 #ifdef RUN_SELF_TESTS
 
 #include "ns3/test.h"
+#include "ns3/random-variable.h"
 #include <iomanip>
 
 namespace ns3 {
@@ -501,14 +511,14 @@
   uint8_t bytes[] = {__VA_ARGS__};             \
   if (!EnsureWrittenBytes (buffer, n , bytes)) \
     {                                          \
-      ok = false;                              \
+      result = false;                          \
     }                                          \
   }
 
 bool
 BufferTest::RunTests (void)
 {
-  bool ok = true;
+  bool result = true;
   Buffer buffer;
   Buffer::Iterator i;
   buffer.AddAtStart (6);
@@ -555,7 +565,7 @@
   i.Prev (2);
   if (i.ReadNtohU16 () != 0xff00) 
     {
-      ok = false;
+      result = false;
     }
   i.Prev (2);
   i.WriteU16 (saved);
@@ -645,7 +655,7 @@
   buffer.RemoveAtEnd (8);
   if (buffer.GetSize () != 0) 
     {
-      ok = false;
+      result = false;
     }
 
   buffer = Buffer (6);
@@ -669,7 +679,31 @@
   i.Prev (100);
   i.WriteU8 (1, 100);
 
-  return ok;
+  // Bug #54
+  {
+    const uint32_t actualSize = 72602;
+    const uint32_t chunkSize = 67624;
+    UniformVariable bytesRng (0, 256);
+
+    Buffer inputBuffer;
+    Buffer outputBuffer;
+    
+    inputBuffer.AddAtEnd (actualSize);
+    {
+      Buffer::Iterator iter = inputBuffer.Begin ();
+      for (uint32_t i = 0; i < actualSize; i++)
+        iter.WriteU8 (static_cast<uint8_t> (bytesRng.GetValue ()));
+    }
+
+    outputBuffer.AddAtEnd (chunkSize);
+    Buffer::Iterator iter = outputBuffer.End ();
+    iter.Prev (chunkSize);
+    iter.Write (inputBuffer.PeekData (), chunkSize);
+
+    NS_TEST_ASSERT (memcmp (inputBuffer.PeekData (), outputBuffer.PeekData (), chunkSize) == 0);
+  }
+
+  return result;
 }
 
 
--- a/src/common/buffer.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/buffer.h	Fri Aug 03 08:29:24 2007 -0700
@@ -158,7 +158,7 @@
        * Write the data in buffer and avance the iterator position
        * by size bytes.
        */
-      inline void Write (uint8_t const*buffer, uint16_t size);
+      inline void Write (uint8_t const*buffer, uint32_t size);
       /**
        * \param start the start of the data to copy
        * \param end the end of the data to copy
@@ -336,7 +336,11 @@
       uint32_t m_dirtySize;
       uint8_t m_data[1];
   };
-  typedef std::vector<struct Buffer::BufferData*> BufferDataList;
+  class BufferDataList : public std::vector<struct Buffer::BufferData*>
+  {
+  public:
+    ~BufferDataList ();
+  };
 
   inline uint8_t *GetStart (void) const;
   static void Recycle (struct Buffer::BufferData *data);
@@ -621,7 +625,7 @@
   m_current += 8;
 }
 void 
-Buffer::Iterator::Write (uint8_t const*buffer, uint16_t size)
+Buffer::Iterator::Write (uint8_t const*buffer, uint32_t size)
 {
   uint8_t *current = m_data + GetIndex (size);
   memcpy (current, buffer, size);
--- a/src/common/packet-metadata.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/packet-metadata.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -37,6 +37,14 @@
 PacketMetadata::DataFreeList PacketMetadata::m_freeList;
 bool g_optOne = false;
 
+PacketMetadata::DataFreeList::~DataFreeList ()
+{
+  for (iterator i = begin (); i != end (); i++)
+    {
+      PacketMetadata::Deallocate (*i);
+    }
+}
+
 void 
 PacketMetadata::Enable (void)
 {
@@ -1369,13 +1377,13 @@
 {
   if (m_headerError)
     {
-      std::cout << "PacketMetadata header error. file=" << file 
+      Failure () << "PacketMetadata header error. file=" << file 
                 << ", line=" << line << std::endl;
       return false;
     }
   if (m_trailerError)
     {
-      std::cout << "PacketMetadata trailer error. file=" << file 
+      Failure () << "PacketMetadata trailer error. file=" << file 
                 << ", line=" << line << std::endl;
       return false;
     }
@@ -1395,20 +1403,20 @@
     }
   return true;
  error:
-  std::cout << "PacketMetadata error. file="<< file 
+  Failure () << "PacketMetadata error. file="<< file 
             << ", line=" << line << ", got:\"";
   for (std::list<int>::iterator i = m_prints.begin (); 
        i != m_prints.end (); i++)
     {
-      std::cout << *i << ", ";
+      Failure () << *i << ", ";
     }
-  std::cout << "\", expected: \"";
+  Failure () << "\", expected: \"";
   for (std::list<int>::iterator j = expected.begin ();
        j != expected.end (); j++)
     {
-      std::cout << *j << ", ";
+      Failure () << *j << ", ";
     }
-  std::cout << "\"" << std::endl;
+  Failure () << "\"" << std::endl;
   return false;
 }
 
@@ -1428,7 +1436,7 @@
   va_end (ap);
 
   m_printer.PrintForward ();
-  p.Print (std::cerr, m_printer);
+  p.Print (Failure (), m_printer);
   bool ok = Check (file, line, expected);
   CleanupPrints ();
   if (!ok)
@@ -1437,7 +1445,7 @@
     }
 
   m_printer.PrintBackward ();
-  p.Print (std::cerr, m_printer);
+  p.Print (Failure (), m_printer);
   expected.reverse ();
   ok = Check (file, line, expected);
   CleanupPrints ();
--- a/src/common/packet-metadata.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/packet-metadata.h	Fri Aug 03 08:29:24 2007 -0700
@@ -182,7 +182,11 @@
     uint32_t packetUid;
   };
 
-  typedef std::vector<struct Data *> DataFreeList;
+  class DataFreeList : public std::vector<struct Data *>
+  {
+  public:
+    ~DataFreeList ();
+  };
   
   PacketMetadata ();
   void DoAddHeader (uint32_t uid, uint32_t size);
--- a/src/common/trace-root.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/trace-root.h	Fri Aug 03 08:29:24 2007 -0700
@@ -148,7 +148,7 @@
  * information on where the trace source is located in the namespace tree.
  * In that example, if there are multiple nodes in this scenario, each
  * call to the MyTraceSink function would receive a different TraceContext,
- * each of which would contain a different NodeList::Index object.
+ * each of which would contain a different NodeList::NodeIndex object.
  *
  * It is important to understand exactly what an ns3::TraceContext
  * is. It is a container for a number of type instances. Each instance of
@@ -164,7 +164,7 @@
  * \code
  * void MyTraceSink (TraceContext const &context, Packet &packet)
  * {
- *   NodeList::Index index;
+ *   NodeList::NodeIndex index;
  *   context.Get (index);
  *   std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl;
  * }
--- a/src/common/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/common/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -1,8 +1,5 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
-def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-common')
-
 def build(bld):
     common = bld.create_obj('cpp', 'shlib')
     common.name = 'ns3-common'
@@ -27,6 +24,7 @@
         'trace-root.cc',
         'data-rate.cc',
         ]
+
     headers = bld.create_obj('ns3header')
     headers.source = [
         'buffer.h',
--- a/src/core/assert.cc	Fri Aug 03 08:23:23 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +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 "assert.h"
-
-namespace ns3 {
-
-void
-AssertBreakpoint (void)
-{
-  int *a = 0;
-  /**
-   * we test here to allow a debugger to change the value of
-   * the variable 'a' to allow the debugger to avoid the 
-   * subsequent segfault.
-   */
-  if (a == 0)
-    {
-      *a = 0;
-    }
-}
-
-}//namespace ns3
--- a/src/core/assert.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/assert.h	Fri Aug 03 08:29:24 2007 -0700
@@ -21,36 +21,12 @@
 #ifndef ASSERT_H
 #define ASSERT_H
 
-/**
- * \defgroup assert Assert
- * \brief assert functions and macros
- *
- * The assert macros are used to verify
- * at runtime that a certain condition is true. If it is
- * not true, the program halts. These checks are built
- * into the program only in debugging builds. They are
- * removed in optimized builds.
- */
-
-namespace ns3 {
-
-/**
- * \ingroup debugging
- *
- * When an NS_ASSERT cannot verify its condition, 
- * this function is called. This is where you should
- * be able to put a breakpoint with a debugger if
- * you want to catch assertions before the program 
- * halts.
- */
-void AssertBreakpoint (void);
-
-}//namespace ns3
-
 #ifdef NS3_ASSERT_ENABLE
 
 #include <iostream>
 
+#include "breakpoint.h"
+
 /**
  * \ingroup assert
  * \param condition condition to verifiy.
@@ -65,10 +41,10 @@
     {                                                           \
       if (!(condition))                                         \
         {                                                       \
-          std::cout << "assert failed. file=" << __FILE__ <<    \
+          std::cerr << "assert failed. file=" << __FILE__ <<    \
             ", line=" << __LINE__ << ", cond=\""#condition <<   \
             "\"" << std::endl;                                  \
-          ns3::AssertBreakpoint ();                             \
+          NS_BREAKPOINT ();                                     \
         }                                                       \
     }                                                           \
   while (false)
@@ -88,8 +64,8 @@
     {                                           \
       if (!(condition))                         \
         {                                       \
-          std::cout << message << std::endl;    \
-          ns3::AssertBreakpoint ();             \
+          std::cerr << message << std::endl;    \
+          NS_BREAKPOINT ();                     \
         }                                       \
     }                                           \
   while (false)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/breakpoint.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA, 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Author: Gustavo Carneiro <gjc@inescporto.pt>
+ */
+
+#include "breakpoint.h"
+#include "ns3/core-config.h"
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+
+namespace ns3 {
+
+#ifdef HAVE_SIGNAL_H
+
+void
+Breakpoint (void)
+{
+  raise (SIGTRAP);
+}
+
+#else
+
+void
+Breakpoint (void)
+{
+  int *a = 0;
+  /**
+   * we test here to allow a debugger to change the value of
+   * the variable 'a' to allow the debugger to avoid the 
+   * subsequent segfault.
+   */
+  if (a == 0)
+    {
+      *a = 0;
+    }
+}
+
+#endif // HAVE_SIGNAL_H
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/breakpoint.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INESC Porto, 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: Gustavo Carneiro <gjc@inescporto.pt>
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef BREAKPOINT_H
+#define BREAKPOINT_H
+
+namespace ns3 {
+
+/* Hacker macro to place breakpoints for selected machines.
+ * Actual use is strongly discouraged of course ;)
+ * Copied from GLib 2.12.9.
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+/**
+ * \ingroup debugging
+ *
+ * Inserts a breakpoint instruction (or equivalent system call) into
+ * the code for selected machines.  When an NS_ASSERT cannot verify its condition, 
+ * this macro is used. Falls back to calling
+ * AssertBreakpoint() for architectures where breakpoint assembly
+ * instructions are not supported.
+ */
+#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) && defined (__GNUC__) && __GNUC__ >= 2
+#  define NS_BREAKPOINT() \
+   do{ __asm__ __volatile__ ("int $03"); }while(false)
+#elif defined (_MSC_VER) && defined (_M_IX86)
+#  define NS_BREAKPOINT() \
+   do{ __asm int 3h }while(false)
+#elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2
+#  define NS_BREAKPOINT() \
+   do{ __asm__ __volatile__ ("bpt"); }while(false)
+#else	/* !__i386__ && !__alpha__ */
+#  define NS_BREAKPOINT()    ns3::BreakpointFallback ()
+#endif
+
+/**
+ * \brief fallback breakpoint function
+ *
+ * This function is used by the NS_BREAKPOINT() macro as a fallback
+ * for when breakpoint assembly instructions are not available.  It
+ * attempts to halt program execution either by a raising SIGTRAP, on
+ * unix systems, or by dereferencing a null pointer.
+ * 
+ * Normally you should not call this function directly.
+ */
+void BreakpointFallback (void);
+
+
+}//namespace ns3
+
+
+#endif /* BREAKPOINT_H */
--- a/src/core/debug.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/debug.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -24,6 +24,7 @@
 #include "debug.h"
 #include "assert.h"
 #include "ns3/core-config.h"
+#include "fatal-error.h"
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -88,7 +89,7 @@
         }
       if (!found)
         {
-          std::cout << "No debug component named=\"" << tmp << "\"" << std::endl;
+          NS_FATAL_ERROR ("No debug component named=\"" << tmp << "\"");
         }
       if (next == std::string::npos)
         {
--- a/src/core/debug.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/debug.h	Fri Aug 03 08:29:24 2007 -0700
@@ -110,7 +110,7 @@
     {                                           \
       if (g_debug.IsEnabled ())			\
         {                                       \
-          std::cout << msg << std::endl;        \
+          std::cerr << msg << std::endl;        \
         }                                       \
     }                                           \
   while (false)
@@ -125,7 +125,7 @@
 #define NS_DEBUG_UNCOND(msg)         \
   do                                 \
     {                                \
-      std::cout << msg << std::endl; \
+      std::cerr << msg << std::endl; \
     }                                \
   while (false)
 
--- a/src/core/default-value.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/default-value.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -26,7 +26,8 @@
 DefaultValueBase::DefaultValueBase (const std::string &name,
 				    const std::string &help)
   : m_name (name),
-    m_help (help)
+    m_help (help),
+    m_dirty (false)
 {}
 DefaultValueBase::~DefaultValueBase ()
 {}
@@ -41,9 +42,24 @@
   return m_help;
 }
 bool 
+DefaultValueBase::IsDirty (void) const
+{
+  return m_dirty;
+}
+void 
+DefaultValueBase::ClearDirtyFlag (void)
+{
+  m_dirty = false;
+}
+bool 
 DefaultValueBase::ParseValue (const std::string &value)
 {
-  return DoParseValue (value);
+  bool ok = DoParseValue (value);
+  if (ok)
+    {
+      m_dirty = true;
+    }
+  return ok;
 }
 std::string 
 DefaultValueBase::GetType (void) const
@@ -374,7 +390,7 @@
       ok = false;
     }
 
-  IntegerDefaultValue<int> i ("test-i", "help-i", -1);
+  NumericDefaultValue<int> i ("test-i", "help-i", -1);
   if (i.GetValue () != -1)
     {
       ok = false;
@@ -393,17 +409,20 @@
     {
       ok = false;
     }
-  IntegerDefaultValue<uint32_t> ui32 ("test-ui32", "help-ui32", 10);
+  NumericDefaultValue<uint32_t> ui32 ("test-ui32", "help-ui32", 10);
   if (ui32.GetType () != "uint32_t(0:4294967295)")
     {
       ok = false;
     }
-  IntegerDefaultValue<char> c ("test-c", "help-c", 10);
+  NumericDefaultValue<char> c ("test-c", "help-c", 10);
   if (c.GetValue () != 10)
     {
       ok = false;
     }
   Bind ("test-c", "257");  
+  NumericDefaultValue<float> x ("test-x", "help-x", 10.0);
+  NumericDefaultValue<double> y ("test-y", "help-y", 10.0);
+
 
   EnumDefaultValue<enum MyEnum> e ("test-e", "help-e",
 				   MY_ENUM_C, "C",
--- a/src/core/default-value.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/default-value.h	Fri Aug 03 08:29:24 2007 -0700
@@ -37,6 +37,19 @@
   virtual ~DefaultValueBase ();
   std::string GetName (void) const;
   std::string GetHelp (void) const;
+
+  /**
+   * \returns true if this value is dirty, false otherwise.
+   *
+   * A value becomes dirty when ParseValue is invoked
+   * and it successfully completes. Dirtyness indicates
+   * that the state of the value was changed by a user.
+   */
+  bool IsDirty (void) const;
+  /**
+   * Clear the dirty state.
+   */
+  void ClearDirtyFlag (void);
   // parse a matching parameter
   // return true in case of success, false otherwise.
   bool ParseValue (const std::string &value);
@@ -46,11 +59,14 @@
   DefaultValueBase (const std::string &name, 
 		    const std::string &help);
 private:
+  DefaultValueBase ();
+private:
   virtual bool DoParseValue (const std::string &value) = 0;
   virtual std::string DoGetType (void) const = 0;
   virtual std::string DoGetDefaultValue (void) const = 0;
   std::string m_name;
   std::string m_help;
+  bool m_dirty;
 };
 
 class DefaultValueList
@@ -119,7 +135,7 @@
 };
 
 /**
- * \brief An Integer variable for ns3::Bind
+ * \brief A Numeric variable for ns3::Bind
  * \ingroup config
  *
  * Every instance of this type is automatically 
@@ -127,7 +143,7 @@
  * by ns3::Bind. 
  */
 template <typename T>
-class IntegerDefaultValue : public DefaultValueBase
+class NumericDefaultValue : public DefaultValueBase
 {
 public:
   /**
@@ -141,7 +157,7 @@
    * of values which can be stored and retrieved from the underlying
    * type.
    */
-  IntegerDefaultValue (std::string name,
+  NumericDefaultValue (std::string name,
 		       std::string help,
 		       T defaultValue);
   /**
@@ -153,7 +169,7 @@
    * \param minValue the minimum value which can be set
    *        in this variable
    */
-  IntegerDefaultValue (std::string name,
+  NumericDefaultValue (std::string name,
 		       std::string help,
 		       T defaultValue,
 		       T minValue);
@@ -169,7 +185,7 @@
    * \param maxValue the maximum value which can be set in this
    *        variable.
    */
-  IntegerDefaultValue (std::string name,
+  NumericDefaultValue (std::string name,
 		       std::string help,
 		       T defaultValue,
 		       T minValue,
@@ -335,7 +351,7 @@
 
 
 template <typename T>
-IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
+NumericDefaultValue<T>::NumericDefaultValue (std::string name,
 					     std::string help,
 					     T defaultValue)
   : DefaultValueBase (name, help),
@@ -348,7 +364,7 @@
   NS_ASSERT (m_minValue < m_maxValue);
 }
 template <typename T>
-IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
+NumericDefaultValue<T>::NumericDefaultValue (std::string name,
 					     std::string help,
 					     T defaultValue,
 					     T minValue)
@@ -364,7 +380,7 @@
 	     m_defaultValue >= m_minValue);
 }
 template <typename T>
-IntegerDefaultValue<T>::IntegerDefaultValue (std::string name,
+NumericDefaultValue<T>::NumericDefaultValue (std::string name,
 					     std::string help,
 					     T defaultValue,
 					     T minValue,
@@ -383,7 +399,7 @@
 
 template <typename T>
 void 
-IntegerDefaultValue<T>::SetValue (T v)
+NumericDefaultValue<T>::SetValue (T v)
 {
   NS_ASSERT (v <= m_maxValue &&
 	     v >= m_minValue);
@@ -392,14 +408,14 @@
 
 template <typename T>
 T
-IntegerDefaultValue<T>::GetValue (void) const
+NumericDefaultValue<T>::GetValue (void) const
 {
   return m_value;
 }
 
 template <typename T>
 bool
-IntegerDefaultValue<T>::DoParseValue (const std::string &value)
+NumericDefaultValue<T>::DoParseValue (const std::string &value)
 {
   std::istringstream iss;
   iss.str (value);
@@ -414,7 +430,7 @@
 
 template <typename T>
 std::string
-IntegerDefaultValue<T>::DoGetType (void) const
+NumericDefaultValue<T>::DoGetType (void) const
 {
   std::ostringstream oss;
   oss << TypeNameGet<T> () << "("
@@ -425,7 +441,7 @@
 
 template <typename T>
 std::string
-IntegerDefaultValue<T>::DoGetDefaultValue (void) const
+NumericDefaultValue<T>::DoGetDefaultValue (void) const
 {
   std::ostringstream oss;
   oss << m_defaultValue;
--- a/src/core/fatal-error.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/fatal-error.h	Fri Aug 03 08:29:24 2007 -0700
@@ -21,7 +21,7 @@
 #ifndef FATAL_ERROR_H
 #define FATAL_ERROR_H
 
-#include "assert.h"
+#include "breakpoint.h"
 #include <iostream>
 
 /**
@@ -32,15 +32,15 @@
  *
  * When this macro is hit at runtime, the user-specified 
  * error message is output and the program is halted by calling
- * the ns3::AssertBreakpoint function. This macro is enabled
+ * the NS_DEBUG_BREAKPOINT macro. This macro is enabled
  * unconditionally in all builds, including debug and optimized 
  * builds.
  */
 #define NS_FATAL_ERROR(msg)				\
   do                                                    \
     {                                                   \
-      std::cout << msg << std::endl;			\
-      ns3::AssertBreakpoint ();                         \
+      std::cerr << msg << std::endl;			\
+      NS_BREAKPOINT ();                                 \
     }                                                   \
   while (false)
 
--- a/src/core/ptr.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/ptr.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -28,9 +28,14 @@
 
 namespace ns3 {
 
+template <typename T>
+void Foo (void) {}
+
+
 class NoCount : public Object
 {
 public:
+  NoCount (void (*fn) (void));
   NoCount (Callback<void> cb);
   ~NoCount ();
   void Nothing (void) const;
@@ -292,12 +297,22 @@
     callback ();
   }
 
+
 #if 0
   // as expected, fails compilation.
   {
     Ptr<const Object> p = Create<NoCount> (cb);
     Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
   }
+  // local types are not allowed as arguments to a template.
+  {
+    class B
+    {
+    public:
+      B () {}
+    };
+    Foo<B> ();
+  }
 #endif
   
 
--- a/src/core/ptr.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/ptr.h	Fri Aug 03 08:29:24 2007 -0700
@@ -22,6 +22,7 @@
 #ifndef PTR_H
 #define PTR_H
 
+#include <iostream>
 #include <stdint.h>
 #include "assert.h"
 
@@ -64,7 +65,7 @@
   template <typename U>
   friend U *PeekPointer (const Ptr<U> &p);
 
-  void Acquire (void) const;
+  inline void Acquire (void) const;
 public:
   /**
    * Create an empty smart pointer
@@ -80,7 +81,16 @@
    * same, so that object is deleted if no more references to it
    * remain.
    */
-  Ptr (T *ptr);
+  Ptr (T *ptr);  
+  /**
+   * \param ptr raw pointer to manage
+   * \param ref if set to true, this method calls Ref, otherwise,
+   *        it does not call Ref.
+   *    
+   * Create a smart pointer which points to the object pointed to by
+   * the input raw pointer ptr.
+   */
+  Ptr (T *ptr, bool ref);
   Ptr (Ptr const&o);
   // allow conversions from T to T const.
   template <typename U>
@@ -143,6 +153,9 @@
 template <typename T>
 T * GetPointer (const Ptr<T> &p);
 
+template <typename T>
+std::ostream &operator << (std::ostream &, const Ptr<T> &p);
+
 
 // allow if (sp == 0)
 template <typename T1, typename T2>
@@ -184,10 +197,10 @@
 };
 
 template <typename T>
-struct EventMemberImplTraits;
+struct EventMemberImplObjTraits;
 
 template <typename T>
-struct EventMemberImplTraits<Ptr<T> >
+struct EventMemberImplObjTraits<Ptr<T> >
 {
   static T &GetReference (Ptr<T> p) {
     return *PeekPointer (p);
@@ -290,6 +303,13 @@
   return p.m_ptr;
 }
 
+template <typename T>
+std::ostream &operator << (std::ostream &os, const Ptr<T> &p)
+{
+  os << PeekPointer (p);
+  return os;
+}
+
 template <typename T1, typename T2>
 bool 
 operator == (Ptr<T1> const &lhs, T2 const *rhs)
@@ -368,6 +388,16 @@
 }
 
 template <typename T>
+Ptr<T>::Ptr (T *ptr, bool ref) 
+  : m_ptr (ptr)
+{
+  if (ref)
+    {
+      Acquire ();
+    }
+}
+
+template <typename T>
 Ptr<T>::Ptr (Ptr const&o) 
   : m_ptr (PeekPointer (o))
 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/random-variable-default-value.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,138 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "random-variable-default-value.h"
+#include "ns3/debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("RandomVariableDefaultValue");
+
+namespace ns3 {
+
+RandomVariableDefaultValue::RandomVariableDefaultValue (std::string name,
+							std::string help,
+							std::string defaultValue)
+  : DefaultValueBase (name, help),
+    m_defaultValue (defaultValue),
+    m_value (defaultValue)
+{
+  if (!Parse (defaultValue, false, 0))
+    {
+      NS_FATAL_ERROR ("Invalid Random Variable specification: " << defaultValue);
+    }
+  DefaultValueList::Add (this);
+}
+
+RandomVariable *
+RandomVariableDefaultValue::GetCopy (void)
+{
+  RandomVariable *variable;
+  bool ok;
+  ok = Parse (m_value, true, &variable);
+  NS_ASSERT (ok);
+  return variable;
+}
+double
+RandomVariableDefaultValue::ReadAsDouble (std::string value, bool &ok)
+{
+  double v;
+  std::istringstream iss;
+  iss.str (value);
+  iss >> v;
+  ok = !iss.bad () && !iss.fail ();
+  return v;
+}
+bool
+RandomVariableDefaultValue::Parse (const std::string &value, 
+				   bool mustCreate, RandomVariable **pVariable)
+{
+  std::string::size_type pos = value.find_first_of(":");
+  if (pos == std::string::npos)
+    {
+      return false;
+    }
+  bool ok;
+  std::string type = value.substr (0, pos);
+  std::string v = value.substr (pos+1, std::string::npos);
+  if (type == "Constant")
+    {
+      double constant = ReadAsDouble (v, ok);
+      if (mustCreate)
+	{
+          NS_DEBUG ("create Constant constant=" << constant);
+	  *pVariable = new ConstantVariable (constant);
+	}
+      else
+        {
+          NS_DEBUG ("parse  Constant constant=" << constant);
+        }
+      return ok;
+    }
+  else if (type == "Uniform")
+    {
+      std::string::size_type maxPos = v.find_first_of(":");
+      if (maxPos == std::string::npos)
+	{
+	  return false;
+	}
+      std::string min = v.substr (0, maxPos);
+      std::string max = v.substr (maxPos + 1, std::string::npos);
+      double minVal;
+      double maxVal;
+      minVal = ReadAsDouble (min, ok);
+      maxVal = ReadAsDouble (max, ok);
+      if (mustCreate)
+	{
+          NS_DEBUG ("create Uniform min=" << min << ", max=" << max);
+	  *pVariable = new UniformVariable (minVal, maxVal);
+	}
+      else
+        {
+          NS_DEBUG ("parse  Uniform min=" << min << ", max=" << max);
+        }
+      return ok;
+    }
+  else
+    {
+      // XXX parse other types of distributions.
+      return false;
+    }
+}
+bool 
+RandomVariableDefaultValue::DoParseValue (const std::string &value)
+{
+  bool ok = Parse (value, false, 0);
+  if (ok)
+    {
+      m_value = value;
+    }
+  return ok;
+}
+std::string 
+RandomVariableDefaultValue::DoGetType (void) const
+{
+  return "(Uniform:min:max|Constant:cst)";
+}
+std::string 
+RandomVariableDefaultValue::DoGetDefaultValue (void) const
+{
+  return m_defaultValue;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/random-variable-default-value.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,50 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 RANDOM_VARIABLE_DEFAULT_VALUE_H
+#define RANDOM_VARIABLE_DEFAULT_VALUE_H
+
+#include "random-variable.h"
+#include "default-value.h"
+
+namespace ns3 {
+
+class RandomVariableDefaultValue : public DefaultValueBase
+{
+ public:
+  RandomVariableDefaultValue (std::string name,
+			      std::string help,
+			      std::string defaultValue);
+
+  RandomVariable *GetCopy (void);
+private:
+  bool Parse (const std::string &value, bool mustCreate, RandomVariable **pVariable);
+  double ReadAsDouble (const std::string value, bool &ok);
+  virtual bool DoParseValue (const std::string &value);
+  virtual std::string DoGetType (void) const;
+  virtual std::string DoGetDefaultValue (void) const;
+
+  std::string m_defaultValue;
+  std::string m_value;
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_VARIABLE_DEFAULT_VALUE_H */
--- a/src/core/random-variable.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/random-variable.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -108,8 +108,8 @@
 {
   if (RandomVariable::globalSeedSet)
     {
-      cout << "Random number generator already initialized!" << endl;
-      cout << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
+      cerr << "Random number generator already initialized!" << endl;
+      cerr << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
       return;
     }
   RandomVariable::globalSeed[0] = s0;
@@ -537,7 +537,7 @@
       ValueCDF& current = emp[i];
       if (current.value < prior.value || current.cdf < prior.cdf)
         { // Error
-          cout << "Empirical Dist error,"
+          cerr << "Empirical Dist error,"
                << " current value " << current.value
                << " prior value "   << prior.value
                << " current cdf "   << current.cdf
@@ -684,6 +684,43 @@
   return z;
 }
 
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// TriangularVariable methods
+TriangularVariable::TriangularVariable() 
+  : m_min(0), m_max(1), m_mode(0.5) { }
+  
+TriangularVariable::TriangularVariable(double s, double l, double mean) 
+  : m_min(s), m_max(l), m_mode(3.0*mean-s-l) { }
+  
+TriangularVariable::TriangularVariable(const TriangularVariable& c) 
+  : RandomVariable(c), m_min(c.m_min), m_max(c.m_max), m_mode(c.m_mode) { }
+
+double TriangularVariable::GetValue()
+{
+  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) );
+  else
+    return m_max - sqrt( (1-u) * (m_max - m_min) * (m_max - m_mode) );
+}
+
+RandomVariable* TriangularVariable::Copy() const
+{
+  return new TriangularVariable(*this);
+}
+
+double TriangularVariable::GetSingleValue(double s, double l, double mean)
+{
+  double mode = 3.0*mean-s-l;
+  double u = m_static_generator->RandU01();
+  if(u <= (mode - s) / (l - s) )
+    return s + sqrt(u * (l - s) * (mode - s) );
+  else
+    return l - sqrt( (1-u) * (l - s) * (l - mode) );
+}
+
+
 }//namespace ns3
 
 
--- a/src/core/random-variable.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/random-variable.h	Fri Aug 03 08:29:24 2007 -0700
@@ -737,6 +737,50 @@
   double m_sigma;
 };
 
+/**
+ * \brief Triangularly Distributed random var
+ * \ingroup randomvariable
+ * 
+ * This distribution is a triangular distribution.  The probablility density
+ * is in the shape of a triangle.
+ */
+class TriangularVariable : public RandomVariable {
+public:
+  /**
+   * Creates a triangle distribution random number generator in the
+   * range [0.0 .. 1.0), with mean of 0.5
+   */
+  TriangularVariable();
+
+  /**
+   * Creates a triangle distribution random number generator with the specified
+   * range
+   * \param s Low end of the range
+   * \param l High end of the range
+   * \param mean mean of the distribution
+   */
+  TriangularVariable(double s, double l, double mean);
+
+  TriangularVariable(const TriangularVariable& c);
+  
+  /**
+   * \return A value from this distribution
+   */
+  virtual double GetValue();
+  virtual RandomVariable*  Copy() const;
+public:
+  /**
+   * \param s Low end of the range
+   * \param l High end of the range
+   * \return A triangularly distributed random number between s and l
+   */
+  static double GetSingleValue(double s, double l, double mean);
+private:
+  double m_min;
+  double m_max;
+  double m_mode;  //easier to work with the mode internally instead of the mean
+                  //they are related by the simple: mean = (min+max+mode)/3
+};
 
 }//namespace ns3
 #endif
--- a/src/core/rng-stream.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/rng-stream.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -269,11 +269,11 @@
     }
     for (i = 3; i < 6; ++i) {
         if (seed[i] >= m2) {
-	  cout << "Seed[" << i << "] = " << seed[i] << endl; 
-            cerr << "*****************************************\n\n"
-                 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
-                 << "\n\n*****************************************\n\n";
-            return (false);
+	  cerr << "Seed[" << i << "] = " << seed[i] << endl; 
+          cerr << "*****************************************\n\n"
+               << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
+               << "\n\n*****************************************\n\n";
+          return (false);
         }
     }
     if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
--- a/src/core/test.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/test.h	Fri Aug 03 08:29:24 2007 -0700
@@ -130,8 +130,8 @@
     if (!(assertion))                                   \
       {                                                 \
         Failure () << __FILE__ << ":" <<__LINE__        \
-                   << ": assertion `" << (assertion)    \
-                   << "'failed." << std::endl;          \
+                   << ": assertion `" << #assertion     \
+                   << "' failed." << std::endl;         \
         result = false;                                 \
       }
 
--- a/src/core/type-name.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/type-name.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -19,6 +19,8 @@
 DEF_TYPE (int16_t);
 DEF_TYPE (int32_t);
 DEF_TYPE (int64_t);
+DEF_TYPE (float);
+DEF_TYPE (double);
 
 
 }//namespace ns3
--- a/src/core/type-name.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/type-name.h	Fri Aug 03 08:29:24 2007 -0700
@@ -26,6 +26,8 @@
 DEF_TYPE (int16_t);
 DEF_TYPE (int32_t);
 DEF_TYPE (int64_t);
+DEF_TYPE (float);
+DEF_TYPE (double);
 
 #undef DEF_TYPE
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/type-traits.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,26 @@
+#ifndef TYPE_TRAITS_H
+#define TYPE_TRAITS_H
+
+template <typename T>
+struct TypeTraits;
+
+template <typename T>
+struct TypeTraits
+{
+  typedef T ReferencedType;
+};
+
+template <typename T>
+struct TypeTraits<const T &>
+{
+  typedef T ReferencedType;
+};
+
+template <typename T>
+struct TypeTraits<T &>
+{
+  typedef T ReferencedType;
+};
+
+
+#endif /* TYPE_TRAITS_H */
--- a/src/core/uid-manager.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/uid-manager.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -20,6 +20,7 @@
  */
 #include "uid-manager.h"
 #include "ns3/fatal-error.h"
+#include "ns3/assert.h"
 
 
 namespace ns3 {
--- a/src/core/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/core/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -3,8 +3,6 @@
 
 
 def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-core')
-
     e = conf.create_header_configurator()
     e.mandatory = False
     e.name = 'stdlib.h'
@@ -17,6 +15,12 @@
     e.define = 'HAVE_GETENV'
     e.run()
 
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'signal.h'
+    e.define = 'HAVE_SIGNAL_H'
+    e.run()
+
     conf.write_config_header('ns3/core-config.h')
 
 
@@ -28,7 +32,7 @@
     core.source = [
         'callback-test.cc',
         'debug.cc',
-        'assert.cc',
+        'breakpoint.cc',
         'ptr.cc',
         'object.cc',
         'test.cc',
@@ -39,6 +43,7 @@
         'command-line.cc',
         'type-name.cc',
         'component-manager.cc',
+        'random-variable-default-value.cc',
         ]
 
     if sys.platform == 'win32':
@@ -59,6 +64,7 @@
         'object.h',
         'debug.h',
         'assert.h',
+        'breakpoint.h',
         'fatal-error.h',
         'test.h',
         'random-variable.h',
@@ -67,5 +73,7 @@
         'command-line.h',
         'type-name.h',
         'component-manager.h',
+        'type-traits.h',
+        'random-variable-default-value.h',
         ]
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/backoff.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include "backoff.h"
+
+namespace ns3 {
+
+Backoff::Backoff() 
+{
+  m_slotTime = MicroSeconds(1);
+  m_minSlots = 1;
+  m_maxSlots = 1000;
+  m_ceiling = 10;
+  m_maxRetries = 1000;
+
+  ResetBackoffTime();
+}
+
+Backoff::Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots,
+                 uint32_t ceiling, uint32_t maxRetries)
+{
+  m_slotTime = slotTime;
+  m_minSlots = minSlots;
+  m_maxSlots = maxSlots;
+  m_ceiling = ceiling;
+  m_maxRetries = maxRetries;
+}  
+
+Time
+Backoff::GetBackoffTime (void)
+{
+  Time backoff;
+  uint32_t ceiling;
+
+  if ((m_ceiling > 0) &&(m_numBackoffRetries > m_ceiling))
+    ceiling = m_ceiling;
+  else
+    ceiling = m_numBackoffRetries;
+
+  uint32_t minSlot = m_minSlots;
+  uint32_t maxSlot = (uint32_t)pow(2, ceiling) - 1;
+  if (maxSlot > m_maxSlots)
+    maxSlot = m_maxSlots;
+
+  uint32_t backoffSlots = 
+    (uint32_t)UniformVariable::GetSingleValue(minSlot, maxSlot);
+
+  backoff = Scalar(backoffSlots) * m_slotTime;
+  return (backoff);
+}
+
+void Backoff::ResetBackoffTime (void)
+{
+  m_numBackoffRetries = 0;
+}
+
+bool Backoff::MaxRetriesReached(void) {
+  return (m_numBackoffRetries >= m_maxRetries);
+}
+
+void Backoff::IncrNumRetries(void) {
+  m_numBackoffRetries++;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/backoff.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,87 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ *
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca
+ * Derived from the p2p net device file
+Transmi */
+
+#ifndef BACKOFF_H
+#define BACKOFF_H
+
+#include <stdint.h>
+#include "ns3/nstime.h"
+#include "ns3/random-variable.h"
+
+namespace ns3 {
+
+  /**
+   * \brief The backoff class is used for calculating backoff times
+   * when many net devices can write to the same channel
+   *
+   */
+
+class Backoff {
+public:
+  uint32_t m_minSlots; // Minimum number of backoff slots (when
+                       // multiplied by m_slotTime, determines minimum
+                       // backoff time)
+  uint32_t m_maxSlots; // Maximim number of backoff slots (when
+                       // multiplied by m_slotTime, determines
+                       // maximum backoff time)
+  uint32_t m_ceiling;  // Caps the exponential function when the
+                       // number of retries reaches m_ceiling
+  uint32_t m_maxRetries; // Maximum number of transmission retries
+                         // before the packet is dropped.
+  Time     m_slotTime; // Length of one slot. A slot time, it usually
+                       // the packet transmission time, if the packet
+                       // size is fixed.
+
+  Backoff();
+  Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots, 
+          uint32_t ceiling, uint32_t maxRetries);
+
+  /**
+   * \return The amount of time that the net device should wait before
+   * trying to retransmit the packet
+   */
+  Time GetBackoffTime();
+  /**
+   * Indicates to the backoff object that the last packet was
+   * successfully transmitted and that the number of retries should be
+   * reset to 0.
+   */
+  void ResetBackoffTime();
+  /**
+   * \return True if the maximum number of retries has been reached
+   */
+  bool MaxRetriesReached();
+  /**
+   * Increments the number of retries by 1.
+   */
+  void IncrNumRetries();
+
+private:
+  uint32_t m_numBackoffRetries; // Number of times that the
+                                // transmitter has tried to
+                                // unsuccessfully transmit the current
+                                // packet
+};
+
+}; // namespace ns3
+
+#endif // BACKOFF_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-channel.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,371 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include "csma-cd-channel.h"
+#include "csma-cd-net-device.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("CsmaCdChannel");
+
+namespace ns3 {
+
+CsmaCdDeviceRec::CsmaCdDeviceRec()
+{
+  active = false;
+}
+
+CsmaCdDeviceRec::CsmaCdDeviceRec(Ptr<CsmaCdNetDevice> device)
+{
+  devicePtr = device; 
+  active = true;
+}
+
+bool
+CsmaCdDeviceRec::IsActive() {
+  return active;
+}
+
+
+//
+// By default, you get a channel with the name "CsmaCd Channel" that 
+// has an "infitely" fast transmission speed and zero delay.
+CsmaCdChannel::CsmaCdChannel()
+: 
+  Channel ("CsmaCd Channel"), 
+  m_bps (DataRate(0xffffffff)),
+  m_delay (Seconds(0))
+{
+  NS_DEBUG("CsmaCdChannel::CsmaCdChannel ()");
+  Init();
+}
+
+CsmaCdChannel::CsmaCdChannel(
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel ("CsmaCd Channel"), 
+  m_bps (bps),
+  m_delay (delay)
+{
+  NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << Channel::GetName() 
+    << ", " << bps.GetBitRate() << ", " << delay << ")");
+  Init();
+}
+
+CsmaCdChannel::CsmaCdChannel(
+  const std::string& name,
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel (name),
+  m_bps (bps), 
+  m_delay (delay)
+{
+  NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << name << ", " << 
+           bps.GetBitRate() << ", " << delay << ")");
+  Init();
+}
+
+void CsmaCdChannel::Init() {
+  m_state = IDLE;
+  m_deviceList.clear();
+}
+
+int32_t
+CsmaCdChannel::Attach(Ptr<CsmaCdNetDevice> device)
+{
+  NS_DEBUG("CsmaCdChannel::Attach (" << device << ")");
+  NS_ASSERT(device != 0);
+
+  CsmaCdDeviceRec rec(device);
+  
+  m_deviceList.push_back(rec);
+  return (m_deviceList.size() - 1);
+}
+
+bool
+CsmaCdChannel::Reattach(Ptr<CsmaCdNetDevice> device)
+{
+  NS_DEBUG("CsmaCdChannel::Reattach (" << device << ")");
+  NS_ASSERT(device != 0);
+
+  std::vector<CsmaCdDeviceRec>::iterator it;
+  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
+    {
+      if (it->devicePtr == device) 
+        {
+          if (!it->active) 
+            {
+              it->active = true;
+              return true;
+            } 
+          else 
+            {
+              return false;
+            }
+        }
+    }
+  return false;
+}
+
+bool
+CsmaCdChannel::Reattach(uint32_t deviceId)
+{
+  NS_DEBUG("CsmaCdChannel::Reattach (" << deviceId << ")");
+  if (deviceId < m_deviceList.size())
+    {
+      return false;
+    }
+
+  if (m_deviceList[deviceId].active)
+    {
+      return false;
+    } 
+  else 
+    {
+      m_deviceList[deviceId].active = true;
+      return true;
+    }
+}
+
+bool
+CsmaCdChannel::Detach(uint32_t deviceId)
+{
+  NS_DEBUG("CsmaCdChannel::Detach (" << deviceId << ")");
+
+  if (deviceId < m_deviceList.size())
+    {
+      if (!m_deviceList[deviceId].active)
+        {
+          NS_DEBUG("CsmaCdChannel::Detach Device is already detached (" 
+                   << deviceId << ")");
+          return false;
+        }
+
+      m_deviceList[deviceId].active = false;
+      if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId))
+        {
+          NS_DEBUG("CsmaCdChannel::Detach Device is currently"
+                   << "transmitting (" << deviceId << ")");
+          // Here we will need to place a warning in the packet
+        }
+
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+bool
+CsmaCdChannel::Detach(Ptr<CsmaCdNetDevice> device)
+{
+  NS_DEBUG("CsmaCdChannel::Detach (" << device << ")");
+  NS_ASSERT(device != 0);
+
+  std::vector<CsmaCdDeviceRec>::iterator it;
+  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
+    {
+      if ((it->devicePtr == device) && (it->active)) 
+        {
+          it->active = false;
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+CsmaCdChannel::TransmitStart(Packet& p, uint32_t srcId)
+{
+  NS_DEBUG ("CsmaCdChannel::TransmitStart (" << &p << ", " << srcId 
+            << ")");
+  NS_DEBUG ("CsmaCdChannel::TransmitStart (): UID is " << 
+            p.GetUid () << ")");
+
+  if (m_state != IDLE)
+    {
+      NS_DEBUG("CsmaCdChannel::TransmitStart (): state is not IDLE");
+      return false;
+    }
+
+  if (!IsActive(srcId))
+    {
+      NS_DEBUG("CsmaCdChannel::TransmitStart (): ERROR: Seclected "
+               << "source is not currently attached to network");
+      return false;
+    }
+
+  NS_DEBUG("CsmaCdChannel::TransmitStart (): switch to TRANSMITTING");
+  m_currentPkt = p;
+  m_currentSrc = srcId;
+  m_state = TRANSMITTING;
+  return true;
+}
+
+bool
+CsmaCdChannel::IsActive(uint32_t deviceId) 
+{
+    return (m_deviceList[deviceId].active);
+}
+
+bool
+CsmaCdChannel::TransmitEnd()
+{
+  NS_DEBUG("CsmaCdChannel::TransmitEnd (" << &m_currentPkt << ", " 
+           << m_currentSrc << ")");
+  NS_DEBUG("CsmaCdChannel::TransmitEnd (): UID is " << 
+            m_currentPkt.GetUid () << ")");
+
+  NS_ASSERT(m_state == TRANSMITTING);
+  m_state = PROPAGATING;
+
+  bool retVal = true;
+
+  if (!IsActive(m_currentSrc)) {
+    NS_DEBUG("CsmaCdChannel::TransmitEnd (): ERROR: Seclected source "
+             << "was detached before the end of the transmission");
+    retVal = false;
+  }
+
+  NS_DEBUG ("CsmaCdChannel::TransmitEnd (): Schedule event in " << 
+            m_delay.GetSeconds () << "sec");
+
+  Simulator::Schedule (m_delay,
+                       &CsmaCdChannel::PropagationCompleteEvent,
+                       this);
+  return retVal;
+}
+
+void
+CsmaCdChannel::PropagationCompleteEvent()
+{
+  NS_DEBUG("CsmaCdChannel::PropagationCompleteEvent (" 
+           << &m_currentPkt << ")");
+  NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): UID is " << 
+            m_currentPkt.GetUid () << ")");
+
+  NS_ASSERT(m_state == PROPAGATING);
+  m_state = IDLE;
+
+  NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): Receive");
+  
+  std::vector<CsmaCdDeviceRec>::iterator it;
+  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
+    {
+      if (it->IsActive())
+      {
+        it->devicePtr->Receive (m_currentPkt);
+      }
+    }
+}
+
+
+uint32_t 
+CsmaCdChannel::GetNumActDevices (void)
+{
+  int numActDevices = 0;
+  std::vector<CsmaCdDeviceRec>::iterator it;
+  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
+    {
+      if (it->active)
+        {
+          numActDevices++;
+        }
+    }
+  return numActDevices;
+}
+
+// This is not the number of active devices. This is the total number
+// of devices even if some were detached after.
+uint32_t 
+CsmaCdChannel::GetNDevices (void) const
+{
+  return (m_deviceList.size());
+}
+
+Ptr<NetDevice>
+CsmaCdChannel::GetDevice (uint32_t i) const
+{
+  Ptr< CsmaCdNetDevice > netDevice;
+
+  netDevice = m_deviceList[i].devicePtr;
+  return netDevice;
+}
+
+int32_t
+CsmaCdChannel::GetDeviceNum (Ptr<CsmaCdNetDevice> device)
+{
+  std::vector<CsmaCdDeviceRec>::iterator it;
+  int i = 0;
+  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
+    {
+      if (it->devicePtr == device)
+        {
+          if (it->active) 
+            {
+              return i;
+            } 
+          else 
+            {
+              return -2;
+            }
+        }
+      i++;
+    }
+  return -1;
+}
+
+bool 
+CsmaCdChannel::IsBusy (void)
+{
+  if (m_state == IDLE) 
+    {
+      return false;
+    } 
+  else 
+    {
+      return true;
+    }
+}
+
+DataRate
+CsmaCdChannel::GetDataRate (void)
+{
+  return m_bps;
+}
+
+Time
+CsmaCdChannel::GetDelay (void)
+{
+  return m_delay;
+}
+
+WireState
+CsmaCdChannel::GetState(void)
+{
+  return m_state;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-channel.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,307 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ *
+ * 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: Emmanuelle Laprise<emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#ifndef CSMA_CD_CHANNEL_H
+#define CSMA_CD_CHANNEL_H
+
+#include "ns3/channel.h"
+#include "ns3/ptr.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+namespace ns3 {
+
+class CsmaCdNetDevice;
+
+  /**
+   * \brief CsmaCdNetDevice Record 
+   *
+   * Stores the information related to each net device that is
+   * connected to the channel. 
+   */
+  class CsmaCdDeviceRec {
+  public:
+    Ptr< CsmaCdNetDevice > devicePtr; /// Pointer to the net device
+    bool                       active;    /// Is net device enabled to TX/RX
+
+    CsmaCdDeviceRec();
+    CsmaCdDeviceRec(Ptr< CsmaCdNetDevice > device);
+    /*
+     * \return If the net device pointed to by the devicePtr is active
+     * and ready to RX/TX.
+     */
+    bool IsActive();                   
+  };
+
+  /**
+   * Current state of the channel
+   */ 
+  enum WireState
+    {
+      IDLE,          /**< Channel is IDLE, no packet is being
+                        transmitted */
+      TRANSMITTING,  /**< Channel is BUSY, a packet is being written
+                        by a net device */
+      PROPAGATING    /**< Channel is BUSY, packet is propagating to
+                        all attached net devices */
+    };
+
+/**
+ * \brief CsmaCd Channel.
+ *
+ * This class represents a simple Csma/Cd channel that can be used
+ * when many nodes are connected to one wire. It uses a single busy
+ * flag to indicate if the channel is currently in use. It does not
+ * take into account the distances between stations or the speed of
+ * light to determine collisions.
+ *
+ * Each net device must query the state of the channel and make sure
+ * that it is IDLE before writing a packet to the channel.
+ *
+ * When the channel is instaniated, the constructor takes parameters
+ * for a single speed, in bits per second, and a speed-of-light delay
+ * time as a Time object.  When a net device is attached to a channel,
+ * it is assigned a device ID, this is in order to facilitate the
+ * check that makes sure that a net device that is trying to send a
+ * packet to the channel is really connected to this channel
+ *
+ */
+class CsmaCdChannel : public Channel {
+public:
+  /**
+   * \brief Create a CsmaCdChannel
+   *
+   * By default, you get a channel with the name "CsmaCd Channel" that
+   * has an "infitely" fast transmission speed and zero delay.
+   */
+  CsmaCdChannel ();
+  
+  /**
+   * \brief Create a CsmaCdChannel
+   *
+   * \param bps The bitrate of the channel
+   * \param delay Transmission delay through the channel
+   */  
+  CsmaCdChannel (const DataRate& bps, const Time& delay);
+  
+  /**
+   * \brief Create a CsmaCdChannel
+   *
+   * \param name the name of the channel for identification purposes
+   * \param bps The bitrate of the channel
+   * \param delay Transmission delay through the channel
+   */
+  CsmaCdChannel (const std::string& name,
+                     const DataRate& bps, const Time& delay);
+
+  /**
+   * \brief Attach a given netdevice to this channel
+   *
+   * \param device Device pointer to the netdevice to attach to the channel
+   * \return The assigned device number
+   */
+  int32_t Attach (Ptr<CsmaCdNetDevice> device);
+  /**
+   * \brief Detach a given netdevice from this channel
+   *
+   * The net device is marked as inactive and it is not allowed to
+   * receive or transmit packets
+   *
+   * \param device Device pointer to the netdevice to detach from the channel
+   * \return True if the device is found and attached to the channel,
+   * false if the device is not currently connected to the channel or
+   * can't be found.
+   */
+  bool Detach (Ptr<CsmaCdNetDevice> device);
+  /**
+   * \brief Detach a given netdevice from this channel
+   *
+   * The net device is marked as inactive and it is not allowed to
+   * receive or transmit packets
+   *
+   * \param deviceId The deviceID assigned to the net device when it
+   * was connected to the channel
+   * \return True if the device is found and attached to the channel,
+   * false if the device is not currently connected to the channel or
+   * can't be found.
+   */
+  bool Detach (uint32_t deviceId);
+  /**
+   * \brief Reattach a previously detached net device to the channel
+   *
+   * The net device is marked as active. It is now allowed to receive
+   * or transmit packets. The net device must have been previously
+   * attached to the channel using the attach function.
+   *
+   * \param deviceId The device ID assigned to the net device when it
+   * was connected to the channel
+   * \return True if the device is found and is not attached to the
+   * channel, false if the device is currently connected to the
+   * channel or can't be found.
+   */
+  bool Reattach(uint32_t deviceId);
+  /**
+   * \brief Reattach a previously detached net device to the channel
+   *
+   * The net device is marked as active. It is now allowed to receive
+   * or transmit packets. The net device must have been previously
+   * attached to the channel using the attach function.
+   *
+   * \param device Device pointer to the netdevice to detach from the channel
+   * \return True if the device is found and is not attached to the
+   * channel, false if the device is currently connected to the
+   * channel or can't be found.
+   */
+  bool Reattach(Ptr<CsmaCdNetDevice> device);
+  /**
+   * \brief Start transmitting a packet over the channel
+   *
+   * If the srcId belongs to a net device that is connected to the
+   * channel, packet transmission begins, and the channel becomes busy
+   * until the packet has completely reached all destinations.
+   *
+   * \param p A reference to the packet that will be transmitted over
+   * the channel
+   * \param srcId The device Id of the net device that wants to
+   * transmit on the channel.
+   * \return True if the channel is not busy and the transmitting net
+   * device is currently active.
+   */
+  bool TransmitStart (Packet& p, uint32_t srcId);
+  /**
+   * \brief Indicates that the net device has finished transmitting
+   * the packet over the channel
+   *
+   * The channel will stay busy until the packet has completely
+   * propagated to all net devices attached to the channel. The
+   * TransmitEnd function schedules the PropagationCompleteEvent which
+   * will free the channel for further transmissions. Stores the
+   * packet p as the m_currentPkt, the packet being currently
+   * transmitting.
+   *
+   * \return Returns true unless the source was detached before it
+   * completed its transmission.
+   */
+  bool TransmitEnd ();
+  /**
+   * \brief Indicates that the channel has finished propagating the
+   * current packet. The channel is released and becomes free.
+   *
+   * Calls the receive function of every active net device that is
+   * attached to the channel.
+   */
+  void PropagationCompleteEvent();
+  /**
+   * \return Returns the device number assigned to a net device by the
+   * channel
+   *
+   * \param device Device pointer to the netdevice for which the device
+   * number is needed
+   */
+  int32_t GetDeviceNum (Ptr<CsmaCdNetDevice> device);
+  /**
+   * \return Returns the state of the channel (IDLE -- free,
+   * TRANSMITTING -- busy, PROPAGATING - busy )
+   */
+  WireState GetState();
+
+  /**
+   * \brief Indicates if the channel is busy. The channel will only
+   * accept new packets for transmission if it is not busy.
+   *
+   * \return Returns true if the channel is busy and false if it is
+   * free.
+   */
+  bool IsBusy();
+  
+  /**
+   * \brief Indicates if a net device is currently attached or
+   * detached from the channel.
+   *
+   * \param deviceId The ID that was assigned to the net device when
+   * it was attached to the channel.
+   * \return Returns true if the net device is attached to the
+   * channel, false otherwise.
+   */
+  bool IsActive(uint32_t deviceId);
+  /**
+   * \return Returns the number of net devices that are currently
+   * attached to the channel.
+   */
+  uint32_t GetNumActDevices (void);
+  /**
+   * \return Returns the total number of devices including devices
+   * that have been detached from the channel.
+   */
+  virtual uint32_t GetNDevices (void) const;
+  /**
+   * \param i The deviceId of the net device for which we want the
+   * pointer.
+   * \return Returns the pointer to the net device that is associated
+   * with deviceId i.
+   */
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
+  virtual DataRate GetDataRate (void);
+  virtual Time GetDelay (void);
+
+private:
+  DataRate      m_bps;    /// Data rate of the channel
+  Time          m_delay;  /// Delay of the channel.
+
+  /**
+   * List of the net devices that have been or are currently connected
+   * to the channel.
+   *
+   * Devices are nor removed from this list, they are marked as
+   * inactive. Otherwise the assigned device IDs will not refer to the
+   * correct NetDevice. The DeviceIds are used so that it is possible
+   * to have a number to refer to an entry in the list so that the
+   * whole list does not have to be searched when making sure that a
+   * source is attached to a channel when it is transmitting data.
+   */
+  std::vector< CsmaCdDeviceRec >            m_deviceList;
+  /**
+   * Packet that is currently being transmitted on the channel (or last
+   * packet to have been transmitted on the channel if the channel is
+   * free.)
+   */
+  Packet                              m_currentPkt;
+  /**
+   * Device Id of the source that is currently transmitting on the
+   * channel. Or last source to have transmitted a packet on the
+   * channel, if the channel is currently not busy.
+   */
+  uint32_t                            m_currentSrc;
+  /**
+   * Current state of the channel
+   */
+  WireState          m_state;
+  /**
+   * Initializes the channel when it is constructed. Resets the
+   * deviceList and sets the channel state to IDLE.
+   */
+  void Init (void);
+};
+
+} // namespace ns3
+
+#endif /* CSMA_CD_CHANNEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-ipv4-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,156 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2007 Emmanuelle Laprise
+//
+// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+//
+
+#include <algorithm>
+#include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/fatal-error.h"
+#include "ns3/nstime.h"
+#include "ns3/internet-node.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/queue.h"
+
+#include "csma-cd-channel.h"
+#include "csma-cd-net-device.h"
+#include "csma-cd-ipv4-topology.h"
+
+namespace ns3 {
+
+
+uint32_t
+CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr<Node> n1,
+                                      Ptr<CsmaCdChannel> ch,
+                                      MacAddress addr)
+{
+  Ptr<Queue> q = Queue::CreateDefault ();
+
+  // assume full-duplex
+  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr, 
+                                                      ns3::CsmaCdNetDevice::IP_ARP,
+                                                      true, true);
+  nd0->AddQueue(q);
+  nd0->Attach (ch);
+  return nd0->GetIfIndex ();
+}
+
+
+void
+CsmaCdIpv4Topology::AddIpv4LlcCsmaCdNode(Ptr<Node> n1,
+                                         Ptr<CsmaCdChannel> ch,
+                                         MacAddress addr)
+{
+  Ptr<Queue> q = Queue::CreateDefault ();
+
+  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr,
+                                                      ns3::CsmaCdNetDevice::LLC,
+                                                      true, false);
+  nd0->AddQueue(q);
+  nd0->Attach (ch);
+
+  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr,
+                                                      ns3::CsmaCdNetDevice::LLC,
+                                                      false, true);
+  nd1->AddQueue(q);
+  nd1->Attach (ch);
+}
+
+void
+CsmaCdIpv4Topology::AddIpv4RawCsmaCdNode(Ptr<Node> n1,
+                                         Ptr<CsmaCdChannel> ch,
+                                         MacAddress addr)
+{
+  Ptr<Queue> q = Queue::CreateDefault ();
+
+  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr,
+                                                      ns3::CsmaCdNetDevice::RAW,
+                                                      true, false);
+  nd0->AddQueue(q);
+  nd0->Attach (ch);
+
+  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr,
+                                                      ns3::CsmaCdNetDevice::RAW,
+                                                      false, true);
+  nd1->AddQueue(q);
+  nd1->Attach (ch);
+}
+
+void
+CsmaCdIpv4Topology::AddIpv4Address(Ptr<Node> n1,
+                                       int ndNum,
+                                       const Ipv4Address& addr1,
+                                       const Ipv4Mask& netmask1)
+{
+
+  // Duplex link is assumed to be subnetted as a /30
+  // May run this unnumbered in the future?
+  Ipv4Mask netmask(netmask1);
+
+  Ptr<NetDevice> nd1 = n1->GetDevice(ndNum);
+
+  Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
+  uint32_t index1 = ip1->AddInterface (nd1);
+
+  ip1->SetAddress (index1, addr1);
+  ip1->SetNetworkMask (index1, netmask);
+  ip1->SetUp (index1);
+
+}
+
+void
+CsmaCdIpv4Topology::AddIpv4Routes (
+  Ptr<NetDevice> nd1, Ptr<NetDevice> nd2)
+{ 
+  // Assert that both are Ipv4 nodes
+  Ptr<Ipv4> ip1 = nd1->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
+  Ptr<Ipv4> ip2 = nd2->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
+  NS_ASSERT(ip1 != 0 && ip2 != 0);
+
+  // Get interface indexes for both nodes corresponding to the right channel
+  uint32_t index1 = 0;
+  bool found = false;
+  for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
+    {
+      if (ip1 ->GetNetDevice (i) == nd1)
+        {
+          index1 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  uint32_t index2 = 0;
+  found = false;
+  for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
+    {
+      if (ip2 ->GetNetDevice (i) == nd2)
+        {
+          index2 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
+  ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); 
+}
+
+} // namespace ns3
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-ipv4-topology.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2007 Emmanuelle Laprise
+//
+// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+//
+
+#ifndef __CSMA_CD_IPV4_TOPOLOGY_H__
+#define __CSMA_CD_IPV4_TOPOLOGY_H__
+
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/internet-node.h"
+#include "ns3/csma-cd-net-device.h"
+
+// The topology class consists of only static methods thar are used to
+// create the topology and data flows for an ns3 simulation
+
+namespace ns3 {
+
+class CsmaCdIpv4Channel;
+class Node;
+class IPAddr;
+class DataRate;
+class Queue;
+
+/**
+ * \brief A helper class to create Topologies based on the
+ * InternetNodes and CsmaCdChannels. Either the
+ * SimpleCsmaCdNetDevice or the LLCCsmaCdNetDevice can be used
+ * when constructing these topologies.
+ */
+class CsmaCdIpv4Topology {
+public:
+
+  /**
+   * \param n1 Node to be attached to the Csma/Cd channel
+   * \param ch CsmaCdChannel to which node n1 should be attached
+   * \param addr Mac address of the node
+   *
+   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
+   * a EthernetCsmaCdNetDevice to the nodes so that they can
+   * connect to a CsmaCdChannel. This means that Ethernet headers
+   * and trailers will be added to the packet before sending out on
+   * the net device.
+   * 
+   * \return ifIndex of the device
+   */
+  static uint32_t AddIpv4CsmaCdNode( Ptr<Node> n1,
+                                 Ptr<CsmaCdChannel> ch,
+                                 MacAddress addr);
+
+  /**
+   * \param n1 Node to be attached to the Csma/Cd channel
+   * \param ch CsmaCdChannel to which node n1 should be attached
+   * \param addr Mac address of the node
+   *
+   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
+   * a RawCsmaCdNetDevice to the nodes so that they can connect
+   * to a CsmaCdChannel.
+   */
+  static void AddIpv4RawCsmaCdNode( Ptr<Node> n1,
+                                    Ptr<CsmaCdChannel> ch,
+                                    MacAddress addr);
+
+  /**
+   * \param n1 Node to be attached to the Csma/Cd channel
+   * \param ch CsmaCdChannel to which node n1 should be attached
+   * \param addr Mac address of the node
+   *
+   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
+   * a LlcCsmaCdNetDevice to the nodes so that they can connect
+   * to a CsmaCdChannel.
+   */
+  static void AddIpv4LlcCsmaCdNode( Ptr<Node> n1,
+                                    Ptr<CsmaCdChannel> ch,
+                                    MacAddress addr);
+
+
+
+  /** 
+   * \param n1 Node
+   * \param ndNum NetDevice number with which to associate address
+   * \param addr1 Ipv4 Address for ndNum of n1
+   * \param network network mask for ndNum of node n1
+   * 
+   * Add an Ipv4Address to the Ipv4 interface associated with the
+   * ndNum CsmaCdIpv4NetDevices on the provided
+   * CsmaCdIpv4Channel
+   */
+  static void AddIpv4Address(Ptr<Node> n1, int ndNum, 
+                             const Ipv4Address& addr1,
+                             const Ipv4Mask& netmask1);
+
+  /**
+   * \param nd1 Node
+   * \param nd2 Node
+   * 
+   * Add an IPV4 host route between the two specified net devices
+   */
+  static void AddIpv4Routes (Ptr<NetDevice> nd1, Ptr<NetDevice> nd2);
+};
+
+} // namespace ns3
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-net-device.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,488 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include <iostream>
+#include <cassert>
+#include "ns3/debug.h"
+#include "ns3/queue.h"
+#include "ns3/simulator.h"
+#include "ns3/composite-trace-resolver.h"
+#include "csma-cd-net-device.h"
+#include "csma-cd-channel.h"
+#include "ns3/ethernet-header.h"
+#include "ns3/ethernet-trailer.h"
+#include "ns3/llc-snap-header.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("CsmaCdNetDevice");
+
+namespace ns3 {
+
+CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
+                                  CsmaCdEncapsulationMode encapMode) 
+  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
+{
+  NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
+  m_encapMode = encapMode;
+
+  Init(true, true);
+}
+
+CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
+                                  CsmaCdEncapsulationMode encapMode,
+                                  bool sendEnable, bool receiveEnable) 
+  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
+{
+  NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
+  m_encapMode = encapMode;
+
+  Init(sendEnable, receiveEnable);
+}
+
+CsmaCdNetDevice::~CsmaCdNetDevice()
+{
+  NS_DEBUG ("CsmaCdNetDevice::~CsmaCdNetDevice ()");
+  m_queue = 0;
+}
+
+void 
+CsmaCdNetDevice::DoDispose ()
+{
+  m_channel = 0;
+  NetDevice::DoDispose ();
+}
+
+//
+// Assignment operator for CsmaCdNetDevice.
+//
+// This uses the non-obvious trick of taking the source net device passed by
+// value instead of by reference.  This causes the copy constructor to be
+// invoked (where the real work is done -- see above).  All we have to do
+// here is to return the newly constructed net device.
+//
+/*
+CsmaCdNetDevice&
+CsmaCdNetDevice::operator= (const CsmaCdNetDevice nd)
+{
+  NS_DEBUG ("CsmaCdNetDevice::operator= (" << &nd << ")");
+  return *this;
+}
+*/
+
+void 
+CsmaCdNetDevice::Init(bool sendEnable, bool receiveEnable)
+{
+  m_txMachineState = READY;
+  m_tInterframeGap = Seconds(0);
+  m_channel = 0; 
+  m_queue = 0;
+
+  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+  EnableMulticast();
+  EnablePointToPoint();
+
+  SetSendEnable (sendEnable);
+  SetReceiveEnable (receiveEnable);
+}
+
+void
+CsmaCdNetDevice::SetSendEnable (bool sendEnable)
+{
+  m_sendEnable = sendEnable;
+}
+
+void
+CsmaCdNetDevice::SetReceiveEnable (bool receiveEnable)
+{
+  m_receiveEnable = receiveEnable;
+}
+bool
+CsmaCdNetDevice::IsSendEnabled (void)
+{
+  return (m_sendEnable);
+}
+
+bool
+CsmaCdNetDevice::IsReceiveEnabled (void)
+{
+  return (m_receiveEnable);
+}
+
+void 
+CsmaCdNetDevice::SetDataRate (DataRate bps)
+{
+  m_bps = bps;
+}
+
+void 
+CsmaCdNetDevice::SetInterframeGap (Time t)
+{
+  m_tInterframeGap = t;
+}
+
+void 
+CsmaCdNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, 
+                                      uint32_t maxSlots, uint32_t ceiling, 
+                                      uint32_t maxRetries)
+{
+  m_backoff.m_slotTime = slotTime;
+  m_backoff.m_minSlots = minSlots;
+  m_backoff.m_maxSlots = maxSlots;
+  m_backoff.m_ceiling = ceiling;
+  m_backoff.m_maxRetries = maxRetries;
+}
+void 
+CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest,
+                            uint16_t protocolNumber)
+{
+  if (m_encapMode == RAW)
+    {
+      return;
+    }
+  EthernetHeader header (false);
+  EthernetTrailer trailer;
+  header.SetSource(this->GetAddress());
+  header.SetDestination(dest);
+
+  uint16_t lengthType = 0;
+  switch (m_encapMode) 
+    {
+    case ETHERNET_V1:
+      lengthType = p.GetSize() + header.GetSize() + trailer.GetSize();
+      break;
+    case IP_ARP:
+      lengthType = protocolNumber;
+      break;
+    case LLC: {
+      LlcSnapHeader llc;
+      llc.SetType (protocolNumber);
+      p.AddHeader (llc);
+    } break;
+    case RAW:
+      NS_ASSERT (false);
+      break;
+    }
+  header.SetLengthType (lengthType);
+  p.AddHeader(header);
+  trailer.CalcFcs(p);
+  p.AddTrailer(trailer);
+}
+bool 
+CsmaCdNetDevice::ProcessHeader (Packet& p, uint16_t & param)
+{
+  if (m_encapMode == RAW)
+    {
+      return true;
+    }
+  EthernetHeader header (false);
+  EthernetTrailer trailer;
+      
+  p.RemoveTrailer(trailer);
+  trailer.CheckFcs(p);
+  p.RemoveHeader(header);
+
+  if ((header.GetDestination() != this->GetBroadcast()) &&
+      (header.GetDestination() != this->GetAddress()))
+    {
+      return false;
+    }
+
+  switch (m_encapMode)
+    {
+    case ETHERNET_V1:
+    case IP_ARP:
+      param = header.GetLengthType();
+      break;
+    case LLC: {
+      LlcSnapHeader llc;
+      p.RemoveHeader (llc);
+      param = llc.GetType ();
+    } break;
+    case RAW:
+      NS_ASSERT (false);
+      break;
+    }
+  return true;
+}
+
+bool
+CsmaCdNetDevice::DoNeedsArp (void) const
+{
+  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+bool
+CsmaCdNetDevice::SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber)
+{
+  NS_DEBUG ("CsmaCdNetDevice::SendTo (" << &p << ")");
+  NS_DEBUG ("CsmaCdNetDevice::SendTo (): UID is " << p.GetUid () << ")");
+
+  NS_ASSERT (IsLinkUp ());
+
+  // Only transmit if send side of net device is enabled
+  if (!IsSendEnabled())
+    return false;
+
+  AddHeader(p, dest, protocolNumber);
+
+  // Place the packet to be sent on the send queue
+  if (m_queue->Enqueue(p) == false )
+    {
+      return false;
+    }
+  // If the device is idle, we need to start a transmission. Otherwise,
+  // the transmission will be started when the current packet finished
+  // transmission (see TransmitCompleteEvent)
+  if (m_txMachineState == READY) 
+    {
+      // Store the next packet to be transmitted
+      if (m_queue->Dequeue (m_currentPkt))
+        {
+          TransmitStart();
+        }
+    }
+  return true;
+}
+
+void
+CsmaCdNetDevice::TransmitStart ()
+{
+  NS_DEBUG ("CsmaCdNetDevice::TransmitStart (" << &m_currentPkt << ")");
+  NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): UID is " 
+            << m_currentPkt.GetUid () << ")");
+//
+// This function is called to start the process of transmitting a packet.
+// We need to tell the channel that we've started wiggling the wire and
+// schedule an event that will be executed when it's time to tell the 
+// channel that we're done wiggling the wire.
+//
+  NS_ASSERT_MSG((m_txMachineState == READY) || (m_txMachineState == BACKOFF), 
+                "Must be READY to transmit. Tx state is: " 
+                << m_txMachineState);
+
+  // Only transmit if send side of net device is enabled
+  if (!IsSendEnabled())
+    return;
+
+  if (m_channel->GetState() != IDLE)
+    { // Channel busy, backoff and rechedule TransmitStart()
+      m_txMachineState = BACKOFF;
+      if (m_backoff.MaxRetriesReached())
+        { // Too many retries reached, abort transmission of packet
+          TransmitAbort();
+        } 
+      else 
+        {
+          m_backoff.IncrNumRetries();
+          Time backoffTime = m_backoff.GetBackoffTime();
+
+          NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " 
+                    << "Channel busy, backing off for " 
+                    << backoffTime.GetSeconds () << "sec");
+
+          Simulator::Schedule (backoffTime, 
+                               &CsmaCdNetDevice::TransmitStart, 
+                               this);
+        }
+    } 
+  else 
+    {
+      // Channel is free, transmit packet
+      m_txMachineState = BUSY;
+      Time tEvent = Seconds (m_bps.CalculateTxTime(m_currentPkt.GetSize()));
+      
+      NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " <<
+                "Schedule TransmitCompleteEvent in " << 
+                tEvent.GetSeconds () << "sec");
+      
+      Simulator::Schedule (tEvent, 
+                           &CsmaCdNetDevice::TransmitCompleteEvent, 
+                           this);
+      if (!m_channel->TransmitStart (m_currentPkt, m_deviceId))
+        {
+          NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " <<
+                    "Channel transmit start did not work at " << 
+                    tEvent.GetSeconds () << "sec");
+          m_txMachineState = READY;
+        } 
+      else 
+        {
+          // Transmission success, reset backoff time parameters.
+          m_backoff.ResetBackoffTime();
+        }
+    }
+}
+
+
+void
+CsmaCdNetDevice::TransmitAbort (void)
+{
+  NS_DEBUG ("CsmaCdNetDevice::TransmitAbort ()");
+
+  NS_DEBUG ("CsmaCdNetDevice::TransmitAbort (): Pkt UID is " <<
+            m_currentPkt.GetUid () << ")");
+
+  // Try to transmit a new packet
+  bool found;
+  found = m_queue->Dequeue (m_currentPkt);
+  NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
+  m_backoff.ResetBackoffTime();
+  m_txMachineState = READY;
+  TransmitStart ();
+}
+
+void
+CsmaCdNetDevice::TransmitCompleteEvent (void)
+{
+  NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent ()");
+//
+// This function is called to finish the  process of transmitting a packet.
+// We need to tell the channel that we've stopped wiggling the wire and
+// schedule an event that will be executed when it's time to re-enable
+// the transmitter after the interframe gap.
+//
+  NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
+  // Channel should be transmitting
+  NS_ASSERT(m_channel->GetState() == TRANSMITTING);
+  m_txMachineState = GAP;
+
+  NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent (): Pkt UID is " << 
+            m_currentPkt.GetUid () << ")");
+  m_channel->TransmitEnd (); 
+
+  NS_DEBUG (
+    "CsmaCdNetDevice::TransmitCompleteEvent (): " <<
+    "Schedule TransmitReadyEvent in "
+    << m_tInterframeGap.GetSeconds () << "sec");
+
+  Simulator::Schedule (m_tInterframeGap, 
+                       &CsmaCdNetDevice::TransmitReadyEvent, 
+                       this);
+}
+
+void
+CsmaCdNetDevice::TransmitReadyEvent (void)
+{
+  NS_DEBUG ("CsmaCdNetDevice::TransmitReadyEvent ()");
+//
+// This function is called to enable the transmitter after the interframe
+// gap has passed.  If there are pending transmissions, we use this opportunity
+// to start the next transmit.
+//
+  NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap");
+  m_txMachineState = READY;
+
+  // Get the next packet from the queue for transmitting
+  if (m_queue->IsEmpty())
+    {
+      return;
+    }
+  else
+    {
+      bool found;
+      found = m_queue->Dequeue (m_currentPkt);
+      NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
+      TransmitStart ();
+    }
+}
+
+TraceResolver *
+CsmaCdNetDevice::DoCreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("queue", 
+                 MakeCallback (&Queue::CreateTraceResolver, 
+                               PeekPointer (m_queue)),
+                 CsmaCdNetDevice::QUEUE);
+  resolver->Add ("rx",
+                 m_rxTrace,
+                 CsmaCdNetDevice::RX);
+  return resolver;
+}
+
+bool
+CsmaCdNetDevice::Attach (Ptr<CsmaCdChannel> ch)
+{
+  NS_DEBUG ("CsmaCdNetDevice::Attach (" << &ch << ")");
+
+  m_channel = ch;
+
+  m_deviceId = m_channel->Attach(this);
+  m_bps = m_channel->GetDataRate ();
+  m_tInterframeGap = m_channel->GetDelay ();
+
+  /* 
+   * For now, this device is up whenever a channel is attached to it.
+   */
+  NotifyLinkUp ();
+  return true;
+}
+
+void
+CsmaCdNetDevice::AddQueue (Ptr<Queue> q)
+{
+  NS_DEBUG ("CsmaCdNetDevice::AddQueue (" << q << ")");
+
+  m_queue = q;
+}
+
+void
+CsmaCdNetDevice::Receive (Packet& p)
+{
+  NS_DEBUG ("CsmaCdNetDevice::Receive UID is (" << p.GetUid() << ")");
+
+  // Only receive if send side of net device is enabled
+  if (!IsReceiveEnabled())
+    return;
+
+  uint16_t param = 0;
+  Packet packet = p;
+
+  if (ProcessHeader(packet, param))
+    {
+      m_rxTrace (packet);
+      ForwardUp (packet, param);
+    } 
+  else 
+    {
+      m_dropTrace (packet);
+    }
+}
+
+Ptr<Queue>
+CsmaCdNetDevice::GetQueue(void) const 
+{ 
+    return m_queue;
+}
+
+Ptr<Channel>
+CsmaCdNetDevice::DoGetChannel(void) const 
+{ 
+    return m_channel;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-net-device.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,409 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ *
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca
+ * Derived from the p2p net device file
+ */
+
+#ifndef CSMA_CD_NET_DEVICE_H
+#define CSMA_CD_NET_DEVICE_H
+
+#include <string.h>
+#include "ns3/node.h"
+#include "ns3/backoff.h"
+#include "ns3/mac-address.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/callback-trace-source.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+namespace ns3 {
+
+class Queue;
+class CsmaCdChannel;
+
+/**
+ * \class CsmaCdNetDevice
+ * \brief A Device for a CsmaCd Network Link.
+ *
+ * The Csma/Cd net device class is analogous to layer 1 and 2 of the
+ * TCP stack. The NetDevice takes a raw packet of bytes and creates a
+ * protocol specific packet from them. The Csma/Cd net device class
+ * takes this packet and adds and processes the headers/trailers that
+ * are associated with EthernetV1, EthernetV2, RAW or LLC
+ * protocols. The EthernetV1 packet type adds and removes Ethernet
+ * destination and source addresses. The LLC packet type adds and
+ * removes LLC snap headers. The raw packet type does not add or
+ * remove any headers.  Each Csma/Cd net device will receive all
+ * packets written to the Csma/Cd link. The ProcessHeader function can
+ * be used to filter out the packets such that higher level layers
+ * only receive packets that are addressed to their associated net
+ * devices
+ *
+ */
+class CsmaCdNetDevice : public NetDevice {
+public:
+  /**
+   * Enumeration of the types of traces supported in the class.
+   *
+   */
+  enum TraceType {
+    QUEUE, /**< Trace queue events on the attached queue */
+    RX,    /**< Trace packet reception events (from the channel) */
+    DROP    /**< Trace packet drop events (from the channel) */
+  };
+
+  /**
+   * Enumeration of the types of packets supported in the class.
+   *
+   */
+enum CsmaCdEncapsulationMode {
+  ETHERNET_V1, /**< Version one ethernet packet, length field */
+  IP_ARP,      /**< Ethernet packet encapsulates IP/ARP packet */
+  RAW,         /**< Packet that contains no headers */
+  LLC,         /**< LLC packet encapsulation */  
+};
+
+  /**
+   * Construct a CsmaCdNetDevice
+   *
+   * This is the constructor for the CsmaCdNetDevice.  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 deleted.
+   *
+   * \param node the Node to which this device is connected.
+   * \param addr The source MAC address of the net device.
+   */
+  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, CsmaCdEncapsulationMode pktType);
+  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr,
+                   CsmaCdEncapsulationMode pktType,
+                   bool sendEnable, bool receiveEnable);
+  /**
+   * Destroy a CsmaCdNetDevice
+   *
+   * This is the destructor for the CsmaCdNetDevice.
+   */
+  virtual ~CsmaCdNetDevice();
+  /**
+   * 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
+   * to which the device is attached.  It can be overridden using this method.
+   *
+   * @see Attach ()
+   * \param bps the data rate at which this object operates
+   */
+  void SetDataRate (DataRate bps);
+  /**
+   * Set the inteframe gap used to separate packets.  The interframe gap
+   * defines the minimum space required between packets sent by this device.
+   * It is usually set in the Attach () method based on the speed of light
+   * delay of the channel to which the device is attached.  It can be 
+   * overridden using this method if desired.
+   *
+   * @see Attach ()
+   * \param t the interframe gap time
+   */
+  void SetInterframeGap (Time t);
+  /**
+   * Set the backoff parameters used to determine the wait to retry
+   * transmitting a packet when the channel is busy.
+   *
+   * @see Attach ()
+   * \param slotTime Length of a packet slot (or average packet time)
+   * \param minSlots Minimum number of slots to wait
+   * \param maxSlots Maximum number of slots to wait
+   * \param maxRetries Maximum number of retries before packet is discard
+   * \param ceiling Cap on the exponential function when calculating max slots
+   */
+  void SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, 
+                        uint32_t maxRetries, uint32_t ceiling);
+  /**
+   * Attach the device to a channel.
+   *
+   * The function Attach is used to add a CsmaCdNetDevice to a
+   * CsmaCdChannel.
+   *
+   * @see SetDataRate ()
+   * @see SetInterframeGap ()
+   * \param ch a pointer to the channel to which this object is being attached.
+   */
+  bool Attach (Ptr<CsmaCdChannel> ch);
+  /**
+   * Attach a queue to the CsmaCdNetDevice.
+   *
+   * The CsmaCdNetDevice "owns" a queue.  This queue is created by the
+   * CsmaCdTopology object and implements a queueing method such as
+   * DropTail or RED.  The CsmaCdNetDevice assumes ownership of this
+   * queue and must delete it when the device is destroyed.
+   *
+   * @see CsmaCdTopology::AddCsmaCdLink ()
+   * @see Queue
+   * @see DropTailQueue
+   * \param queue a pointer to the queue for which object is assuming
+   *        ownership.
+   */
+  void AddQueue (Ptr<Queue> queue);
+  /**
+   * Receive a packet from a connected CsmaCdChannel.
+   *
+   * The CsmaCdNetDevice receives packets from its connected channel
+   * and forwards them up the protocol stack.  This is the public method
+   * used by the channel to indicate that the last bit of a packet has 
+   * arrived at the device.
+   *
+   * @see CsmaCdChannel
+   * \param p a reference to the received packet
+   */
+  void Receive (Packet& p);
+
+  bool IsSendEnabled (void);
+  bool IsReceiveEnabled (void);
+
+  void SetSendEnable (bool);
+  void SetReceiveEnable (bool);
+
+protected:
+  virtual bool DoNeedsArp (void) const;
+  virtual void DoDispose (void);
+  /**
+   * Get a copy of the attached Queue.
+   *
+   * This method is provided for any derived class that may need to get
+   * direct access to the underlying queue.
+   *
+   * \return a pointer to the queue.
+   */
+  Ptr<Queue> GetQueue (void) const; 
+  /**
+   * Get a copy of the attached Channel
+   *
+   * This method is provided for any derived class that may need to get
+   * direct access to the connected channel
+   *
+   * \return a pointer to the channel
+   */
+  virtual Ptr<Channel> DoGetChannel (void) const;
+  /**
+   * Adds the necessary headers and trailers to a packet of data in order to
+   * respect the packet type
+   *
+   * \param p Packet to which header should be added
+   * \param dest MAC destination address to which packet should be sent
+   * \param protocolNumber In some protocols, identifies the type of
+   * payload contained in this packet.
+   */
+  void AddHeader (Packet& p, const MacAddress& dest, 
+                  uint16_t protocolNumber);
+  /**
+   * Removes, from a packet of data, all headers and trailers that
+   * relate to the packet type
+   *
+   * \param p Packet whose headers need to be processed
+   * \param param An integer parameter that can be set by the function
+   * to return information gathered in the header
+   * \return Returns true if the packet should be forwarded up the
+   * protocol stack.
+   */
+  bool ProcessHeader (Packet& p, uint16_t & param);
+
+private:
+  // disable copy constructor and operator =
+  CsmaCdNetDevice &operator = (const CsmaCdNetDevice &o);
+  CsmaCdNetDevice (const CsmaCdNetDevice &o);
+  /**
+   * Initializes variablea when construction object.
+   */
+  void Init (bool sendEnable, bool receiveEnable);
+  /**
+   * Send a Packet on the Csma/Cd network
+   *
+   * This method does not use a destination address since all packets
+   * are broadcast to all NetDevices attached to the channel. Packet
+   * should contain all needed headers at this time.
+   *
+   * If the device is ready to transmit, the next packet is read off
+   * of the queue and stored locally until it has been transmitted.
+   *
+   * \param p a reference to the packet to send
+   * \param dest destination address
+   * \param protocolNumber -- this parameter is not used here
+   * \return true if success, false on failure
+   */
+  virtual bool SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber);
+
+  /**
+   * Start Sending a Packet Down the Wire.
+   *
+   * The TransmitStart method is the method that is used internally in
+   * the CsmaCdNetDevice to begin the process of sending a packet
+   * out on the channel.  The corresponding method is called on the
+   * channel to let it know that the physical device this class
+   * represents has virually started sending signals, this causes the
+   * channel to become busy.  An event is scheduled for the time at
+   * which the bits have been completely transmitted. If the channel
+   * is busy, the method reschedules itself for a later time (within
+   * the backoff period)
+   *
+   * @see CsmaCdChannel::TransmitStart ()
+   * @see TransmitCompleteEvent ()
+   */
+  void TransmitStart ();
+  /**
+   * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
+   *
+   * The TransmitCompleteEvent method is used internally to finish the process
+   * of sending a packet out on the channel.  During execution of this method
+   * the TransmitEnd method is called on the channel to let it know that the
+   * physical device this class represents has virually finished sending 
+   * signals.  The channel uses this event to begin its speed of light delay
+   * timer after which it notifies the Net Device at the other end of the 
+   * link that the bits have arrived.  During this method, the net device 
+   * also schedules the TransmitReadyEvent at which time the transmitter 
+   * becomes ready to send the next packet.
+   *
+   * @see CsmaCdChannel::TransmitEnd ()
+   * @see TransmitReadyEvent ()
+   */
+  void TransmitCompleteEvent (void);
+  /**
+   * Cause the Transmitter to Become Ready to Send Another Packet.
+   *
+   * The TransmitReadyEvent method is used internally to re-enable the 
+   * transmit machine of the net device.  It is scheduled after a suitable
+   * interframe gap after the completion of the previous transmission.
+   * The queue is checked at this time, and if there is a packet waiting on
+   * the queue, the transmission process is begun.
+   *
+   * If a packet is in the queue, it is extracted for the queue as the
+   * next packet to be transmitted by the net device.
+   *
+   * @see TransmitStart ()
+   */
+  void TransmitReadyEvent (void);
+  /**
+   * Create a Trace Resolver for events in the net device.
+   * (NOT TESTED)
+   * @see class TraceResolver
+   */
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
+
+  /**
+   * Aborts the transmission of the current packet
+   *
+   * If the net device has tried to transmit a packet for more times
+   * than the maximum allowed number of retries (channel always busy)
+   * then the packet is dropped.
+   *
+   */
+  void TransmitAbort (void);
+
+  /** 
+   * Device ID returned by the attached functions. It is used by the
+   * mp-channel to identify each net device to make sure that only
+   * active net devices are writing to the channel
+   */
+  uint32_t m_deviceId; 
+
+  /**
+   * Enable net device to send packets. True by default
+   */
+  bool m_sendEnable;
+  /**
+   * Enable net device to receive packets. True by default
+   */
+  bool m_receiveEnable;
+  /**
+   * Enumeration of the states of the transmit machine of the net device.
+   */
+  enum TxMachineState
+    {
+      READY, /**< The transmitter is ready to begin transmission of a packet */
+      BUSY,  /**< The transmitter is busy transmitting a packet */
+      GAP,    /**< The transmitter is in the interframe gap time */
+      BACKOFF    /**< The transmitter is waiting for the channel to be free */
+    };
+  /**
+   * The state of the Net Device transmit state machine.
+   * @see TxMachineState
+   */
+  TxMachineState m_txMachineState;
+  
+  /**
+   * The type of packet that should be created by the AddHeader
+   * function and that should be processed by the ProcessHeader
+   * function.
+   */
+  CsmaCdEncapsulationMode m_encapMode;
+  /**
+   * The data rate that the Net Device uses to simulate packet transmission
+   * timing.
+   * @see class DataRate
+   */
+  DataRate m_bps;
+  /**
+   * The interframe gap that the Net Device uses to throttle packet
+   * transmission
+   * @see class Time
+   */
+  Time m_tInterframeGap;
+  /**
+   * Holds the backoff parameters and is used to calculate the next
+   * backoff time to use when the channel is busy and the net device
+   * is ready to transmit
+   */
+  Backoff m_backoff;
+  /**
+   * Next packet that will be transmitted (if transmitter is not
+   * currently transmitting) or packet that is currently being
+   * transmitted.
+   */
+  Packet m_currentPkt;
+  /**
+   * The CsmaCdChannel to which this CsmaCdNetDevice has been
+   * attached.
+   * @see class CsmaCdChannel
+   */
+  Ptr<CsmaCdChannel> m_channel;
+  /**
+   * The Queue which this CsmaCdNetDevice uses as a packet source.
+   * Management of this Queue has been delegated to the CsmaCdNetDevice
+   * and it has the responsibility for deletion.
+   * @see class Queue
+   * @see class DropTailQueue
+   */
+  Ptr<Queue> m_queue;
+  /**
+   * NOT TESTED
+   * The trace source for the packet reception events that the device can
+   * fire.
+   *
+   * @see class CallBackTraceSource
+   * @see class TraceResolver
+   */
+  CallbackTraceSource<Packet &> m_rxTrace;
+  CallbackTraceSource<Packet &> m_dropTrace;
+
+};
+
+}; // namespace ns3
+
+#endif // CSMA_CD_NET_DEVICE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2007 Emmanuelle Laprise
+//
+// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+//
+
+//
+// Topology helper for CsmaCd channels in ns3.
+
+#include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/queue.h"
+
+#include "csma-cd-channel.h"
+#include "csma-cd-net-device.h"
+#include "csma-cd-topology.h"
+#include "ns3/socket-factory.h"
+
+namespace ns3 {
+
+Ptr<CsmaCdChannel>
+CsmaCdTopology::CreateCsmaCdChannel(
+  const DataRate& bps,
+  const Time& delay)
+{
+  Ptr<CsmaCdChannel> channel = Create<CsmaCdChannel> (bps, delay);
+
+  return channel;
+}
+
+#if 0
+Ptr<CsmaCdNetDevice>
+CsmaCdTopology::AddCsmaCdEthernetNode(
+  Ptr<Node> n1,
+  Ptr<CsmaCdChannel> ch,
+  MacAddress addr)
+{
+  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr, 
+                                                      ns3::CsmaCdNetDevice::ETHERNET_V1);
+
+  Ptr<Queue> q = Queue::CreateDefault ();
+  nd1->AddQueue(q);
+  nd1->Attach (ch);
+  
+  return nd1;
+}
+
+Ptr<PacketSocket>
+CsmaCdTopology::ConnectPacketSocket(Ptr<PacketSocketApp> app, 
+                                        Ptr<CsmaCdNetDevice> ndSrc,
+                                        Ptr<CsmaCdNetDevice> ndDest)
+{
+  Ptr<PacketSocket> socket = Create<PacketSocket> ();
+  socket->Bind(ndSrc);
+  socket->Connect(ndDest->GetAddress());
+  app->Connect(socket);
+
+  return socket;
+}
+
+Ptr<PacketSocket>
+CsmaCdTopology::ConnectPacketSocket(Ptr<PacketSocketApp> app,
+                                        Ptr<CsmaCdNetDevice> ndSrc,
+                                        MacAddress macAddr)
+{
+  Ptr<PacketSocket> socket = Create<PacketSocket> ();
+  socket->Bind(ndSrc);
+  socket->Connect(macAddr);
+  app->Connect(socket);
+
+  return socket;
+}
+
+Ptr<Socket>
+CsmaCdTopology::CreatePacketSocket(Ptr<Node> n1, std::string iid_name)
+{
+  InterfaceId iid = InterfaceId::LookupByName (iid_name);
+
+  Ptr<SocketFactory> socketFactory =
+    n1->QueryInterface<SocketFactory> (iid);
+
+  Ptr<Socket> socket = socketFactory->CreateSocket ();
+
+  return socket;
+}
+#endif
+
+} // namespace ns3
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/csma-cd-topology.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2007 Emmanuelle Laprise
+//
+// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+//
+// Topology helper for multipoint channels in ns3.
+// 
+#ifndef CSMA_CD_TOPOLOGY_H
+#define CSMA_CD_TOPOLOGY_H
+
+#include "ns3/ptr.h"
+#include "ns3/csma-cd-net-device.h"
+#if 0
+#include "ns3/packet-socket.h"
+#include "ns3/packet-socket-app.h"
+#endif
+#include "ns3/node.h"
+#include "ns3/mac-address.h"
+
+// The topology class consists of only static methods thar are used to
+// create the topology and data flows for an ns3 simulation
+
+namespace ns3 {
+
+class CsmaCdChannel;
+class Node;
+class DataRate;
+class Queue;
+
+/**
+ * \brief A helper class to create CsmaCd Topologies 
+ *
+ * CsmaCd topologies are created based on the
+ * ns3::CsmaCdNetDevice subclasses and ns3::CsmaCdChannel
+ * objects.  This class uses the EthernetNetDevice and
+ * PacketSocket classes in order to create logical connections between
+ * net devices. The PacketSocket class generates the data and the
+ * EthernetNetDevice class creates ethernet packets from the
+ * data, filling in source and destination addresses. The
+ * EthernetNetDevice class filters received data packets
+ * according to its destination Mac addresses.
+ */
+class CsmaCdTopology {
+public:
+  /** 
+   * \param dataRate Maximum transmission link rate 
+   * \param delay propagation delay between any two nodes 
+   * \return Pointer to the created CsmaCdChannel
+   * 
+   * Create a CsmaCdChannel. All nodes connected to a multipoint
+   * channels will receive all packets written to that channel
+   */
+  static Ptr<CsmaCdChannel> CreateCsmaCdChannel(
+    const DataRate& dataRate, const Time& delay);
+
+#if 0
+  /**
+   * \param n1 Node to be attached to the multipoint channel
+   * \param ch CsmaCdChannel to which node n1 should be attached 
+   * \param addr MacAddress that should be assigned to the
+   * EthernetNetDevice that will be added to the node.
+   *
+   * Add a multipoint node to a multipoint channel
+   */
+  static Ptr<CsmaCdNetDevice> AddCsmaCdEthernetNode(Ptr<Node> n1, 
+                                                    Ptr<CsmaCdChannel> ch,
+                                                    MacAddress addr);
+
+  /**
+   * \param app Application that will be sending data to the agent
+   * \param ndSrc Net Device that will be sending the packets onto the
+   * network
+   * \param ndDest Net Device to which ndSrc will be sending the packets
+   * \return A pointer to the PacketSocket
+   *
+   * Creates an PacketSocket and configure it to send packets between
+   * two net devices
+   */
+static Ptr<PacketSocket> ConnectPacketSocket(Ptr<PacketSocketApp> app,
+                                      Ptr<CsmaCdNetDevice> ndSrc,
+                                      Ptr<CsmaCdNetDevice> ndDest);
+
+  /**
+   * \param app Application that will be sending data to the agent
+   * \param ndSrc Net Device that will be sending the packets onto the
+   * network 
+   * \param macAddr Mac destination address for the packets send by
+   * the ndSrc net device \return a Pointer to the created
+   * PacketSocket
+   *
+   * Creates an PacketSocket and configure it to send packets from a
+   * net device to a destination MacAddress
+   */
+static Ptr<PacketSocket> ConnectPacketSocket(Ptr<PacketSocketApp> app,
+                                      Ptr<CsmaCdNetDevice> ndSrc,
+                                      MacAddress macAddr);
+
+  /**
+   * \param n1 Node from which socketfactory should be tested.
+   * \param iid_name Interface identifier ("Packet", in this case)
+   *
+   * This is a test function to make sure that a socket can be created
+   * by using the socketfactory interface provided in the
+   * netdevicenode.
+   */
+static  Ptr<Socket> CreatePacketSocket(Ptr<Node> n1, 
+                                       std::string iid_name);
+#endif
+
+};
+} // namespace ns3
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma-cd/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,24 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    obj = bld.create_obj('cpp', 'shlib')
+    obj.name = 'ns3-csma-cd'
+    obj.target = obj.name
+    obj.uselib_local = ['ns3-node']
+    obj.source = [
+        'backoff.cc',
+        'csma-cd-net-device.cc',
+        'csma-cd-channel.cc',
+        'csma-cd-topology.cc',
+        'csma-cd-ipv4-topology.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'backoff.h',
+        'csma-cd-net-device.h',
+        'csma-cd-channel.h',
+        'csma-cd-topology.h',
+        'csma-cd-ipv4-topology.h',
+        ]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-channel.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,142 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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: Craig Dowell <craigdo@ee.washington.edu>
+ */
+
+#include "point-to-point-channel.h"
+#include "point-to-point-net-device.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("PointToPointChannel");
+
+namespace ns3 {
+
+//
+// By default, you get a channel with the name "PointToPoint Channel" that 
+// has an "infitely" fast transmission speed and zero delay.
+PointToPointChannel::PointToPointChannel()
+: 
+  Channel ("PointToPoint Channel"), 
+  m_bps (DataRate(0xffffffff)),
+  m_delay (Seconds(0)),
+  m_nDevices(0)
+{
+  NS_DEBUG("PointToPointChannel::PointToPointChannel ()");
+}
+
+PointToPointChannel::PointToPointChannel(
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel ("PointToPoint Channel"), 
+  m_bps (bps),
+  m_delay (delay),
+  m_nDevices(0)
+{
+  NS_DEBUG("PointToPointChannel::PointToPointChannel (" << Channel::GetName() 
+    << ", " << bps.GetBitRate() << ", " << delay << ")");
+}
+
+PointToPointChannel::PointToPointChannel(
+  const std::string& name,
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel (name),
+  m_bps (bps), 
+  m_delay (delay),
+  m_nDevices(0)
+{
+  NS_DEBUG("PointToPointChannel::PointToPointChannel (" << name << ", " << 
+    bps.GetBitRate() << ", " << delay << ")");
+}
+
+  void
+PointToPointChannel::Attach(Ptr<PointToPointNetDevice> device)
+{
+  NS_DEBUG("PointToPointChannel::Attach (" << device << ")");
+  NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
+  NS_ASSERT(device != 0);
+
+  m_link[m_nDevices++].m_src = device;
+//
+// If we have both devices connected to the channel, then finish introducing
+// the two halves and set the links to IDLE.
+//
+  if (m_nDevices == N_DEVICES)
+    {
+      m_link[0].m_dst = m_link[1].m_src;
+      m_link[1].m_dst = m_link[0].m_src;
+      m_link[0].m_state = IDLE;
+      m_link[1].m_state = IDLE;
+    }
+}
+
+bool PointToPointChannel::TransmitStart(Packet& p,
+                                        Ptr<PointToPointNetDevice> src,
+                                        const Time& txTime)
+{
+  NS_DEBUG ("PointToPointChannel::TransmitStart (" << &p << ", " << src << 
+            ")");
+  NS_DEBUG ("PointToPointChannel::TransmitStart (): UID is " << 
+            p.GetUid () << ")");
+
+  NS_ASSERT(m_link[0].m_state != INITIALIZING);
+  NS_ASSERT(m_link[1].m_state != INITIALIZING);
+
+  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
+
+  // Here we schedule the packet receive event at the receiver,
+  // which simplifies this model quite a bit.  The channel just
+  // adds the propagation delay time
+  Simulator::Schedule (txTime + m_delay,
+                       &PointToPointNetDevice::Receive,
+                       m_link[wire].m_dst, p);
+  return true;
+}
+
+uint32_t 
+PointToPointChannel::GetNDevices (void) const
+{
+  return m_nDevices;
+}
+
+Ptr<NetDevice>
+PointToPointChannel::GetDevice (uint32_t i) const
+{
+  NS_ASSERT(i < 2);
+  return m_link[i].m_src;
+}
+
+const DataRate&
+PointToPointChannel::GetDataRate (void)
+{
+  return m_bps;
+}
+
+const Time&
+PointToPointChannel::GetDelay (void)
+{
+  return m_delay;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-channel.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,127 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ *
+ * 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
+ */
+
+#ifndef POINT_TO_POINT_CHANNEL_H
+#define POINT_TO_POINT_CHANNEL_H
+
+#include <list>
+#include "ns3/channel.h"
+#include "ns3/ptr.h"
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+namespace ns3 {
+
+class PointToPointNetDevice;
+
+/**
+ * \brief Simple Point To Point Channel.
+ *
+ * This class represents a very simple point to point channel.  Think full
+ * duplex RS-232 or RS-422 with null modem and no handshaking.  There is no
+ * multi-drop capability on this channel -- there can be a maximum of two 
+ * point-to-point net devices connected.  Once we start talking about multi-
+ * drop, or CSMA, or some other sharing mechanism, things begin getting 
+ * complicated quickly.  Rather than invent some ad-hoc mechanism, we just
+ * Keep It Simple everywhere.
+ *
+ * When the channel is instaniated, the constructor takes parameters for
+ * a single speed, in bits per second, and a speed-of-light delay time as a
+ * Time object.  Both directions use the same speed and delay time.
+ *
+ * There are two "wires" in the channel.  The first device connected gets the
+ * [0] wire to transmit on.  The second device gets the [1] wire.  There is a
+ * state (IDLE, TRANSMITTING) associated with each wire.
+ */
+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
+   *
+   * By default, you get a channel with the name "PointToPoint Channel" that
+   * has an "infitely" fast transmission speed and zero delay.
+   */
+  PointToPointChannel ();
+  
+  /**
+   * \brief Create a PointToPointChannel
+   *
+   * \param bps The maximum bitrate of the channel
+   * \param delay Transmission delay through the channel
+   */  
+  PointToPointChannel (const DataRate& bps, const Time& delay);
+  
+  /**
+   * \brief Create a PointToPointChannel
+   *
+   * \param name the name of the channel for identification purposes
+   * \param bps The maximum bitrate of the channel
+   * \param delay Transmission delay through the channel
+   */
+  PointToPointChannel (const std::string& name,
+                 const DataRate& bps, const Time& delay);
+
+  /**
+   * \brief Attach a given netdevice to this channel
+   * \param device pointer to the netdevice to attach to the channel
+   */
+  void Attach (Ptr<PointToPointNetDevice> device);
+  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);
+
+
+  virtual uint32_t GetNDevices (void) const;
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
+  virtual const DataRate& GetDataRate (void);
+  virtual const Time&     GetDelay (void);
+
+private:
+  DataRate      m_bps;
+  Time          m_delay;
+  int32_t       m_nDevices;
+
+  enum WireState
+    {
+      INITIALIZING,
+      IDLE,
+      TRANSMITTING,
+      PROPAGATING
+    };
+
+  class Link
+  {
+  public:
+    Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
+    WireState              m_state;
+    Ptr<PointToPointNetDevice> m_src;
+    Ptr<PointToPointNetDevice> m_dst;
+  };
+    
+  Link    m_link[N_DEVICES];
+};
+
+} // namespace ns3
+
+#endif /* POINT_TO_POINT_CHANNEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,244 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,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:  Craig Dowell <craigdo@ee.washington.edu>
+ * Revised: George Riley <riley@ece.gatech.edu>
+ */
+
+#include <iostream>
+#include <cassert>
+#include "ns3/debug.h"
+#include "ns3/queue.h"
+#include "ns3/simulator.h"
+#include "ns3/composite-trace-resolver.h"
+#include "point-to-point-net-device.h"
+#include "point-to-point-channel.h"
+#include "ns3/llc-snap-header.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("PointToPointNetDevice");
+
+namespace ns3 {
+
+DataRateDefaultValue PointToPointNetDevice::g_defaultRate(
+           "PointToPointLinkDataRate", 
+           "The default data rate for point to point links",
+           DataRate ("10Mb/s"));
+
+  PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
+                                                const DataRate& rate) 
+: 
+  NetDevice(node, MacAddress (6)), 
+  m_txMachineState (READY),
+  m_bps (rate),
+  m_tInterframeGap (Seconds(0)),
+  m_channel (0), 
+  m_queue (0),
+  m_rxTrace ()
+{
+  NS_DEBUG ("PointToPointNetDevice::PointToPointNetDevice (" << node << ")");
+
+  // BUGBUG FIXME
+  //
+  // You _must_ support broadcast to get any sort of packet from the ARP layer.
+  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+  EnableMulticast();
+  EnablePointToPoint();
+}
+
+PointToPointNetDevice::~PointToPointNetDevice()
+{
+  NS_DEBUG ("PointToPointNetDevice::~PointToPointNetDevice ()");
+  m_queue = 0;
+}
+
+void PointToPointNetDevice::AddHeader(Packet& p, const MacAddress& dest,
+                                      uint16_t protocolNumber)
+{
+  LlcSnapHeader llc;
+  llc.SetType (protocolNumber);
+  p.AddHeader (llc);
+}
+
+bool PointToPointNetDevice::ProcessHeader(Packet& p, uint16_t& param)
+{
+  LlcSnapHeader llc;
+  p.RemoveHeader (llc);
+
+  param = llc.GetType ();
+
+  return true;
+}
+
+void PointToPointNetDevice::DoDispose()
+{
+  m_channel = 0;
+  NetDevice::DoDispose ();
+}
+
+void PointToPointNetDevice::SetDataRate(const DataRate& bps)
+{
+  m_bps = bps;
+}
+
+void PointToPointNetDevice::SetInterframeGap(const Time& t)
+{
+  m_tInterframeGap = t;
+}
+
+bool PointToPointNetDevice::SendTo (Packet& p, const MacAddress& dest, 
+                                    uint16_t protocolNumber)
+{
+  NS_DEBUG ("PointToPointNetDevice::SendTo (" << &p << ", " << &dest << ")");
+  NS_DEBUG ("PointToPointNetDevice::SendTo (): UID is " << p.GetUid () << ")");
+
+  // GFR Comment. Why is this an assertion? Can't a link legitimately
+  // "go down" during the simulation?  Shouldn't we just wait for it
+  // to come back up?
+  NS_ASSERT (IsLinkUp ());
+  AddHeader(p, dest, protocolNumber);
+
+//
+// This class simulates a point to point device.  In the case of a serial
+// link, this means that we're simulating something like a UART.
+//
+//
+// If there's a transmission in progress, we enque the packet for later
+// trnsmission; otherwise we send it now.
+    if (m_txMachineState == READY) 
+      {
+        return TransmitStart (p);
+      }
+    else
+      {
+        return m_queue->Enqueue(p);
+      }
+}
+
+  bool
+PointToPointNetDevice::TransmitStart (Packet &p)
+{
+  NS_DEBUG ("PointToPointNetDevice::TransmitStart (" << &p << ")");
+  NS_DEBUG (
+    "PointToPointNetDevice::TransmitStart (): UID is " << p.GetUid () << ")");
+//
+// This function is called to start the process of transmitting a packet.
+// We need to tell the channel that we've started wiggling the wire and
+// schedule an event that will be executed when the transmission is complete.
+//
+  NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
+  m_txMachineState = BUSY;
+  Time txTime = Seconds (m_bps.CalculateTxTime(p.GetSize()));
+  Time txCompleteTime = txTime + m_tInterframeGap;
+
+  NS_DEBUG ("PointToPointNetDevice::TransmitStart (): " <<
+    "Schedule TransmitCompleteEvent in " << 
+    txCompleteTime.GetSeconds () << "sec");
+  // Schedule the tx complete event
+  Simulator::Schedule (txCompleteTime, 
+                       &PointToPointNetDevice::TransmitComplete, 
+                       this);
+  return m_channel->TransmitStart(p, this, txTime); 
+}
+
+void PointToPointNetDevice::TransmitComplete (void)
+{
+  NS_DEBUG ("PointToPointNetDevice::TransmitCompleteEvent ()");
+//
+// This function is called to finish the  process of transmitting a packet.
+// We need to tell the channel that we've stopped wiggling the wire and
+// get the next packet from the queue.  If the queue is empty, we are
+// done, otherwise transmit the next packet.
+//
+  NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
+  m_txMachineState = READY;
+  Packet p;
+  if (!m_queue->Dequeue(p)) return; // Nothing to do at this point
+  TransmitStart(p);
+}
+
+TraceResolver* PointToPointNetDevice::DoCreateTraceResolver (
+                                      TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("queue", 
+                 MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)),
+                 PointToPointNetDevice::QUEUE);
+  resolver->Add ("rx",
+                 m_rxTrace,
+                 PointToPointNetDevice::RX);
+  return resolver;
+}
+
+bool PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
+{
+  NS_DEBUG ("PointToPointNetDevice::Attach (" << &ch << ")");
+
+  m_channel = ch;
+
+  m_channel->Attach(this);
+  m_bps = m_channel->GetDataRate ();
+  // GFR Comment.  Below is definitely wrong.  Interframe gap
+  // is unrelated to channel delay.
+  //m_tInterframeGap = m_channel->GetDelay ();
+
+  /* 
+   * For now, this device is up whenever a channel is attached to it.
+   * In fact, it should become up only when the second device
+   * is attached to the channel. So, there should be a way for
+   * a PointToPointChannel to notify both of its attached devices
+   * that the channel is 'complete', hence that the devices are
+   * up, hence that they can call NotifyLinkUp. 
+   */
+  NotifyLinkUp ();
+  return true;
+}
+
+void PointToPointNetDevice::AddQueue (Ptr<Queue> q)
+{
+  NS_DEBUG ("PointToPointNetDevice::AddQueue (" << q << ")");
+
+  m_queue = q;
+}
+
+void PointToPointNetDevice::Receive (Packet& p)
+{
+  NS_DEBUG ("PointToPointNetDevice::Receive (" << &p << ")");
+  uint16_t param = 0;
+  Packet packet = p;
+
+  ProcessHeader(packet, param);
+  m_rxTrace (packet);
+  ForwardUp (packet, param);
+}
+
+Ptr<Queue> PointToPointNetDevice::GetQueue(void) const 
+{ 
+    return m_queue;
+}
+
+Ptr<Channel> PointToPointNetDevice::DoGetChannel(void) const 
+{ 
+    return m_channel;
+}
+
+bool PointToPointNetDevice::DoNeedsArp (void) const
+{
+  return false;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,305 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ *
+ * 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: Craig Dowell <craigdo@ee.washington.edu>
+ */
+
+#ifndef POINT_TO_POINT_NET_DEVICE_H
+#define POINT_TO_POINT_NET_DEVICE_H
+
+#include <string.h>
+#include "ns3/mac-address.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/callback-trace-source.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Queue;
+class PointToPointChannel;
+
+/**
+ * \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.
+ */
+class PointToPointNetDevice : public NetDevice {
+public:
+  /**
+   * Enumeration of the types of traces supported in the class.
+   *
+   */
+  enum TraceType {
+    QUEUE, /**< Trace queue events on the attached queue */
+    RX,    /**< Trace packet reception events (from the channel) */
+  };
+  /**
+   * 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.
+   *
+   * @see PointToPointTopology::AddPointToPointLink ()
+   * @param node the Node to which this device is connected.
+   */
+  PointToPointNetDevice (Ptr<Node> node,
+                         const DataRate& = g_defaultRate.GetValue());
+  /**
+   * Destroy a PointToPointNetDevice
+   *
+   * This is the destructor for the 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
+   * to which the device is attached.  It can be overridden using this method.
+   *
+   * @see Attach ()
+   * @param bps the data rate at which this object operates
+   */
+  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.
+   * It is usually set in the Attach () method based on the speed of light
+   * delay of the channel to which the device is attached.  It can be 
+   * overridden using this method if desired.
+   *
+   * @see Attach ()
+   * @param t the interframe gap time
+   */
+  void SetInterframeGap(const Time& t);
+  /**
+   * Attach the device to a channel.
+   *
+   * The PointToPointTopology object creates a PointToPointChannel and two
+   * PointtoPointNetDevices.  In order to introduce these components to each
+   * other, the topology object calls Attach () on each PointToPointNetDevice.
+   * Inside this method, the Net Device calls out to the PointToPointChannel
+   * to introduce itself.
+   *
+   * @see PointToPointTopology::AddPointToPointLink ()
+   * @see SetDataRate ()
+   * @see SetInterframeGap ()
+   * @param ch a pointer to the channel to which this object is being attached.
+   */
+  bool Attach(Ptr<PointToPointChannel> ch);
+  /**
+   * Attach a queue to the PointToPointNetDevice.
+   *
+   * The PointToPointNetDevice "owns" a queue.  This queue is created by the
+   * PointToPointTopology object and implements a queueing method such as
+   * DropTail or RED.  The PointToPointNetDevice assumes ownership of this
+   * queue and must delete it when the device is destroyed.
+   *
+   * @see PointToPointTopology::AddPointToPointLink ()
+   * @see Queue
+   * @see DropTailQueue
+   * @param queue a pointer to the queue for which object is assuming
+   *        ownership.
+   */
+  void AddQueue(Ptr<Queue> queue);
+  /**
+   * Receive a packet from a connected PointToPointChannel.
+   *
+   * The PointToPointNetDevice receives packets from its connected channel
+   * and forwards them up the protocol stack.  This is the public method
+   * used by the channel to indicate that the last bit of a packet has 
+   * arrived at the device.
+   *
+   * @see PointToPointChannel
+   * @param p a reference to the received packet
+   */
+  void Receive (Packet& p);
+protected:
+  virtual void DoDispose (void);
+  /**
+   * Get a copy of the attached Queue.
+   *
+   * This method is provided for any derived class that may need to get
+   * direct access to the underlying queue.
+   *
+   * @see PointToPointTopology
+   * @returns a pointer to the queue.
+   */
+  Ptr<Queue> GetQueue(void) const; 
+  /**
+   * Get a copy of the attached Channel
+   *
+   * This method is provided for any derived class that may need to get
+   * direct access to the connected channel
+   *
+   * @see PointToPointChannel
+   * @returns a pointer to the channel
+   */
+  virtual Ptr<Channel> DoGetChannel(void) const;
+  /**
+   * Set a new default data rate
+   * @param Data rate to set for new default
+   */
+  static void SetDefaultRate(const DataRate&);
+
+  /** 
+   * Get the current default rate.
+   * @returns a const reference to current default
+   */
+
+  static const DataRate& GetDefaultRate();
+
+private:
+  /**
+   * Adds the necessary headers and trailers to a packet of data in order to
+   * respect the protocol implemented by the agent.
+   */
+  void AddHeader(Packet& p, const MacAddress& dest, uint16_t protocolNumber);
+  /**
+   * Removes, from a packet of data, all headers and trailers that
+   * relate to the protocol implemented by the agent
+   * \return Returns true if the packet should be forwarded up the
+   * protocol stack.
+   */
+  bool ProcessHeader(Packet& p, uint16_t& param);
+  /**
+   * Send a Packet Down the Wire.
+   *
+   * The SendTo method is defined as the standard way that the level three
+   * protocol uses to tell a NetDevice to send a packet.  SendTo is declared
+   * as abstract in the NetDevice class and we declare it here.
+   *
+   * @see NetDevice
+   * @param p a reference to the packet to send
+   * @param dest a reference to the MacAddress of the destination device
+   * @param protocolNumber Protocol Number used to find protocol touse
+   * @returns true if success, false on failure
+   */
+  virtual bool SendTo (Packet& p, const MacAddress& dest, 
+                       uint16_t protocolNumber);
+  /**
+   * Start Sending a Packet Down the Wire.
+   *
+   * The TransmitStart method is the method that is used internally in the
+   * PointToPointNetDevice to begin the process of sending a packet out on
+   * the channel.  The corresponding method is called on the channel to let
+   * it know that the physical device this class represents has virually
+   * started sending signals.  An event is scheduled for the time at which
+   * the bits have been completely transmitted.
+   *
+   * @see PointToPointChannel::TransmitStart ()
+   * @see TransmitCompleteEvent ()
+   * @param p a reference to the packet to send
+   * @returns true if success, false on failure
+   */
+  bool TransmitStart (Packet &p);
+  /**
+   * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
+   *
+   * The TransmitComplete method is used internally to finish the process
+   * of sending a packet out on the channel.
+   *
+   */
+  void TransmitComplete(void);
+  /**
+   * Create a Trace Resolver for events in the net device.
+   *
+   * @see class TraceResolver
+   */
+  virtual TraceResolver* DoCreateTraceResolver (TraceContext const &context);
+  virtual bool DoNeedsArp (void) const;
+  /**
+   * Enumeration of the states of the transmit machine of the net device.
+   */
+  enum TxMachineState
+    {
+      READY, /**< The transmitter is ready to begin transmission of a packet */
+      BUSY   /**< The transmitter is busy transmitting a packet */
+    };
+  /**
+   * The state of the Net Device transmit state machine.
+   * @see TxMachineState
+   */
+  TxMachineState m_txMachineState;
+  /**
+   * The data rate that the Net Device uses to simulate packet transmission
+   * timing.
+   * @see class DataRate
+   */
+  DataRate       m_bps;
+  /**
+   * The interframe gap that the Net Device uses to throttle packet
+   * transmission
+   * @see class Time
+   */
+  Time           m_tInterframeGap;
+  /**
+   * The PointToPointChannel to which this PointToPointNetDevice has been
+   * attached.
+   * @see class PointToPointChannel
+   */
+  Ptr<PointToPointChannel> m_channel;
+  /**
+   * The Queue which this PointToPointNetDevice uses as a packet source.
+   * Management of this Queue has been delegated to the PointToPointNetDevice
+   * and it has the responsibility for deletion.
+   * @see class Queue
+   * @see class DropTailQueue
+   */
+  Ptr<Queue> m_queue;
+  /**
+   * The trace source for the packet reception events that the device can
+   * fire.
+   *
+   * @see class CallBackTraceSource
+   * @see class TraceResolver
+   */
+  CallbackTraceSource<Packet &> m_rxTrace;
+  /** 
+   * Default data rate.  Used for all newly created p2p net devices
+   */
+   static DataRateDefaultValue g_defaultRate;
+
+};
+
+}; // namespace ns3
+
+#endif // POINT_TO_POINT_NET_DEVICE_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+//
+// Topology helper for ns3.
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include <algorithm>
+#include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/fatal-error.h"
+#include "ns3/nstime.h"
+#include "ns3/internet-node.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/queue.h"
+
+#include "point-to-point-channel.h"
+#include "point-to-point-net-device.h"
+#include "point-to-point-topology.h"
+
+namespace ns3 {
+
+Ptr<PointToPointChannel>
+PointToPointTopology::AddPointToPointLink(
+  Ptr<Node> n1,
+  Ptr<Node> n2,
+  const DataRate& bps,
+  const Time& delay)
+{
+  Ptr<PointToPointChannel> channel = Create<PointToPointChannel> (bps, delay);
+
+  Ptr<PointToPointNetDevice> net1 = Create<PointToPointNetDevice> (n1);
+
+  Ptr<Queue> q = Queue::CreateDefault ();
+  net1->AddQueue(q);
+  net1->Attach (channel);
+  
+  Ptr<PointToPointNetDevice> net2 = Create<PointToPointNetDevice> (n2);
+
+  q = Queue::CreateDefault ();
+  net2->AddQueue(q);
+  net2->Attach (channel);
+
+  return channel;
+}
+
+void
+PointToPointTopology::AddIpv4Addresses(
+  Ptr<const PointToPointChannel> chan,
+  Ptr<Node> n1, const Ipv4Address& addr1,
+  Ptr<Node> n2, const Ipv4Address& addr2)
+{
+
+  // Duplex link is assumed to be subnetted as a /30
+  // May run this unnumbered in the future?
+  Ipv4Mask netmask("255.255.255.252");
+  NS_ASSERT (netmask.IsMatch(addr1,addr2));
+
+  // 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 ());
+  
+  Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
+  uint32_t index1 = ip1->AddInterface (nd1);
+
+  ip1->SetAddress (index1, addr1);
+  ip1->SetNetworkMask (index1, netmask);
+  ip1->SetUp (index1);
+
+  Ptr<Ipv4> ip2 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  uint32_t index2 = ip2->AddInterface (nd2);
+
+  ip2->SetAddress (index2, addr2);
+  ip2->SetNetworkMask (index2, netmask);
+  ip2->SetUp (index2);
+  
+}
+
+void
+PointToPointTopology::AddIpv4Routes (
+  Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> chan)
+{ 
+  // 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);
+
+  // Assert that n1 is the Node owning one of the two NetDevices
+  // and make sure that nd1 corresponds to it
+  if (nd1->GetNode ()->GetId () == n1->GetId ())
+    {
+      ; // Do nothing
+    }
+  else if (nd2->GetNode ()->GetId () == n1->GetId ())
+    {
+      std::swap(nd1, nd2);
+    }
+  else
+    {
+      NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
+    }
+
+   // Assert that n2 is the Node owning one of the two NetDevices
+   // and make sure that nd2 corresponds to it
+  if (nd2->GetNode ()->GetId () != n2->GetId ())
+    {
+      NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
+    }
+
+  // Assert that both are Ipv4 nodes
+  Ptr<Ipv4> ip1 = nd1->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
+  Ptr<Ipv4> ip2 = nd2->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
+  NS_ASSERT(ip1 != 0 && ip2 != 0);
+
+  // Get interface indexes for both nodes corresponding to the right channel
+  uint32_t index1 = 0;
+  bool found = false;
+  for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
+    {
+      if (ip1 ->GetNetDevice (i) == nd1)
+        {
+          index1 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  uint32_t index2 = 0;
+  found = false;
+  for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
+    {
+      if (ip2 ->GetNetDevice (i) == nd2)
+        {
+          index2 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
+  ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); 
+}
+
+} // namespace ns3
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-topology.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,87 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+// Topology helper for ns3.
+// George F. Riley, Georgia Tech, Spring 2007
+#ifndef __POINT_TO_POINT_TOPOLOGY_H__
+#define __POINT_TO_POINT_TOPOLOGY_H__
+
+#include "ns3/ptr.h"
+
+// The topology class consists of only static methods thar are used to
+// create the topology and data flows for an ns3 simulation
+
+namespace ns3 {
+
+class PointToPointChannel;
+class Node;
+class IPAddr;
+class DataRate;
+class Queue;
+
+/**
+ * \brief A helper class to create Topologies based on the 
+ * ns3::PointToPointNetDevice and  ns3::PointToPointChannel objects.
+ */
+class PointToPointTopology {
+public:
+  /** 
+   * \param n1 Node
+   * \param n2 Node
+   * \param dataRate Maximum transmission link rate 
+   * \param delay one-way propagation delay 
+   * \return Pointer to the underlying PointToPointChannel
+   * 
+   * Add a full-duplex point-to-point link between two nodes
+   * and attach PointToPointNetDevices to the resulting
+   * PointToPointChannel.  
+   */
+  static Ptr<PointToPointChannel> AddPointToPointLink(
+    Ptr<Node> n1, Ptr<Node> n2, const DataRate& dataRate, const Time& delay);
+
+  /** 
+   * \param chan PointToPointChannel to use
+   * \param n1 Node
+   * \param addr1 Ipv4 Address for n1
+   * \param n2 Node
+   * \param addr2 Ipv4 Address for n2
+   * 
+   * Add Ipv4Addresses to the Ipv4 interfaces associated with the 
+   * two PointToPointNetDevices on the provided PointToPointChannel
+   */
+  static void AddIpv4Addresses(
+    Ptr<const PointToPointChannel> chan,
+    Ptr<Node> n1, const Ipv4Address& addr1,
+    Ptr<Node> n2, const Ipv4Address& addr2);
+
+  /**
+   * \param channel PointToPointChannel to use
+   * \param n1 Node
+   * \param n2 Node
+   * 
+   * For the given PointToPointChannel, for each Node, add an 
+   * IPv4 host route to the IPv4 address of the peer node.  
+   */
+  static void AddIpv4Routes (Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> channel);
+};
+
+} // namespace ns3
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,20 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    module = bld.create_obj('cpp', 'shlib')
+    module.name = 'ns3-point-to-point'
+    module.target = module.name
+    module.uselib_local = ['ns3-node']
+    module.source = [
+        'point-to-point-net-device.cc',
+        'point-to-point-channel.cc',
+        'point-to-point-topology.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'point-to-point-net-device.h',
+        'point-to-point-channel.h',
+        'point-to-point-topology.h',
+        ]
+
--- a/src/internet-node/arp-cache.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/arp-cache.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -109,6 +109,8 @@
 ArpCache::Entry *
 ArpCache::Add (Ipv4Address to)
 {
+  NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());
+
   ArpCache::Entry *entry = new ArpCache::Entry (this);
   m_arpCache[to] = entry;  
   return entry;
--- a/src/internet-node/arp-header.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/arp-header.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -20,8 +20,8 @@
  */
 
 #include "ns3/assert.h"
+#include "ns3/address-utils.h"
 #include "arp-header.h"
-#include "header-utils.h"
 
 namespace ns3 {
 
--- a/src/internet-node/arp-ipv4-interface.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/arp-ipv4-interface.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -21,6 +21,7 @@
  */
 
 #include "ns3/packet.h"
+#include "ns3/debug.h"
 #include "ns3/composite-trace-resolver.h"
 #include "ns3/node.h"
 #include "ns3/net-device.h"
@@ -60,7 +61,19 @@
     {
       Ptr<ArpPrivate> arp = m_node->QueryInterface<ArpPrivate> (ArpPrivate::iid);
       MacAddress hardwareDestination;
-      bool found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination);
+      bool found;
+
+      if (dest.IsBroadcast ())
+        {
+           hardwareDestination = GetDevice ()->GetBroadcast ();
+           found = true;
+        }
+      else
+        {
+          Ptr<ArpPrivate> arp = m_node->QueryInterface<ArpPrivate> (ArpPrivate::iid);
+          found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination);
+        }
+
       if (found)
         {
           GetDevice ()->Send (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER);
--- a/src/internet-node/arp-l3-protocol.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/arp-l3-protocol.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -87,6 +87,13 @@
   ArpCache *cache = FindCache (device);
   ArpHeader arp;
   packet.RemoveHeader (arp);
+  
+  NS_DEBUG ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
+            " node="<<m_node->GetId ()<<", got request from " <<
+            arp.GetSourceIpv4Address () << " for address " <<
+            arp.GetDestinationIpv4Address () << "; we have address " <<
+            cache->GetInterface ()->GetAddress ());
+
   if (arp.IsRequest () && 
       arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) 
     {
@@ -128,6 +135,12 @@
 	  // XXX report packet as dropped.
         }
     }
+  else
+    {
+      NS_DEBUG ("node="<<m_node->GetId ()<<", got request from " <<
+                arp.GetSourceIpv4Address () << " for unknown address " <<
+                arp.GetDestinationIpv4Address () << " -- drop");
+    }
 }
 bool 
 ArpL3Protocol::Lookup (Packet &packet, Ipv4Address destination, 
@@ -203,6 +216,11 @@
 ArpL3Protocol::SendArpRequest (ArpCache const *cache, Ipv4Address to)
 {
   ArpHeader arp;
+  NS_DEBUG ("ARP: sending request from node "<<m_node->GetId ()<<
+            " || src: " << cache->GetDevice ()->GetAddress () <<
+            " / " << cache->GetInterface ()->GetAddress () <<
+            " || dst: " << cache->GetDevice ()->GetBroadcast () <<
+            " / " << to);
   arp.SetRequest (cache->GetDevice ()->GetAddress (),
 		  cache->GetInterface ()->GetAddress (), 
                   cache->GetDevice ()->GetBroadcast (),
@@ -216,6 +234,10 @@
 ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, MacAddress toMac)
 {
   ArpHeader arp;
+  NS_DEBUG ("ARP: sending reply from node "<<m_node->GetId ()<<
+            "|| src: " << cache->GetDevice ()->GetAddress () << 
+            " / " << cache->GetInterface ()->GetAddress () <<
+            " || dst: " << toMac << " / " << toIp);
   arp.SetReply (cache->GetDevice ()->GetAddress (),
                 cache->GetInterface ()->GetAddress (),
                 toMac, toIp);
--- a/src/internet-node/header-utils.cc	Fri Aug 03 08:23:23 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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 "header-utils.h"
-
-namespace ns3 {
-
-void WriteTo (Buffer::Iterator &i, Ipv4Address ad)
-{
-  i.WriteHtonU32 (ad.GetHostOrder ());
-}
-void WriteTo (Buffer::Iterator &i, MacAddress ad)
-{
-  uint8_t mac[MacAddress::MAX_LEN];
-  ad.Peek (mac);
-  i.Write (mac, ad.GetLength ());
-}
-
-void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad)
-{
-  ad.SetHostOrder (i.ReadNtohU32 ());
-}
-void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len)
-{
-  uint8_t mac[MacAddress::MAX_LEN];
-  i.Read (mac, len);
-  ad.Set (mac, len);
-}
-
-
-
-}; // namespace ns3
--- a/src/internet-node/header-utils.h	Fri Aug 03 08:23:23 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +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 HEADER_UTILS_H
-#define HEADER_UTILS_H
-
-#include "ns3/buffer.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/mac-address.h"
-
-namespace ns3 {
-
-void WriteTo (Buffer::Iterator &i, Ipv4Address ad);
-void WriteTo (Buffer::Iterator &i, MacAddress ad);
-
-void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad);
-void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len);
-
-};
-
-#endif /* HEADER_UTILS_H */
--- a/src/internet-node/internet-node.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/internet-node.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -96,7 +96,7 @@
 }
 
 void 
-InternetNode::DoAddDevice (Ptr<NetDevice> device) const
+InternetNode::DoAddDevice (Ptr<NetDevice> device)
 {
   device->SetReceiveCallback (MakeCallback (&InternetNode::ReceiveFromDevice, this));
 }
--- a/src/internet-node/internet-node.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/internet-node.h	Fri Aug 03 08:29:24 2007 -0700
@@ -46,7 +46,7 @@
 protected:
   virtual void DoDispose(void);
 private:
-  virtual void DoAddDevice (Ptr<NetDevice> device) const;
+  virtual void DoAddDevice (Ptr<NetDevice> device);
   virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
   bool ReceiveFromDevice (Ptr<NetDevice> device, const Packet &p, uint16_t protocolNumber) const;
   void Construct (void);
--- a/src/internet-node/ipv4-end-point-demux.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-end-point-demux.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -21,9 +21,12 @@
 
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
+#include "ns3/debug.h"
 
 namespace ns3{
 
+NS_DEBUG_COMPONENT_DEFINE ("Ipv4EndPointDemux");
+
 Ipv4EndPointDemux::Ipv4EndPointDemux ()
   : m_ephemeral (1025)
 {}
@@ -68,9 +71,11 @@
 Ipv4EndPoint *
 Ipv4EndPointDemux::Allocate (void)
 {
+  NS_DEBUG ("Ipv4EndPointDemux::Allocate ()");
   uint16_t port = AllocateEphemeralPort ();
   if (port == 0) 
     {
+      NS_DEBUG ("Ipv4EndPointDemux::Allocate ephemeral port allocation failed.");
       return 0;
     }
   Ipv4EndPoint *endPoint = new Ipv4EndPoint (Ipv4Address::GetAny (), port);
@@ -80,9 +85,11 @@
 Ipv4EndPoint *
 Ipv4EndPointDemux::Allocate (Ipv4Address address)
 {
+  NS_DEBUG ("Ipv4EndPointDemux::Allocate (address=" << address << ")");
   uint16_t port = AllocateEphemeralPort ();
   if (port == 0) 
     {
+      NS_DEBUG ("Ipv4EndPointDemux::Allocate ephemeral port allocation failed.");
       return 0;
     }
   Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
@@ -97,8 +104,11 @@
 Ipv4EndPoint *
 Ipv4EndPointDemux::Allocate (Ipv4Address address, uint16_t port)
 {
+  NS_DEBUG ("Ipv4EndPointDemux::Allocate (address=" << address
+            << ", port=" << port << ")");
   if (LookupLocal (address, port)) 
     {
+      NS_DEBUG ("Ipv4EndPointDemux::Allocate duplicate address/port; failing.");
       return 0;
     }
   Ipv4EndPoint *endPoint = new Ipv4EndPoint (address, port);
@@ -110,6 +120,10 @@
 Ipv4EndPointDemux::Allocate (Ipv4Address localAddress, uint16_t localPort,
 			     Ipv4Address peerAddress, uint16_t peerPort)
 {
+  NS_DEBUG ("Ipv4EndPointDemux::Allocate (localAddress=" << localAddress
+            << ", localPort=" << localPort
+            << ", peerAddress=" << peerAddress
+            << ", peerPort=" << peerPort << ")");
   for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
     {
       if ((*i)->GetLocalPort () == localPort &&
@@ -117,6 +131,7 @@
           (*i)->GetPeerPort () == peerPort &&
           (*i)->GetPeerAddress () == peerAddress) 
         {
+          NS_DEBUG ("Ipv4EndPointDemux::Allocate: no way we can allocate this end-point.");
           /* no way we can allocate this end-point. */
           return 0;
         }
@@ -147,35 +162,46 @@
  * Otherwise, if we find a generic match, we return it.
  * Otherwise, we return 0.
  */
-Ipv4EndPoint *
+Ipv4EndPointDemux::EndPoints
 Ipv4EndPointDemux::Lookup (Ipv4Address daddr, uint16_t dport, 
-                              Ipv4Address saddr, uint16_t sport)
+                           Ipv4Address saddr, uint16_t sport)
 {
   uint32_t genericity = 3;
   Ipv4EndPoint *generic = 0;
-  //TRACE ("lookup " << daddr << ":" << dport << " " << saddr << ":" << sport);
+  EndPoints retval;
+
+  NS_DEBUG ("Ipv4EndPointDemux::Lookup (daddr=" << daddr << ", dport=" << dport
+            << ", saddr=" << saddr << ", sport=" << sport
+            << ")");
   for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
     {
-#if 0
-      TRACE ("against " << 
-             (*i)->GetLocalAddress ()
-             << ":" << 
-             (*i)->GetLocalPort () 
-             << " " << 
-             (*i)->GetPeerAddress () 
-             << ":" 
-             << (*i)->GetPeerPort ());
-#endif
+      NS_DEBUG ("Ipv4EndPointDemux::Lookup against " << 
+                (*i)->GetLocalAddress ()
+                << ":" << 
+                (*i)->GetLocalPort () 
+                << " " << 
+                (*i)->GetPeerAddress () 
+                << ":" 
+                << (*i)->GetPeerPort ());
       if ((*i)->GetLocalPort () != dport) 
         {
           continue;
         }
-      if ((*i)->GetLocalAddress () == daddr &&
-          (*i)->GetPeerPort () == sport &&
-          (*i)->GetPeerAddress () == saddr) 
+      NS_DEBUG ("Ipv4EndPointDemux::Lookup local address matches: "
+                << bool ((*i)->GetLocalAddress () == daddr || daddr.IsBroadcast ()));
+      NS_DEBUG ("Ipv4EndPointDemux::Lookup peer port matches: "
+                << bool ((*i)->GetPeerPort () == sport || sport == 0));
+      NS_DEBUG ("Ipv4EndPointDemux::Lookup peer address matches: "
+                << bool ((*i)->GetPeerAddress () == saddr ||
+                         (*i)->GetPeerAddress () == Ipv4Address::GetAny ()));
+      
+      if ( ((*i)->GetLocalAddress () == daddr || daddr.IsBroadcast ())
+           && ((*i)->GetPeerPort () == sport || (*i)->GetPeerPort () == 0)
+           && ((*i)->GetPeerAddress () == saddr || (*i)->GetPeerAddress () == Ipv4Address::GetAny ()))
         {
+          NS_DEBUG ("Ipv4EndPointDemux::Lookup MATCH");
           /* this is an exact match. */
-          return *i;
+          retval.push_back (*i);
         }
       uint32_t tmp = 0;
       if ((*i)->GetLocalAddress () == Ipv4Address::GetAny ()) 
@@ -192,7 +218,11 @@
           genericity = tmp;
         }
     }
-  return generic;
+  if (retval.size () == 0 && generic != 0)
+    {
+      retval.push_back (generic);
+    }
+  return retval;
 }
 
 uint16_t
--- a/src/internet-node/ipv4-end-point-demux.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-end-point-demux.h	Fri Aug 03 08:29:24 2007 -0700
@@ -32,15 +32,18 @@
 
 class Ipv4EndPointDemux {
 public:
+  typedef std::list<Ipv4EndPoint *> EndPoints;
+  typedef std::list<Ipv4EndPoint *>::iterator EndPointsI;
+
   Ipv4EndPointDemux ();
   ~Ipv4EndPointDemux ();
 
   bool LookupPortLocal (uint16_t port);
   bool LookupLocal (Ipv4Address addr, uint16_t port);
-  Ipv4EndPoint *Lookup (Ipv4Address daddr, 
-                        uint16_t dport, 
-                        Ipv4Address saddr, 
-                        uint16_t sport);
+  EndPoints Lookup (Ipv4Address daddr, 
+                    uint16_t dport, 
+                    Ipv4Address saddr, 
+                    uint16_t sport);
 
   Ipv4EndPoint *Allocate (void);
   Ipv4EndPoint *Allocate (Ipv4Address address);
@@ -55,8 +58,6 @@
 
  private:
   uint16_t AllocateEphemeralPort (void);
-  typedef std::list<Ipv4EndPoint *> EndPoints;
-  typedef std::list<Ipv4EndPoint *>::iterator EndPointsI;
 
   uint16_t m_ephemeral;
   EndPoints m_endPoints;
--- a/src/internet-node/ipv4-impl.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-impl.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -39,6 +39,13 @@
   m_ipv4 = 0;
 }
 
+void
+Ipv4Impl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+                              int16_t priority)
+{
+  m_ipv4->AddRoutingProtocol (routingProtocol, priority);
+}
+
 void 
 Ipv4Impl::AddHostRouteTo (Ipv4Address dest, 
 			   Ipv4Address nextHop, 
--- a/src/internet-node/ipv4-impl.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-impl.h	Fri Aug 03 08:29:24 2007 -0700
@@ -35,6 +35,9 @@
 
   virtual ~Ipv4Impl ();
 
+  virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+                                   int16_t priority);
+
   virtual void AddHostRouteTo (Ipv4Address dest, 
 			       Ipv4Address nextHop, 
 			       uint32_t interface);
--- a/src/internet-node/ipv4-l3-protocol.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -48,9 +48,10 @@
     m_nInterfaces (0),
     m_defaultTtl (64),
     m_identification (0),
-    m_defaultRoute (0),
     m_node (node)
 {
+  m_staticRouting = Create<Ipv4StaticRouting> ();
+  AddRoutingProtocol (m_staticRouting, 0);
   SetupLoopback ();
 }
 Ipv4L3Protocol::~Ipv4L3Protocol ()
@@ -64,25 +65,10 @@
       delete (*i);
     }
   m_interfaces.clear ();
-  for (HostRoutesI i = m_hostRoutes.begin (); 
-       i != m_hostRoutes.end (); 
-       i = m_hostRoutes.erase (i)) 
-    {
-      delete (*i);
-    }
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j = m_networkRoutes.erase (j)) 
-    {
-      delete (*j);
-    }
-  if (m_defaultRoute != 0)
-    {
-      delete m_defaultRoute;
-      m_defaultRoute = 0;
-    }
   m_node = 0;
   L3Protocol::DoDispose ();
+  m_staticRouting->Dispose ();
+  m_staticRouting = 0;
 }
 
 void
@@ -132,17 +118,13 @@
                       Ipv4Address nextHop, 
                       uint32_t interface)
 {
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
-  m_hostRoutes.push_back (route);
+  m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
 }
 void 
 Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
 				uint32_t interface)
 {
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, interface);
-  m_hostRoutes.push_back (route);
+  m_staticRouting->AddHostRouteTo (dest, interface);
 }
 void 
 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
@@ -150,163 +132,63 @@
 				   Ipv4Address nextHop, 
 				   uint32_t interface)
 {
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
-                                            networkMask,
-                                            nextHop,
-                                            interface);
-  m_networkRoutes.push_back (route);
+  m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
 }
 void 
 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
 				   Ipv4Mask networkMask, 
 				   uint32_t interface)
 {
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
-                                            networkMask,
-                                            interface);
-  m_networkRoutes.push_back (route);
+  m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
 }
 void 
 Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, 
 				 uint32_t interface)
 {
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
-  delete m_defaultRoute;
-  m_defaultRoute = route;
+  m_staticRouting->SetDefaultRoute (nextHop, interface);
 }
 
-Ipv4Route *
-Ipv4L3Protocol::Lookup (Ipv4Address dest)
+
+void
+Ipv4L3Protocol::Lookup (Ipv4Header const &ipHeader,
+                        Packet packet,
+                        Ipv4RoutingProtocol::RouteReplyCallback routeReply)
 {
-  for (HostRoutesCI i = m_hostRoutes.begin (); 
-       i != m_hostRoutes.end (); 
-       i++) 
+  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++)
     {
-      NS_ASSERT ((*i)->IsHost ());
-      if ((*i)->GetDest ().IsEqual (dest)) 
-        {
-          return (*i);
-        }
+      if ((*rprotoIter).second->RequestRoute (ipHeader, packet, routeReply))
+        return;
     }
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      NS_ASSERT ((*j)->IsNetwork ());
-      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
-      Ipv4Address entry = (*j)->GetDestNetwork ();
-      if (mask.IsMatch (dest, entry)) 
-        {
-          return (*j);
-        }
-    }
-  if (m_defaultRoute != 0) 
-    {
-      NS_ASSERT (m_defaultRoute->IsDefault ());
-      return m_defaultRoute;
-    }
-  return 0;
+  // No route found
+  routeReply (false, Ipv4Route (), packet, ipHeader);
+}
+
+void
+Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+                                    int priority)
+{
+  m_routingProtocols.push_back
+    (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
+  m_routingProtocols.sort ();
 }
 
 uint32_t 
 Ipv4L3Protocol::GetNRoutes (void)
 {
-  uint32_t n = 0;
-  if (m_defaultRoute != 0)
-    {
-      n++;
-    }
-  n += m_hostRoutes.size ();
-  n += m_networkRoutes.size ();
-  return n;
+  return m_staticRouting->GetNRoutes ();
 }
+
 Ipv4Route *
 Ipv4L3Protocol::GetRoute (uint32_t index)
 {
-  if (index == 0 && m_defaultRoute != 0)
-    {
-      return m_defaultRoute;
-    }
-  if (index > 0 && m_defaultRoute != 0)
-    {
-      index--;
-    }
-  if (index < m_hostRoutes.size ())
-    {
-      uint32_t tmp = 0;
-      for (HostRoutesCI i = m_hostRoutes.begin (); 
-           i != m_hostRoutes.end (); 
-           i++) 
-        {
-          if (tmp  == index)
-            {
-              return *i;
-            }
-          tmp++;
-        }
-    }
-  index -= m_hostRoutes.size ();
-  uint32_t tmp = 0;
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      if (tmp == index)
-        {
-          return *j;
-        }
-      tmp++;
-    }
-  NS_ASSERT (false);
-  // quiet compiler.
-  return 0;
+  return m_staticRouting->GetRoute (index);
 }
+
 void 
 Ipv4L3Protocol::RemoveRoute (uint32_t index)
 {
-  if (index == 0 && m_defaultRoute != 0)
-    {
-      delete m_defaultRoute;
-      m_defaultRoute = 0;
-    }
-  if (index > 0 && m_defaultRoute != 0)
-    {
-      index--;
-    }
-  if (index < m_hostRoutes.size ())
-    {
-      uint32_t tmp = 0;
-      for (HostRoutesI i = m_hostRoutes.begin (); 
-           i != m_hostRoutes.end (); 
-           i++) 
-        {
-          if (tmp  == index)
-            {
-              delete *i;
-              m_hostRoutes.erase (i);
-              return;
-            }
-          tmp++;
-        }
-    }
-  index -= m_hostRoutes.size ();
-  uint32_t tmp = 0;
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      if (tmp == index)
-        {
-          delete *j;
-          m_networkRoutes.erase (j);
-          return;
-        }
-      tmp++;
-    }
-  NS_ASSERT (false);
+  m_staticRouting->RemoveRoute (index);
 }
 
 
@@ -386,6 +268,7 @@
   ForwardUp (packet, ipHeader);
 }
 
+
 void 
 Ipv4L3Protocol::Send (Packet const &packet, 
             Ipv4Address source, 
@@ -404,30 +287,49 @@
 
   m_identification ++;
 
-  // XXX Note here that in most ipv4 stacks in the world,
-  // the route calculation for an outgoing packet is not
-  // done in the ip layer. It is done within the application
-  // socket when the first packet is sent to avoid this
-  // costly lookup on a per-packet basis.
-  // That would require us to get the route from the packet,
-  // most likely with a packet tag. The higher layers do not
-  // do this yet for us.
-  Ipv4Route *route = Lookup (ipHeader.GetDestination ());
-  if (route == 0) 
+  if (destination.IsBroadcast ())
+    {
+      uint32_t ifaceIndex = 0;
+      for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+           ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+        {
+          Ipv4Interface *outInterface = *ifaceIter;
+          Packet packetCopy = packet;
+
+          NS_ASSERT (packetCopy.GetSize () <= outInterface->GetMtu ());
+          packetCopy.AddHeader (ipHeader);
+          m_txTrace (packetCopy, ifaceIndex);
+          outInterface->Send (packetCopy, destination);
+        }
+    }
+  else
     {
-      NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
+      // XXX Note here that in most ipv4 stacks in the world,
+      // the route calculation for an outgoing packet is not
+      // done in the ip layer. It is done within the application
+      // socket when the first packet is sent to avoid this
+      // costly lookup on a per-packet basis.
+      // That would require us to get the route from the packet,
+      // most likely with a packet tag. The higher layers do not
+      // do this yet for us.
+      Lookup (ipHeader, packet,
+              MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+    }
+}
+
+void
+Ipv4L3Protocol::SendRealOut (bool found,
+                             Ipv4Route const &route,
+                             Packet packet,
+                             Ipv4Header const &ipHeader)
+{
+  if (!found)
+    {
+      NS_DEBUG ("no route to host. drop.");
       m_dropTrace (packet);
       return;
     }
-
-  SendRealOut (packet, ipHeader, *route);
-}
-
-void
-Ipv4L3Protocol::SendRealOut (Packet const &p, Ipv4Header const &ip, Ipv4Route const &route)
-{
-  Packet packet = p;
-  packet.AddHeader (ip);
+  packet.AddHeader (ipHeader);
   Ipv4Interface *outInterface = GetInterface (route.GetInterface ());
   NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ());
   m_txTrace (packet, route.GetInterface ());
@@ -437,7 +339,7 @@
     } 
   else 
     {
-      outInterface->Send (packet, ip.GetDestination ());
+      outInterface->Send (packet, ipHeader.GetDestination ());
     }
 }
 
@@ -470,7 +372,7 @@
 	}
     }
       
-  if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetBroadcast ())) 
+  if (ipHeader.GetDestination ().IsBroadcast ()) 
     {
       NS_DEBUG ("for me 3");
       return false;
@@ -489,15 +391,10 @@
       return true;
     }
   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
-  Ipv4Route *route = Lookup (ipHeader.GetDestination ());
-  if (route == 0) 
-    {
-      NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
-      m_dropTrace (packet);
-      return true;
-    }
+
   NS_DEBUG ("not for me -- forwarding.");
-  SendRealOut (packet, ipHeader, *route);
+  Lookup (ipHeader, packet,
+          MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
   return true;
 }
 
@@ -551,12 +448,39 @@
 {
   Ipv4Interface *interface = GetInterface (i);
   interface->SetUp ();
+
+  // If interface address and network mask have been set, add a route
+  // to the network of the interface (like e.g. ifconfig does on a
+  // Linux box)
+  if ((interface->GetAddress ()) != (Ipv4Address ())
+      && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
+    {
+      AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
+                         interface->GetNetworkMask (), i);
+    }
 }
 void 
-Ipv4L3Protocol::SetDown (uint32_t i)
+Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
 {
-  Ipv4Interface *interface = GetInterface (i);
+  Ipv4Interface *interface = GetInterface (ifaceIndex);
   interface->SetDown ();
+
+  // Remove all routes that are going through this interface
+  bool modified = true;
+  while (modified)
+    {
+      modified = false;
+      for (uint32_t i = 0; i < GetNRoutes (); i++)
+        {
+          Ipv4Route *route = GetRoute (i);
+          if (route->GetInterface () == ifaceIndex)
+            {
+              RemoveRoute (i);
+              modified = true;
+              break;
+            }
+        }
+    }
 }
 
 
--- a/src/internet-node/ipv4-l3-protocol.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.h	Fri Aug 03 08:29:24 2007 -0700
@@ -27,8 +27,11 @@
 #include "ns3/callback-trace-source.h"
 #include "ns3/array-trace-resolver.h"
 #include "ns3/ipv4-address.h"
+#include "ipv4-header.h"
 #include "ns3/ptr.h"
+#include "ns3/ipv4.h"
 #include "l3-protocol.h"
+#include "ipv4-static-routing.h"
 
 namespace ns3 {
 
@@ -124,7 +127,10 @@
   void SetDefaultRoute (Ipv4Address nextHop, 
                         uint32_t interface);
 
-  Ipv4Route *Lookup (Ipv4Address dest);
+  void Lookup (Ipv4Header const &ipHeader,
+               Packet packet,
+               Ipv4RoutingProtocol::RouteReplyCallback routeReply);
+
   uint32_t GetNRoutes (void);
   Ipv4Route *GetRoute (uint32_t i);
   void RemoveRoute (uint32_t i);
@@ -143,11 +149,19 @@
   void SetUp (uint32_t i);
   void SetDown (uint32_t i);
 
+  void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+                           int priority);
 
 protected:
+
   virtual void DoDispose (void);
+
 private:
-  void SendRealOut (Packet const &packet, Ipv4Header const &ip, Ipv4Route const &route);
+
+  void SendRealOut (bool found,
+                    Ipv4Route const &route,
+                    Packet packet,
+                    Ipv4Header const &ipHeader);
   bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, Ptr<NetDevice> device);
   void ForwardUp (Packet p, Ipv4Header const&ip);
   uint32_t AddIpv4Interface (Ipv4Interface *interface);
@@ -155,26 +169,22 @@
   TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context) const;
 
   typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
-  typedef std::list<Ipv4Route *> HostRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator HostRoutesI;
-  typedef std::list<Ipv4Route *> NetworkRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
+  typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
 
   Ipv4InterfaceList m_interfaces;
   uint32_t m_nInterfaces;
   uint8_t m_defaultTtl;
   uint16_t m_identification;
-  HostRoutes m_hostRoutes;
-  NetworkRoutes m_networkRoutes;
-  Ipv4Route *m_defaultRoute;
   Ptr<Node> m_node;
   CallbackTraceSource<Packet const &, uint32_t> m_txTrace;
   CallbackTraceSource<Packet const &, uint32_t> m_rxTrace;
   CallbackTraceSource<Packet const &> m_dropTrace;
+
+  Ipv4RoutingProtocolList m_routingProtocols;
+
+  Ptr<Ipv4StaticRouting> m_staticRouting;
 };
 
 } // Namespace ns3
 
-#endif /* IPV$_L3_PROTOCOL_H */
+#endif /* IPV4_L3_PROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/ipv4-static-routing.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,253 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//         Gustavo Carneiro <gjc@inescporto.pt>
+
+#include "ipv4-static-routing.h"
+#include "ns3/packet.h"
+
+
+namespace ns3 {
+
+
+void 
+Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, 
+                                   Ipv4Address nextHop, 
+                                   uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
+  m_hostRoutes.push_back (route);
+}
+void 
+Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, 
+                                   uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateHostRouteTo (dest, interface);
+  m_hostRoutes.push_back (route);
+}
+void 
+Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, 
+                                      Ipv4Mask networkMask, 
+                                      Ipv4Address nextHop, 
+                                      uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            nextHop,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+void 
+Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, 
+                                      Ipv4Mask networkMask, 
+                                      uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+void 
+Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, 
+                                    uint32_t interface)
+{
+  Ipv4Route *route = new Ipv4Route ();
+  *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
+  delete m_defaultRoute;
+  m_defaultRoute = route;
+}
+
+Ipv4Route *
+Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
+{
+  for (HostRoutesCI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i++) 
+    {
+      NS_ASSERT ((*i)->IsHost ());
+      if ((*i)->GetDest ().IsEqual (dest)) 
+        {
+          return (*i);
+        }
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      NS_ASSERT ((*j)->IsNetwork ());
+      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
+      Ipv4Address entry = (*j)->GetDestNetwork ();
+      if (mask.IsMatch (dest, entry)) 
+        {
+          return (*j);
+        }
+    }
+  if (m_defaultRoute != 0) 
+    {
+      NS_ASSERT (m_defaultRoute->IsDefault ());
+      return m_defaultRoute;
+    }
+  return 0;
+}
+
+uint32_t 
+Ipv4StaticRouting::GetNRoutes (void)
+{
+  uint32_t n = 0;
+  if (m_defaultRoute != 0)
+    {
+      n++;
+    }
+  n += m_hostRoutes.size ();
+  n += m_networkRoutes.size ();
+  return n;
+}
+Ipv4Route *
+Ipv4StaticRouting::GetRoute (uint32_t index)
+{
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      return m_defaultRoute;
+    }
+  if (index > 0 && m_defaultRoute != 0)
+    {
+      index--;
+    }
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesCI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              return *i;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          return *j;
+        }
+      tmp++;
+    }
+  NS_ASSERT (false);
+  // quiet compiler.
+  return 0;
+}
+void 
+Ipv4StaticRouting::RemoveRoute (uint32_t index)
+{
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  if (index > 0 && m_defaultRoute != 0)
+    {
+      index--;
+    }
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              delete *i;
+              m_hostRoutes.erase (i);
+              return;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          delete *j;
+          m_networkRoutes.erase (j);
+          return;
+        }
+      tmp++;
+    }
+  NS_ASSERT (false);
+}
+
+bool
+Ipv4StaticRouting::RequestRoute (Ipv4Header const &ipHeader,
+                                 Packet packet,
+                                 RouteReplyCallback routeReply)
+{
+  Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
+  if (route != 0)
+    {
+      routeReply (true, *route, packet, ipHeader);
+      return true;
+    }
+  else
+    {
+      return false; // Let other routing protocols try to handle this
+                    // route request.
+    }
+}
+
+void
+Ipv4StaticRouting::DoDispose (void)
+{
+  for (HostRoutesI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i = m_hostRoutes.erase (i)) 
+    {
+      delete (*i);
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j = m_networkRoutes.erase (j)) 
+    {
+      delete (*j);
+    }
+  if (m_defaultRoute != 0)
+    {
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  Ipv4RoutingProtocol::DoDispose ();
+}
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/ipv4-static-routing.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,101 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//         Gustavo Carneiro <gjc@inescporto.pt>
+//
+
+#ifndef IPV4_STATIC_ROUTING_H
+#define IPV4_STATIC_ROUTING_H
+
+#include <list>
+#include <stdint.h>
+#include "ns3/callback-trace-source.h"
+#include "ns3/array-trace-resolver.h"
+#include "ns3/ipv4-address.h"
+#include "ipv4-header.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4.h"
+#include "l3-protocol.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4Route;
+class Node;
+class TraceResolver;
+class TraceContext;
+
+
+class Ipv4StaticRouting : public Ipv4RoutingProtocol
+{
+
+public:
+  Ipv4StaticRouting () : m_defaultRoute (0) {}
+
+  virtual bool RequestRoute (Ipv4Header const &ipHeader,
+                             Packet packet,
+                             RouteReplyCallback routeReply);
+
+
+  void AddHostRouteTo (Ipv4Address dest, 
+                       Ipv4Address nextHop, 
+                       uint32_t interface);
+  void AddHostRouteTo (Ipv4Address dest, 
+                       uint32_t interface);
+
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          Ipv4Address nextHop, 
+                          uint32_t interface);
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          uint32_t interface);
+  void SetDefaultRoute (Ipv4Address nextHop, 
+                        uint32_t interface);
+  uint32_t GetNRoutes (void);
+  Ipv4Route *GetRoute (uint32_t i);
+  void RemoveRoute (uint32_t i);
+
+protected:
+  void DoDispose (void);
+
+private:
+  typedef std::list<Ipv4Route *> HostRoutes;
+  typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
+  typedef std::list<Ipv4Route *>::iterator HostRoutesI;
+  typedef std::list<Ipv4Route *> NetworkRoutes;
+  typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
+  typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
+
+  Ipv4Route *LookupStatic (Ipv4Address dest);
+
+  HostRoutes m_hostRoutes;
+  NetworkRoutes m_networkRoutes;
+  Ipv4Route *m_defaultRoute;
+};
+
+
+
+} // Namespace ns3
+
+#endif /* IPV4_STATIC_ROUTING_H */
--- a/src/internet-node/udp-l4-protocol.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/udp-l4-protocol.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -113,13 +113,14 @@
 {
   UdpHeader udpHeader;
   packet.RemoveHeader (udpHeader);
-  Ipv4EndPoint *endPoint = m_endPoints->Lookup (destination, udpHeader.GetDestination (),
-                                                source, udpHeader.GetSource ());
-  if (endPoint == 0)
+  Ipv4EndPointDemux::EndPoints endPoints =
+    m_endPoints->Lookup (destination, udpHeader.GetDestination (),
+                         source, udpHeader.GetSource ());
+  for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
+       endPoint != endPoints.end (); endPoint++)
     {
-      return;
+      (*endPoint)->ForwardUp (packet, source, udpHeader.GetSource ());
     }
-  endPoint->ForwardUp (packet, source, udpHeader.GetSource ());
 }
 
 void
--- a/src/internet-node/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/internet-node/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -1,10 +1,6 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 
-def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-internet-node')
-
-
 def build(bld):
     obj = bld.create_obj('cpp', 'shlib')
     obj.name = 'ns3-internet-node'
@@ -21,6 +17,7 @@
         'ipv4-checksum.cc',
         'ipv4-interface.cc',
         'ipv4-l3-protocol.cc',
+        'ipv4-static-routing.cc',
         'ipv4-end-point.cc',
         'udp-l4-protocol.cc',
         'arp-header.cc',
@@ -28,7 +25,6 @@
         'arp-ipv4-interface.cc',
         'arp-l3-protocol.cc',
         'ipv4-loopback-interface.cc',
-        'header-utils.cc',
         'udp-socket.cc',
         'ipv4-end-point-demux.cc',
         'arp-private.cc',
@@ -44,4 +40,5 @@
         'internet-node.h',
         'ascii-trace.h',
         'pcap-trace.h',
+        'ipv4-header.h',
         ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/grid-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,66 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "grid-topology.h"
+#include "static-mobility-model.h"
+
+namespace ns3 {
+
+GridTopology::GridTopology (double xMin, double yMin, uint32_t n, double deltaX, double deltaY)
+  : m_xMin (xMin),
+    m_yMin (yMin),
+    m_n (n),
+    m_deltaX (deltaX),
+    m_deltaY (deltaY),
+    m_positionClassId (StaticMobilityModel::cid)
+{}
+
+void 
+GridTopology::SetMobilityModel (ClassId classId)
+{
+  m_positionClassId = classId;
+}
+
+void 
+GridTopology::LayoutOneRowFirst (Ptr<Object> object, uint32_t i)
+{
+  double x, y;
+  x = m_xMin + m_deltaX * (i % m_n);
+  y = m_yMin + m_deltaY * (i / m_n);
+  Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_positionClassId,
+                                                                         MobilityModel::iid);
+  object->AddInterface (mobility);
+  mobility->Set (Position (x, y, 0.0));
+}
+
+void 
+GridTopology::LayoutOneColumnFirst (Ptr<Object> object, uint32_t i)
+{
+  double x, y;
+  x = m_xMin + m_deltaX * (i / m_n);
+  y = m_yMin + m_deltaY * (i % m_n);
+  Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_positionClassId, 
+                                                                         MobilityModel::iid);
+  object->AddInterface (mobility);
+  mobility->Set (Position (x, y, 0.0));
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/grid-topology.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,120 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 GRID_TOPOLOGY_H
+#define GRID_TOPOLOGY_H
+
+#include <vector>
+#include "ns3/component-manager.h"
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+/**
+ * \brief a 2D grid of objects
+ */
+class GridTopology
+{
+ public:
+  /**
+   * \param xMin the left boundary where the objects will start being arranged.
+   * \param yMin the lower boundary where the objects will start being arranged.
+   * \param n number of objects for each row or column
+   * \param deltaX distance separating two adjacent objects along the x axis.
+   * \param deltaY distance separating two adjacent objects along the y axis.
+   *
+   * The first object is positioned at (xMin,yMin).
+   */
+  GridTopology (double xMin, double yMin, uint32_t n, double deltaX, double deltaY);
+
+  /**
+   * \param classId the classId of the position object to attach to each
+   *        input object.
+   */
+  void SetMobilityModel (ClassId classId);
+
+  /**
+   * \param begin an iterator to the first object to layout.
+   * \param end an iterator to the last object to layout.
+   *
+   * Attach a position (the type of position is specified through 
+   * the ClassId given to SetMobilityModelModel) to each input object
+   * and configure its initial location with a set
+   * of coordinates arranged according to a regular rectangular grid,
+   * one row after the other.
+   */
+  template <typename T>
+  void LayoutRowFirst (const T &begin, const T &end);
+
+  /**
+   * \param begin an iterator to the first object to layout.
+   * \param end an iterator to the last object to layout.
+   *
+   * Attach a position (the type of position is specified through 
+   * the ClassId given to SetMobilityModelModel) to each input object
+   * and configure its initial location with a set
+   * of coordinates arranged according to a regular rectangular grid,
+   * one column after the other.
+   */
+  template <typename T>
+  void LayoutColumnFirst (const T &begin, const T &end);
+ private:
+  GridTopology ();
+  void LayoutOneRowFirst (Ptr<Object> object, uint32_t i);
+  void LayoutOneColumnFirst (Ptr<Object> object, uint32_t i);
+  double m_xMin;
+  double m_yMin;
+  uint32_t m_n;
+  double m_deltaX;
+  double m_deltaY;
+  ClassId m_positionClassId;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void
+GridTopology::LayoutRowFirst (const T &begin, const T &end)
+{
+  uint32_t j = 0;
+  for (T i = begin; i != end; i++)
+    {
+      j++;
+      LayoutOneRowFirst (*i, j);
+    }  
+}
+
+template <typename T>
+void
+GridTopology::LayoutColumnFirst (const T &begin, const T &end)
+{
+  uint32_t j = 0;
+  for (T i = begin; i != end; i++)
+    {
+      j++;
+      LayoutOneColumnFirst (*i, j);
+    }
+}
+
+} // namespace ns3
+
+#endif /* GRID_TOPOLOGY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/hierarchical-mobility-model.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,105 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "hierarchical-mobility-model.h"
+#include "mobility-model-notifier.h"
+
+namespace ns3 {
+
+HierarchicalMobilityModel::HierarchicalMobilityModel (Ptr<MobilityModel> child, Ptr<MobilityModel> parent)
+  : m_child (child),
+    m_parent (parent)
+{
+  Ptr<MobilityModelNotifier> childNotifier = 
+    m_child->QueryInterface<MobilityModelNotifier> (MobilityModelNotifier::iid);
+  Ptr<MobilityModelNotifier> parentNotifier = 
+    m_parent->QueryInterface<MobilityModelNotifier> (MobilityModelNotifier::iid);
+  if (childNotifier == 0)
+    {
+      childNotifier = Create<MobilityModelNotifier> ();
+      child->AddInterface (childNotifier);
+    }
+  if (parentNotifier == 0)
+    {
+      parentNotifier = Create<MobilityModelNotifier> ();
+      parent->AddInterface (parentNotifier);
+    }
+  childNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+  parentNotifier->RegisterListener (MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+}
+
+Ptr<MobilityModel> 
+HierarchicalMobilityModel::GetChild (void) const
+{
+  return m_child;
+}
+
+Ptr<MobilityModel> 
+HierarchicalMobilityModel::GetParent (void) const
+{
+  return m_parent;
+}
+
+Position 
+HierarchicalMobilityModel::DoGet (void) const
+{
+  Position parentPosition = m_parent->Get ();
+  Position childPosition = m_child->Get ();
+  return Position (parentPosition.x + childPosition.x,
+		   parentPosition.y + childPosition.y,
+		   parentPosition.z + childPosition.z);
+}
+void 
+HierarchicalMobilityModel::DoSet (const Position &position)
+{
+  // This implementation of DoSet is really an arbitraty choice.
+  // anything else would have been ok.
+  Position parentPosition = m_parent->Get ();
+  Position childPosition (position.x - parentPosition.x,
+			  position.y - parentPosition.y,
+			  position.z - parentPosition.z);
+  m_child->Set (childPosition);
+}
+Speed 
+HierarchicalMobilityModel::DoGetSpeed (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);
+  return speed;
+}
+
+void 
+HierarchicalMobilityModel::ParentChanged (Ptr<const MobilityModel> model)
+{
+  MobilityModel::NotifyCourseChange ();
+}
+
+void 
+HierarchicalMobilityModel::ChildChanged (Ptr<const MobilityModel> model)
+{
+  MobilityModel::NotifyCourseChange ();
+}
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/hierarchical-mobility-model.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,76 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 HIERARCHICAL_MOBILITY_MODEL_H
+#define HIERARCHICAL_MOBILITY_MODEL_H
+
+#include "mobility-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief a hierachical mobility model.
+ * 
+ * This model allows you to specify the position of a
+ * child object relative to a parent object.
+ */
+class HierarchicalMobilityModel : public MobilityModel
+{
+public:
+  static const InterfaceId iid;
+
+  /**
+   * \param child the "relative" mobility model
+   * \param parent the "reference" mobility model
+   */
+  HierarchicalMobilityModel (Ptr<MobilityModel> child, Ptr<MobilityModel> parent);
+
+  /**
+   * \returns the child mobility model.
+   *
+   * This allows you to get access to the position of the child
+   * relative to its parent.
+   */
+  Ptr<MobilityModel> GetChild (void) const;
+  /**
+   * \returns the parent mobility model.
+   *
+   * This allows you to get access to the position of the 
+   * parent mobility model which is used as the reference 
+   * position by the child mobility model.
+   */
+  Ptr<MobilityModel> GetParent (void) const;
+  
+private:
+  virtual Position DoGet (void) const;
+  virtual void DoSet (const Position &position);
+  virtual Speed DoGetSpeed (void) const;
+
+  void ParentChanged (Ptr<const MobilityModel> model);
+  void ChildChanged (Ptr<const MobilityModel> model);
+
+  Ptr<MobilityModel> m_child;
+  Ptr<MobilityModel> m_parent;
+};
+
+
+} // namespace ns3
+
+#endif /* HIERARCHICAL_MOBILITY_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-model-notifier.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,68 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "mobility-model-notifier.h"
+
+namespace ns3 {
+
+const InterfaceId MobilityModelNotifier::iid = MakeInterfaceId ("MobilityModelNotifier", Object::iid);
+const ClassId MobilityModelNotifier::cid = 
+  MakeClassId<MobilityModelNotifier> ("MobilityModelNotifier", 
+				    MobilityModelNotifier::iid);
+
+MobilityModelNotifier::MobilityModelNotifier ()
+{
+  SetInterfaceId (MobilityModelNotifier::iid);
+}
+
+void 
+MobilityModelNotifier::RegisterListener (Listener listener)
+{
+  m_listeners.push_back (listener);
+}
+void 
+MobilityModelNotifier::UnregisterListener (Listener callback)
+{
+  for (std::list<Listener>::iterator i = m_listeners.begin ();
+       i != m_listeners.end ();)
+    {
+      Listener listener = *i;
+      if (listener.IsEqual (callback))
+	{
+	  i = m_listeners.erase (i);
+	}
+      else
+	{
+	  i++;
+	}
+    }  
+}
+void 
+MobilityModelNotifier::Notify (Ptr<const MobilityModel> position) const
+{
+  for (std::list<Listener>::const_iterator i = m_listeners.begin ();
+       i != m_listeners.end (); i++)
+    {
+      Listener listener = *i;
+      listener (position);
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-model-notifier.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,72 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 MOBILITY_MODEL_NOTIFIER_H
+#define MOBILITY_MODEL_NOTIFIER_H
+
+#include "ns3/object.h"
+#include "ns3/component-manager.h"
+#include "ns3/callback.h"
+#include "mobility-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief notify listeners of position changes.
+ */
+class MobilityModelNotifier : public Object
+{
+public:
+  static const InterfaceId iid;
+  static const ClassId cid;
+
+  typedef Callback<void,Ptr<const MobilityModel> > Listener;
+
+  /**
+   * Create a new position notifier
+   */
+  MobilityModelNotifier ();
+
+  /**
+   * \param position the position which just changed.
+   */
+  void Notify (Ptr<const MobilityModel> position) const;
+
+  /**
+   * \param listener listener to add
+   *
+   * The listener will be notified upon every position change.
+   */
+  void RegisterListener (Listener listener);
+  /**
+   * \param listener listener to remove
+   *
+   * The listener will not be notified anymore upon every 
+   * position change. It is not an error to try to unregister
+   * a non-registered liste
+   */
+  void UnregisterListener (Listener listener);
+private:
+  std::list<Listener> m_listeners;
+};
+
+} // namespace ns3
+
+#endif /* MOBILITY_MODEL_NOTIFIER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-model.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,73 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 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 "mobility-model.h"
+#include "mobility-model-notifier.h"
+#include <math.h>
+
+namespace ns3 {
+
+const InterfaceId MobilityModel::iid = MakeInterfaceId ("MobilityModel", Object::iid);
+
+MobilityModel::MobilityModel ()
+{
+  SetInterfaceId (MobilityModel::iid);
+}
+
+MobilityModel::~MobilityModel ()
+{}
+
+Position
+MobilityModel::Get (void) const
+{
+  return DoGet ();
+}
+Speed 
+MobilityModel::GetSpeed (void) const
+{
+  return DoGetSpeed ();
+}
+
+void 
+MobilityModel::Set (const Position &position)
+{
+  DoSet (position);
+}
+
+double 
+MobilityModel::GetDistanceFrom (const MobilityModel &other) const
+{
+  Position oPosition = other.DoGet ();
+  Position position = DoGet ();
+  return CalculateDistance (position, oPosition);
+}
+
+void
+MobilityModel::NotifyCourseChange (void) const
+{
+  Ptr<MobilityModelNotifier> notifier = 
+    QueryInterface<MobilityModelNotifier> (MobilityModelNotifier::iid);
+  if (notifier != 0)
+    {
+      notifier->Notify (this);
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-model.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,93 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 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 MOBILITY_MODEL_H
+#define MOBILITY_MODEL_H
+
+#include "ns3/object.h"
+#include "position.h"
+#include "speed.h"
+
+namespace ns3 {
+
+/**
+ * \brief keep track of the current position of an object
+ *
+ * All space coordinates in this class and its subclasses are
+ * understood to be meters or meters/s. i.e., they are all
+ * metric international units.
+ */
+class MobilityModel : public Object
+{
+public:
+  static const InterfaceId iid;
+  MobilityModel ();
+  virtual ~MobilityModel () = 0;
+
+  /**
+   * \returns the current position
+   */
+  Position Get (void) const;
+  /**
+   * \param position the position to set.
+   */
+  void Set (const Position &position);
+  /**
+   * \returns the current position.
+   */
+  Speed GetSpeed (void) const;
+  /**
+   * \param position a reference to another mobility model
+   * \returns the distance between the two objects. Unit is meters.
+   */
+  double GetDistanceFrom (const MobilityModel &position) const;
+protected:
+  /**
+   * Must be invoked by subclasses when the course of the
+   * position changes to notify course change listeners.
+   */
+  void NotifyCourseChange (void) const;
+private:
+  /**
+   * \returns the current position.
+   *
+   * Concrete subclasses of this base class must 
+   * implement this method.
+   */
+  virtual Position DoGet (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;
+  /**
+   * \returns the current speed.
+   *
+   * Concrete subclasses of this base class must 
+   * implement this method.
+   */
+  virtual Speed DoGetSpeed (void) const = 0;
+};
+
+}; // namespace ns3
+
+#endif /* MOBILITY_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,42 @@
+/**
+ * \defgroup mobility Mobility
+ *
+ * The mobility support includes:
+ *  - a set of mobility models which are used to track and maintain
+ *    the "current" cartesian position and speed of an object.
+ *
+ *  - a "course change notifier" which can be used to register listeners
+ *    to the course changes of a mobility model: ns3::MobilityModelNotifier.
+ *
+ *  - a set of topology constructors which are used to set the initial
+ *    position and associate a specific mobility model to a set of objects.
+ *
+ * The mobility models themselves are:
+ *   - ns3::StaticMobilityModel: a model which maintains a constant position
+ *     until it is changed by the user.
+ *
+ *   - ns3::StaticSpeedMobilityModel: a model which maintains a constant speed
+ *     until it is changed by the user.
+ *
+ *   - ns3::HierarchicalMobilityModel: a model which calculates the current 
+ *     absolute position from a "reference" (parent) mobility model
+ *     and a "relative" (child) mobility model. This allows users to
+ *     compose mobility models.
+ *
+ *   - ns3::RandomWalk2dMobilityModel: a 2d "brownian" motion mobility model
+ *     where the bounds of the mobility area are a rectangle.
+ *
+ *   - ns3::RandomWaypointMobilityModel: a 3d random waypoint mobility model.
+ *
+ *   - ns3::RandomDirection2dMobilityModel: a 2d random direction mobility
+ *     model where the bounds of the mobility are are a rectangle.
+ *
+ * The topology constructors:
+ *   - ns3::GridTopology: layout objects in a 2d grid.
+ *
+ *   - ns3::RandomTopology: layout objects in a 3d space, according to a 
+ *     RandomPosition model.
+ *
+ *   - ns3::Ns2MobilityFileTopology: layout objects in a 3d space according
+ *     to an ns2 CMU mobility file (as generated by the setdest tool).
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/position.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,29 @@
+#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/position.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,45 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+#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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-position.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,116 @@
+#include "random-position.h"
+#include "ns3/random-variable.h"
+#include "ns3/default-value.h"
+#include "ns3/random-variable-default-value.h"
+#include "ns3/debug.h"
+#include <cmath>
+
+NS_DEBUG_COMPONENT_DEFINE ("RandomPosition");
+
+namespace ns3 {
+
+static RandomVariableDefaultValue
+g_rectangleX ("RandomRectanglePositionX",
+	      "A random variable which represents the x position of a position in a random rectangle.",
+	      "Uniform:0:200");
+
+static RandomVariableDefaultValue
+g_rectangleY ("RandomRectanglePositionY",
+	      "A random variable which represents the y position of a position in a random rectangle.",
+	      "Uniform:0:200");
+
+static RandomVariableDefaultValue
+g_discTheta ("RandomDiscPositionTheta",
+	     "A random variable which represents the angle (gradients) of a position in a random disc.",
+	     "Uniform:0:6.2830");
+
+static RandomVariableDefaultValue
+g_discRho ("RandomDiscPositionRho",
+	   "A random variable which represents the radius of a position in a random disc.",
+	   "Uniform:0:200");
+
+static NumericDefaultValue<double>
+g_discX ("RandomDiscPositionX",
+	 "The x coordinate of the center of the random position disc.",
+	 0.0);
+
+static NumericDefaultValue<double>
+g_discY ("RandomDiscPositionY",
+	 "The y coordinate of the center of the random position disc.",
+	 0.0);
+
+const InterfaceId RandomPosition::iid = MakeInterfaceId ("RandomPosition", Object::iid);
+
+const ClassId RandomRectanglePosition::cid = 
+  MakeClassId<RandomRectanglePosition> ("RandomRectanglePosition", 
+					RandomPosition::iid);
+const ClassId RandomDiscPosition::cid = 
+  MakeClassId<RandomDiscPosition> ("RandomDiscPosition", 
+				   RandomPosition::iid);
+
+RandomPosition::RandomPosition ()
+{
+  Object::SetInterfaceId (RandomPosition::iid);
+}
+
+RandomPosition::~RandomPosition ()
+{}
+
+RandomRectanglePosition::RandomRectanglePosition ()
+  : m_x (g_rectangleX.GetCopy ()),
+    m_y (g_rectangleY.GetCopy ())
+{}
+RandomRectanglePosition::RandomRectanglePosition (const RandomVariable &x,
+						  const RandomVariable &y)
+  : m_x (x.Copy ()),
+    m_y (y.Copy ())
+{}
+RandomRectanglePosition::~RandomRectanglePosition ()
+{
+  delete m_x;
+  delete m_y;
+  m_x = 0;
+  m_y = 0;
+}
+Position
+RandomRectanglePosition::Get (void) const
+{
+  double x = m_x->GetValue ();
+  double y = m_y->GetValue ();
+  return Position (x, y, 0.0);
+}
+
+RandomDiscPosition::RandomDiscPosition ()
+  : m_theta (g_discTheta.GetCopy ()),
+    m_rho (g_discRho.GetCopy ()),
+    m_x (g_discX.GetValue ()),
+    m_y (g_discY.GetValue ())
+{}
+RandomDiscPosition::RandomDiscPosition (const RandomVariable &theta,
+					const RandomVariable &rho,
+					double x, double y)
+  : m_theta (theta.Copy ()),
+    m_rho (rho.Copy ()),
+    m_x (0.0),
+    m_y (0.0)
+{}
+RandomDiscPosition::~RandomDiscPosition ()
+{
+  delete m_theta;
+  delete m_rho;
+  m_theta = 0;
+  m_rho = 0;
+}
+Position
+RandomDiscPosition::Get (void) const
+{
+  double theta = m_theta->GetValue ();
+  double rho = m_rho->GetValue ();
+  double x = m_x + std::cos (theta) * rho;
+  double y = m_y + std::sin (theta) * rho;
+  NS_DEBUG ("Disc position x=" << x << ", y=" << y);
+  return Position (x, y, 0.0);
+}
+
+
+} // namespace ns3 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-position.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,97 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+#ifndef RANDOM_POSITION_H
+#define RANDOM_POSITION_H
+
+#include "ns3/object.h"
+#include "ns3/component-manager.h"
+#include "position.h"
+
+namespace ns3 {
+
+class RandomVariable;
+
+/**
+ * \brief choose a position at random.
+ *
+ * This is a pure abstract base class.
+ */
+class RandomPosition : public Object
+{
+public:
+  static const InterfaceId iid;
+  RandomPosition ();
+  virtual ~RandomPosition ();
+  /**
+   * \returns the next randomly-choosen position.
+   */
+  virtual Position Get (void) const = 0;
+};
+
+/**
+ * \brief allocate random positions within a rectangle
+ * according to a pair of random variables.
+ */
+class RandomRectanglePosition : public RandomPosition
+{
+public:
+  static const ClassId cid;
+  /**
+   * Create a random position model based on the
+   * Bind default values.
+   */
+  RandomRectanglePosition ();
+  /**
+   * \param x the random variable which is used to choose
+   *        the x coordinates.
+   * \param y the random variable which is used to choose
+   *        the y coordinates.
+   */
+  RandomRectanglePosition (const RandomVariable &x,
+			   const RandomVariable &y);
+  virtual ~RandomRectanglePosition ();
+  virtual Position Get (void) const;
+private:
+  RandomVariable *m_x;
+  RandomVariable *m_y;
+};
+
+/**
+ * \brief allocate random positions within a disc
+ * according to a pair of random variables.
+ */
+class RandomDiscPosition : public RandomPosition
+{
+public:
+  static const ClassId cid;
+  /**
+   * Create a random position model based on the
+   * Bind default values.
+   */
+  RandomDiscPosition ();
+  /**
+   * \param theta the random variable used to pick
+   *        the angle of the random position in polar
+   *        coordinates.
+   * \param rho the random variable used to pick the
+   *        radius of the random position in polar
+   *        coordinates.
+   * \param x the x coordinate of the center of the
+   *        polar coodinate system.
+   * \param y the y coordinate of the center of the
+   *        polar coodinate system.
+   */
+  RandomDiscPosition (const RandomVariable &theta,
+		      const RandomVariable &rho,
+		      double x, double y);
+  virtual ~RandomDiscPosition ();
+  virtual Position Get (void) const;
+private:
+  RandomVariable *m_theta;
+  RandomVariable *m_rho;
+  double m_x;
+  double m_y;
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_POSITION_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-topology.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,78 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "ns3/random-variable-default-value.h"
+#include "random-topology.h"
+#include "random-position.h"
+#include "mobility-model.h"
+
+namespace ns3 {
+
+static ClassIdDefaultValue
+g_position ("RandomTopologyPositionType",
+            "The type of initial random position in a 3d topology.",
+            RandomPosition::iid,
+            "RandomRectanglePosition");
+
+static ClassIdDefaultValue
+g_mobility ("RandomTopologyMobilityType",
+            "The type of mobility model attached to an object in a 3d topology.",
+            MobilityModel::iid,
+            "StaticMobilityModel");
+
+RandomTopology::RandomTopology ()
+  : m_mobilityModel (g_mobility.GetValue ())
+{
+  m_positionModel = ComponentManager::Create<RandomPosition> (g_position.GetValue (), 
+                                                              RandomPosition::iid);
+}
+RandomTopology::RandomTopology (Ptr<RandomPosition> positionModel, ClassId mobilityModel)
+  : m_positionModel (positionModel),
+    m_mobilityModel (mobilityModel)
+{}
+RandomTopology::~RandomTopology ()
+{
+  m_positionModel = 0;
+}
+
+void 
+RandomTopology::SetMobilityModel (ClassId classId)
+{
+  m_mobilityModel = classId;
+}
+
+void 
+RandomTopology::SetPositionModel (Ptr<RandomPosition> positionModel)
+{
+  m_positionModel = positionModel;
+}
+
+void 
+RandomTopology::LayoutOne (Ptr<Object> object)
+{
+  Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_mobilityModel, 
+                                                                         MobilityModel::iid);
+  object->AddInterface (mobility);
+  Position position = m_positionModel->Get ();
+  mobility->Set (position);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/random-topology.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,113 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 RANDOM_TOPOLOGY_H
+#define RANDOM_TOPOLOGY_H
+
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "ns3/component-manager.h"
+
+namespace ns3 {
+
+class RandomPosition;
+
+/**
+ * \brief layout objects randomly in 3d space.
+ *
+ * This assigns an initial position to each object
+ * according to its position model and assigns
+ * an instance of a mobility model to each object
+ * according to its mobility model class id.
+ */
+class RandomTopology
+{
+ public:
+  /**
+   * Create a default random topology based
+   * on Bind configuration.
+   */
+  RandomTopology ();
+  /**
+   * \param positionModel model to set the initial position
+   *        of each object.
+   * \param mobilityModel type of mobility model to attach to each object.
+   *
+   * Create a random topology based on the
+   * specified position and mobility models.
+   */
+  RandomTopology (Ptr<RandomPosition> positionModel,
+                  ClassId mobilityModel);
+
+  ~RandomTopology ();
+
+  /**
+   * \param classId the type of mobility model attached to each
+   *        input object if it does not have one already.
+   */
+  void SetMobilityModel (ClassId classId);
+  /**
+   * \param positionModel the position model used to initialize
+   *        the position of each object.
+   */
+  void SetPositionModel (Ptr<RandomPosition> positionModel);
+
+  /**
+   * \param object the object to layout
+   *
+   * Assign an initial position and a mobility model
+   * to the object.
+   */
+  void LayoutOne (Ptr<Object> object);
+
+  /**
+   * \param begin iterator which identifies the first
+   *        object to configure.
+   * \param end iterator which identifies the last
+   *        object to configure.
+   *
+   * Assign an initial position and a mobility model
+   * to the objects.
+   */
+  template <typename T>
+  void Layout (const T &begin, const T &end);
+ private:
+  Ptr<RandomPosition> m_positionModel;
+  ClassId m_mobilityModel;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void 
+RandomTopology::Layout (const T &begin, const T &end)
+{
+  for (T i = begin; i != end; i++)
+    {
+      LayoutOne (*i);
+    }
+}
+
+
+} // namespace ns3 
+
+#endif /* RANDOM_TOPOLOGY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/rectangle-default-value.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,93 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "rectangle-default-value.h"
+
+namespace ns3 {
+
+RectangleDefaultValue::RectangleDefaultValue (std::string name,
+					      std::string help,
+					      double xMin, double xMax,
+					      double yMin, double yMax)
+  : DefaultValueBase (name, help),
+    m_default (xMin, xMax, yMin, yMax),
+    m_rectangle (xMin, xMax, yMin, yMax)
+{
+  DefaultValueList::Add (this);
+}
+
+Rectangle
+RectangleDefaultValue::GetValue (void) const
+{
+  return m_rectangle;
+}
+double
+RectangleDefaultValue::ReadDouble (std::string str, bool &ok)
+{
+  double value;
+  std::istringstream iss;
+  iss.str (str);
+  iss >> value;
+  if (iss.bad () || iss.fail ())
+    {
+      ok = false;
+    }
+  return value;
+}
+bool 
+RectangleDefaultValue::DoParseValue (const std::string &value)
+{
+  std::string::size_type xMinStart = 0;
+  std::string::size_type xMinEnd = value.find_first_of(":", xMinStart);
+  std::string::size_type xMaxStart = xMinEnd + 1;
+  std::string::size_type xMaxEnd = value.find_first_of(":", xMaxStart);
+  std::string::size_type yMinStart = xMaxEnd + 1;
+  std::string::size_type yMinEnd = value.find_first_of(":", yMinStart);
+  std::string::size_type yMaxStart = yMinEnd + 1;
+  std::string::size_type yMaxEnd = std::string::npos;
+
+  std::string xMinString = value.substr (xMinStart, xMinEnd);
+  std::string xMaxString = value.substr (xMaxStart, xMaxEnd);
+  std::string yMinString = value.substr (yMinStart, yMinEnd);
+  std::string yMaxString = value.substr (yMaxStart, yMaxEnd);
+
+  bool ok = true;
+  m_rectangle.xMin = ReadDouble (xMinString, ok);
+  m_rectangle.yMin = ReadDouble (yMinString, ok);
+  m_rectangle.xMax = ReadDouble (xMaxString, ok);
+  m_rectangle.yMax = ReadDouble (yMaxString, ok);
+  return ok;
+}
+std::string 
+RectangleDefaultValue::DoGetType (void) const
+{
+  return "(xMin:xMax:yMin:yMax)";
+}
+std::string 
+RectangleDefaultValue::DoGetDefaultValue (void) const
+{
+  std::ostringstream oss;
+  oss << m_default.xMin << ":" << m_default.xMax << ":" << m_default.yMin << ":" << m_default.yMax;
+  return oss.str ();
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/rectangle-default-value.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,51 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 RECTANGLE_DEFAULT_VALUE_H
+#define RECTANGLE_DEFAULT_VALUE_H
+
+#include <string>
+#include "ns3/default-value.h"
+#include "rectangle.h"
+
+namespace ns3 {
+
+class RectangleDefaultValue : public DefaultValueBase
+{
+ public:
+  RectangleDefaultValue (std::string name,
+			 std::string help,
+			 double xMin, double xMax,
+			 double yMin, double yMax);
+
+  Rectangle GetValue (void) const;
+ private:
+  double ReadDouble (std::string str, bool &ok);
+  virtual bool DoParseValue (const std::string &value);
+  virtual std::string DoGetType (void) const;
+  virtual std::string DoGetDefaultValue (void) const;
+
+  Rectangle m_default;
+  Rectangle m_rectangle;
+};
+
+} // namespace ns3
+
+#endif /* RECTANGLE_DEFAULT_VALUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/rectangle.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,123 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "rectangle.h"
+#include "position.h"
+#include "speed.h"
+#include "ns3/assert.h"
+#include <cmath>
+#include <algorithm>
+
+namespace ns3 {
+
+Rectangle::Rectangle (double _xMin, double _xMax,
+		      double _yMin, double _yMax)
+  : xMin (_xMin),
+    xMax (_xMax),
+    yMin (_yMin),
+    yMax (_yMax)
+{}
+
+Rectangle::Rectangle ()
+  : xMin (0.0),
+    xMax (0.0),
+    yMin (0.0),
+    yMax (0.0)
+{}
+
+bool 
+Rectangle::IsInside (const Position &position) const
+{
+  return 
+    position.x <= xMax && position.x >= xMin &&
+    position.y <= yMax && position.y >= yMin;
+}
+
+Rectangle::Side 
+Rectangle::GetClosestSide (const Position &position) const
+{
+  double xMinDist = std::abs (position.x - xMin);
+  double xMaxDist = std::abs (xMax - position.x);
+  double yMinDist = std::abs (position.y - yMin);
+  double yMaxDist = std::abs (yMax - position.y);
+  double minX = std::min (xMinDist, xMaxDist);
+  double minY = std::min (yMinDist, yMaxDist);
+  if (minX < minY)
+    {
+      if (xMinDist < xMaxDist)
+        {
+          return LEFT;
+        }
+      else
+        {
+          return RIGHT;
+        }
+    }
+  else
+    {
+      if (yMinDist < yMaxDist)
+        {
+          return BOTTOM;
+        }
+      else
+        {
+          return TOP;
+        }
+    }
+}
+
+Position
+Rectangle::CalculateIntersection (const Position &current, const Speed &speed) const
+{
+  double xMaxY = current.y + (xMax - current.x) / speed.dx * speed.dy;
+  double xMinY = current.y + (xMin - current.x) / speed.dx * speed.dy;
+  double yMaxX = current.x + (yMax - current.y) / speed.dy * speed.dx;
+  double yMinX = current.x + (yMin - current.y) / speed.dy * speed.dx;
+  bool xMaxOk = xMaxY <= yMax && xMaxY >= yMin;
+  bool xMinOk = xMinY <= yMax && xMinY >= yMin;
+  bool yMaxOk = yMaxX <= xMax && yMaxX >= xMin;
+  bool yMinOk = yMinX <= xMax && yMinX >= xMin;
+  if (xMaxOk && speed.dx >= 0)
+    {
+      return Position (xMax, xMaxY, 0.0);
+    }
+  else if (xMinOk && speed.dx <= 0)
+    {
+      return Position (xMin, xMinY, 0.0);
+    }
+  else if (yMaxOk && speed.dy >= 0)
+    {
+      return Position (yMaxX, yMax, 0.0);
+    }
+  else if (yMinOk && speed.dy <= 0)
+    {
+      return Position (yMinX, yMin, 0.0);
+    }
+  else
+    {
+      NS_ASSERT (false);
+      // quiet compiler
+      return Position (0.0, 0.0, 0.0);
+    }
+
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/rectangle.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,67 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 RECTANGLE_H
+#define RECTANGLE_H
+
+namespace ns3 {
+
+class Position;
+class Speed;
+
+/**
+ * \brief a 2d rectangle
+ */
+class Rectangle
+{
+public:
+  enum Side {
+    RIGHT,
+    LEFT,
+    TOP,
+    BOTTOM
+  };
+  /**
+   * \param _xMin x coordinates of left boundary.
+   * \param _xMax x coordinates of right boundary.
+   * \param _yMin y coordinates of bottom boundary.
+   * \param _yMax y coordinates of top boundary.
+   *
+   * Create a rectangle.
+   */
+  Rectangle (double _xMin, double _xMax,
+             double _yMin, double _yMax);
+  /**
+   * 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;
+
+  double xMin;
+  double xMax;
+  double yMin;
+  double yMax;
+};
+
+} // namespace ns3
+
+#endif /* RECTANGLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/speed.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,17 @@
+#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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/speed.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,43 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+#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 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-mobility-model.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,57 @@
+/* -*-  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 "static-mobility-model.h"
+
+namespace ns3 {
+
+const ClassId StaticMobilityModel::cid = MakeClassId<StaticMobilityModel> ("StaticMobilityModel", 
+                                                                           MobilityModel::iid);
+  
+StaticMobilityModel::StaticMobilityModel ()
+{
+  SetInterfaceId (StaticMobilityModel::iid);
+}
+StaticMobilityModel::StaticMobilityModel (const Position &position)
+  : m_position (position)
+{
+  SetInterfaceId (StaticMobilityModel::iid);
+}
+StaticMobilityModel::~StaticMobilityModel ()
+{}
+
+Position
+StaticMobilityModel::DoGet (void) const
+{
+  return m_position;
+}
+void 
+StaticMobilityModel::DoSet (const Position &position)
+{
+  m_position = position;
+  NotifyCourseChange ();
+}
+Speed 
+StaticMobilityModel::DoGetSpeed (void) const
+{
+  return Speed ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-mobility-model.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,61 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 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 STATIC_MOBILITY_MODEL_H
+#define STATIC_MOBILITY_MODEL_H
+
+#include "ns3/component-manager.h"
+#include "mobility-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief a position model for which the current position does not
+ *        change once it has been set and until it is set again 
+ *        explicitely to a new value.
+ */
+class StaticMobilityModel : public MobilityModel 
+{
+public:
+  static const ClassId cid;
+  /**
+   * Create a position located at coordinates (0,0,0)
+   */
+  StaticMobilityModel ();
+  /**
+   * \param position the initial position.
+   *
+   * Create a position located at coordinates (x,y,z).
+   * Unit is meters
+   */
+  StaticMobilityModel (const Position &position);
+  virtual ~StaticMobilityModel ();
+
+private:
+  virtual Position DoGet (void) const;
+  virtual void DoSet (const Position &position);
+  virtual Speed DoGetSpeed (void) const;
+
+  Position m_position;
+};
+
+}; // namespace ns3
+
+#endif /* STATIC_MOBILITY_MODEL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-speed-helper.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,100 @@
+#include "ns3/simulator.h"
+#include "ns3/rectangle.h"
+#include "static-speed-helper.h"
+
+namespace ns3 {
+
+StaticSpeedHelper::StaticSpeedHelper ()
+{}
+StaticSpeedHelper::StaticSpeedHelper (const Position &position)
+  : m_position (position)
+{}
+StaticSpeedHelper::StaticSpeedHelper (const Position &position,
+				      const Speed &speed)
+  : m_position (position),
+    m_speed (speed)
+{}
+void 
+StaticSpeedHelper::InitializePosition (const Position &position)
+{
+  m_position = position;
+  m_speed.dx = 0.0;
+  m_speed.dy = 0.0;
+  m_speed.dz = 0.0;
+  m_lastUpdate = Simulator::Now ();
+  m_pauseEnd = Simulator::Now ();
+}
+
+void
+StaticSpeedHelper::Reset (const Speed &speed, const Time &pauseDelay)
+{
+  Reset (speed);
+  m_pauseEnd = Simulator::Now () + pauseDelay;
+}
+
+Position 
+StaticSpeedHelper::GetCurrentPosition (void) const
+{
+  Update ();
+  return m_position;
+}
+
+Speed 
+StaticSpeedHelper::GetSpeed (void) const
+{
+  return m_speed;
+}
+void 
+StaticSpeedHelper::SetSpeed (const Speed &speed)
+{
+  Update ();
+  m_speed = speed;
+}
+
+void
+StaticSpeedHelper::Update (void) const
+{
+  Time now = Simulator::Now ();
+  if (m_pauseEnd > now)
+    {
+      return;
+    }
+  Time last = std::max (now, m_pauseEnd);
+  if (m_lastUpdate >= last)
+    {
+      return;
+    }
+  Time deltaTime = now - last;
+  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;
+}
+
+void 
+StaticSpeedHelper::Reset (const Speed &speed)
+{
+  Update ();
+  m_speed = speed;
+  m_pauseEnd = Simulator::Now ();
+}
+void
+StaticSpeedHelper::UpdateFull (const Rectangle &bounds) const
+{
+  Update ();
+  m_position.x = std::min (bounds.xMax, m_position.x);
+  m_position.x = std::max (bounds.xMin, m_position.x);
+  m_position.y = std::min (bounds.yMax, m_position.y);
+  m_position.y = std::max (bounds.yMin, m_position.y);
+}
+
+Position 
+StaticSpeedHelper::GetCurrentPosition (const Rectangle &bounds) const
+{
+  UpdateFull (bounds);
+  return m_position;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-speed-helper.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,40 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+#ifndef STATIC_SPEED_HELPER_H
+#define STATIC_SPEED_HELPER_H
+
+#include "ns3/nstime.h"
+#include "position.h"
+#include "speed.h"
+
+namespace ns3 {
+
+class Rectangle;
+
+class StaticSpeedHelper
+{
+ public:
+  StaticSpeedHelper ();
+  StaticSpeedHelper (const Position &position);
+  StaticSpeedHelper (const Position &position,
+		     const Speed &speed);
+  void InitializePosition (const Position &position);
+
+  void Reset (const Speed &speed, const Time &pauseDelay);
+  void Reset (const Speed &speed);
+  Position GetCurrentPosition (const Rectangle &bounds) const;
+  Position GetCurrentPosition (void) const;
+  Speed GetSpeed (void) const;
+  void SetSpeed (const Speed &speed);
+
+ private:
+  void Update (void) const;
+  void UpdateFull (const Rectangle &rectangle) const;
+  mutable Time m_lastUpdate;
+  mutable Position m_position;
+  Speed m_speed;
+  Time m_pauseEnd;
+};
+
+} // namespace ns3
+
+#endif /* STATIC_SPEED_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-speed-mobility-model.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,77 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006, 2007 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 "static-speed-mobility-model.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+const InterfaceId StaticSpeedMobilityModel::iid = 
+  MakeInterfaceId ("StaticSpeedMobilityModel", MobilityModel::iid);
+const ClassId StaticSpeedMobilityModel::cid = 
+  MakeClassId<StaticSpeedMobilityModel> ("StaticSpeedMobilityModel", 
+                                         StaticSpeedMobilityModel::iid);
+
+
+StaticSpeedMobilityModel::StaticSpeedMobilityModel ()
+{
+  SetInterfaceId (StaticSpeedMobilityModel::iid);
+}
+StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Position &position)
+  : m_helper (position)
+{
+  SetInterfaceId (StaticSpeedMobilityModel::iid);
+}
+StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Position &position,
+                                                    const Speed &speed)
+  : m_helper (position, speed)
+{
+  SetInterfaceId (StaticSpeedMobilityModel::iid);
+}
+
+StaticSpeedMobilityModel::~StaticSpeedMobilityModel ()
+{}
+
+void 
+StaticSpeedMobilityModel::SetSpeed (const Speed speed)
+{
+  m_helper.SetSpeed (speed);
+  NotifyCourseChange ();
+}
+
+
+Position
+StaticSpeedMobilityModel::DoGet (void) const
+{
+  return m_helper.GetCurrentPosition ();
+}
+void 
+StaticSpeedMobilityModel::DoSet (const Position &position)
+{
+  m_helper.InitializePosition (position);
+  NotifyCourseChange ();
+}
+Speed 
+StaticSpeedMobilityModel::DoGetSpeed (void) const
+{
+  return m_helper.GetSpeed ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/static-speed-mobility-model.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,80 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006, 2007 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 STATIC_SPEED_MOBILITY_MODEL_H
+#define STATIC_SPEED_MOBILITY_MODEL_H
+
+#include <stdint.h>
+#include "mobility-model.h"
+#include "ns3/nstime.h"
+#include "ns3/component-manager.h"
+#include "static-speed-helper.h"
+#include "speed.h"
+
+namespace ns3 {
+
+/**
+ * \brief a position model for which the current speed does not
+ *        change once it has been set and until it is set again 
+ *        explicitely to a new value.
+ */
+class StaticSpeedMobilityModel : public MobilityModel 
+{
+public:
+  static const InterfaceId iid;
+  static const ClassId cid;
+  /**
+   * Create position located at coordinates (0,0,0) with
+   * speed (0,0,0).
+   */
+  StaticSpeedMobilityModel ();
+  /**
+   * Create a position located at coordinates (x,y,z) with
+   * speed (0,0,0).
+   */
+  StaticSpeedMobilityModel (const Position &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);
+  virtual ~StaticSpeedMobilityModel ();
+
+  /**
+   * \param speed the new speed to set.
+   *
+   * Set the current speed now to (dx,dy,dz)
+   * Unit is meters/s
+   */
+  void SetSpeed (const Speed speed);
+private:
+  virtual Position DoGet (void) const;
+  virtual void DoSet (const Position &position);
+  virtual Speed DoGetSpeed (void) const;
+  void Update (void) const;
+  StaticSpeedHelper m_helper;
+};
+
+}; // namespace ns3
+
+#endif /* STATIC_SPEED_POSITION */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,39 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    mobility = bld.create_obj('cpp', 'shlib')
+    mobility.name = 'ns3-mobility'
+    mobility.target = mobility.name
+    mobility.uselib_local = ['ns3-core', 'ns3-simulator']
+    mobility.source = [
+        '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',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        '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',
+        ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/address-utils.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,49 @@
+/* -*-  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 "address-utils.h"
+
+namespace ns3 {
+
+void WriteTo (Buffer::Iterator &i, Ipv4Address ad)
+{
+  i.WriteHtonU32 (ad.GetHostOrder ());
+}
+void WriteTo (Buffer::Iterator &i, MacAddress ad)
+{
+  uint8_t mac[MacAddress::MAX_LEN];
+  ad.Peek (mac);
+  i.Write (mac, ad.GetLength ());
+}
+
+void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad)
+{
+  ad.SetHostOrder (i.ReadNtohU32 ());
+}
+void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len)
+{
+  uint8_t mac[MacAddress::MAX_LEN];
+  i.Read (mac, len);
+  ad.Set (mac, len);
+}
+
+
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/address-utils.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,38 @@
+/* -*-  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 ADDRESS_UTILS_H
+#define ADDRESS_UTILS_H
+
+#include "ns3/buffer.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/mac-address.h"
+
+namespace ns3 {
+
+void WriteTo (Buffer::Iterator &i, Ipv4Address ad);
+void WriteTo (Buffer::Iterator &i, MacAddress ad);
+
+void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad);
+void ReadFrom (Buffer::Iterator &i, MacAddress &ad, uint32_t len);
+
+};
+
+#endif /* ADDRESS_UTILS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ethernet-header.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,163 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/header.h"
+#include "ethernet-header.h"
+#include "address-utils.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("EthernetHeader");
+
+namespace ns3 {
+
+EthernetHeader::EthernetHeader (bool hasPreamble)
+  : m_enPreambleSfd (hasPreamble),
+    m_lengthType (0)
+{}
+
+EthernetHeader::EthernetHeader ()
+  : m_enPreambleSfd (false),
+    m_lengthType (0)
+{}
+
+EthernetHeader::~EthernetHeader ()
+{}
+
+void 
+EthernetHeader::SetLengthType (uint16_t lengthType)
+{
+  m_lengthType = lengthType;
+}
+uint16_t 
+EthernetHeader::GetLengthType (void) const
+{
+  return m_lengthType;
+}
+
+void 
+EthernetHeader::SetPreambleSfd (uint64_t preambleSfd)
+{
+  m_preambleSfd = preambleSfd;
+}
+uint64_t 
+EthernetHeader::GetPreambleSfd (void) const
+{
+  return m_preambleSfd;
+}
+
+void 
+EthernetHeader::SetSource (MacAddress source)
+{
+  m_source = source;
+}
+MacAddress
+EthernetHeader::GetSource (void) const
+{
+  return m_source;
+}
+
+void 
+EthernetHeader::SetDestination (MacAddress dst)
+{
+  m_destination = dst;
+}
+MacAddress
+EthernetHeader::GetDestination (void) const
+{
+  return m_destination;
+}
+
+ethernet_header_t 
+EthernetHeader::GetPacketType (void) const
+{
+  return LENGTH;
+}
+
+uint32_t 
+EthernetHeader::GetHeaderSize (void) const
+{
+  return GetSerializedSize();
+}
+
+std::string
+EthernetHeader::DoGetName (void) const
+{
+  return "ETHERNET";
+}
+
+void 
+EthernetHeader::PrintTo (std::ostream &os) const
+{
+  // ethernet, right ?
+  os << "(ethernet)";
+  if (m_enPreambleSfd)
+    {
+      os << " preamble/sfd=" << m_preambleSfd << ",";
+    }
+  os << " length/type=" << m_lengthType
+     << ", source=" << m_source
+     << ", destination=" << m_destination;
+}
+uint32_t 
+EthernetHeader::GetSerializedSize (void) const
+{
+  if (m_enPreambleSfd)
+    {
+      return PREAMBLE_SIZE + LENGTH_SIZE + 2*MAC_ADDR_SIZE;
+    } else {
+      return LENGTH_SIZE + 2*MAC_ADDR_SIZE;
+    }
+}
+
+void
+EthernetHeader::SerializeTo (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  
+  if (m_enPreambleSfd)
+    {
+      i.WriteU64(m_preambleSfd);
+    }
+  NS_ASSERT (m_destination.GetLength () == MAC_ADDR_SIZE);
+  NS_ASSERT (m_source.GetLength () == MAC_ADDR_SIZE);
+  WriteTo (i, m_destination);
+  WriteTo (i, m_source);
+  i.WriteU16 (m_lengthType);
+}
+uint32_t
+EthernetHeader::DeserializeFrom (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  if (m_enPreambleSfd)
+    {
+      m_enPreambleSfd = i.ReadU64 ();
+    }
+
+  ReadFrom (i, m_destination, MAC_ADDR_SIZE);
+  ReadFrom (i, m_source, MAC_ADDR_SIZE);
+  m_lengthType = i.ReadU16 ();
+
+  return GetSerializedSize ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ethernet-header.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,127 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#ifndef ETHERNET_HEADER_H
+#define ETHERNET_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/mac-address.h"
+
+namespace ns3 {
+
+  /**
+   * Types of ethernet packets. Indicates the type of the current
+   * header.
+   */
+  enum ethernet_header_t {
+    LENGTH,   /**< Basic ethernet packet, no tags, type/length field
+                 indicates packet length or IP/ARP packet */
+    VLAN,     /**< Single tagged packet. Header includes VLAN tag */
+    QINQ      /**< Double tagged packet. Header includes two VLAN tags */
+  };
+/**
+ * \brief Packet header for Ethernet
+ *
+ * This class can be used to add a header to an ethernet packet that
+ * will specify the source and destination addresses and the length of
+ * the packet. Eventually the class will be improved to also support
+ * VLAN tags in packet headers.
+ */
+class EthernetHeader : public Header {
+public:
+  /**
+   * \brief Construct a null ethernet header
+   * \param hasPreamble if true, insert and remove an ethernet preamble from the
+   *       packet, if false, does not insert and remove it.
+   */
+  EthernetHeader (bool hasPreamble);
+  /**
+   * \brief Construct a null ethernet header
+   * By default, does not add or remove an ethernet preamble
+   */
+  EthernetHeader ();
+  virtual ~EthernetHeader ();
+  /**
+   * \param size The size of the payload in bytes
+   */
+  void SetLengthType (uint16_t size);
+  /**
+   * \param source The source address of this packet
+   */
+  void SetSource (MacAddress source);
+  /**
+   * \param destination The destination address of this packet.
+   */
+  void SetDestination (MacAddress destination);
+  /**
+   * \param preambleSfd The value that the preambleSfd field should take
+   */
+  void SetPreambleSfd (uint64_t preambleSfd);
+  /**
+   * \return The size of the payload in bytes
+   */
+  uint16_t GetLengthType (void) const;
+  /**
+   * \return The type of packet (only basic Ethernet is currently supported)
+   */
+  ethernet_header_t GetPacketType (void) const;
+  /**
+   * \return The source address of this packet
+   */
+  MacAddress GetSource (void) const;
+  /**
+   * \return The destination address of this packet
+   */
+  MacAddress GetDestination (void) const;  
+  /**
+   * \return The value of the PreambleSfd field
+   */
+  uint64_t GetPreambleSfd () const;
+  /**
+   * \return The size of the header
+   */
+  uint32_t GetHeaderSize() const;
+
+private:
+  static const int PREAMBLE_SIZE = 8; /// size of the preamble_sfd header field
+  static const int LENGTH_SIZE = 2;   /// size of the length_type header field
+  static const int MAC_ADDR_SIZE = 6; /// size of src/dest addr header fields
+
+  virtual std::string DoGetName (void) const;
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator start) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+
+  /**
+   * If false, the preamble/sfd are not serialised/deserialised.
+   */
+  bool m_enPreambleSfd;
+  uint64_t m_preambleSfd;     /// Value of the Preamble/SFD fields
+  uint16_t m_lengthType;      /// Length or type of the packet
+  MacAddress m_source;        /// Source address
+  MacAddress m_destination;   /// Destination address
+};
+
+}; // namespace ns3
+
+
+#endif /* ETHERNET_HEADER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ethernet-trailer.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,124 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/trailer.h"
+#include "ethernet-trailer.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("EthernetTrailer");
+
+namespace ns3 {
+
+bool EthernetTrailer::m_calcFcs = false;
+
+EthernetTrailer::EthernetTrailer ()
+{
+  Init();
+}
+
+EthernetTrailer::~EthernetTrailer ()
+{}
+
+void EthernetTrailer::Init()
+{
+  m_fcs = 0;
+}
+
+void 
+EthernetTrailer::EnableFcs (bool enable)
+{
+  m_calcFcs = enable;
+}
+
+bool
+EthernetTrailer::CheckFcs (const Packet& p) const
+{
+  if (!m_calcFcs)
+    {
+      return true;
+    } else {
+      NS_DEBUG("FCS calculation is not yet enabled" << std::endl);
+      return false;
+    }
+}
+
+void
+EthernetTrailer::CalcFcs (const Packet& p)
+{
+  NS_DEBUG("FCS calculation is not yet enabled" << std::endl);
+}
+
+void
+EthernetTrailer::SetFcs (uint32_t fcs)
+{
+  m_fcs = fcs;
+}
+
+uint32_t
+EthernetTrailer::GetFcs (void)
+{
+  return m_fcs;
+}
+
+uint32_t
+EthernetTrailer::GetTrailerSize (void) const
+{
+  return GetSerializedSize();
+}
+std::string
+EthernetTrailer::DoGetName (void) const
+{
+  return "ETHERNET";
+}
+
+void 
+EthernetTrailer::PrintTo (std::ostream &os) const
+{
+  os << " fcs=" << m_fcs;
+}
+uint32_t 
+EthernetTrailer::GetSerializedSize (void) const
+{
+  return 4;
+}
+
+void
+EthernetTrailer::SerializeTo (Buffer::Iterator end) const
+{
+  Buffer::Iterator i = end;
+  i.Prev(GetSerializedSize());
+  
+  i.WriteU32 (m_fcs);
+}
+uint32_t
+EthernetTrailer::DeserializeFrom (Buffer::Iterator end)
+{
+  Buffer::Iterator i = end;
+  uint32_t size = GetSerializedSize();
+  i.Prev(size);
+
+  m_fcs = i.ReadU32 ();
+
+  return size;
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ethernet-trailer.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,104 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#ifndef ETHERNET_TRAILER_H
+#define ETHERNET_TRAILER_H
+
+#include "ns3/trailer.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+/**
+ * \brief Packet trailer for Ethernet
+ *
+ * This class can be used to add and verify the FCS at the end of an
+ * ethernet packet. The actual FCS functionality is not yet coded and
+ * so this acts more as a placeholder.
+ */
+class EthernetTrailer : public Trailer {
+public:
+  /**
+   * \brief Construct a null ethernet trailer
+   */
+  EthernetTrailer ();
+  virtual ~EthernetTrailer ();
+  /**
+   * \brief Enable or disabled FCS checking and calculations
+   * \param enable If true, enables FCS calculations.
+   */
+  static void EnableFcs (bool enable);
+  /**
+   * \brief Updates the Fcs Field to the correct FCS
+   * \param p Reference to a packet on which the FCS should be
+   * calculated. The packet should not currently contain an FCS
+   * trailer.
+   */
+  void CalcFcs (const Packet& p);
+  /**
+   * \brief Sets the FCS to a new value
+   * \param fcs New FCS value
+   */
+  void SetFcs (uint32_t fcs);
+  /**
+   * \return the FCS contained in this trailer
+   */
+  uint32_t GetFcs ();
+
+  /**
+   * \param p Reference to the packet on which the FCS should be
+   * calculated. The packet should not contain an FCS trailer.
+   * \return Returns true if the packet fcs is correct, false otherwise.
+   *
+   * If FCS checking is disabled, this method will always
+   * return true.
+   */
+  bool CheckFcs (const Packet& p) const;
+
+  /**
+   *\return Returns the size of the trailer
+   */ 
+  uint32_t GetTrailerSize() const;
+
+private:
+  virtual std::string DoGetName (void) const;
+  virtual void PrintTo (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void SerializeTo (Buffer::Iterator end) const;
+  virtual uint32_t DeserializeFrom (Buffer::Iterator end);
+
+  /**
+   * Initializes the trailer parameters during construction.
+   */
+  void Init (void);
+
+  /**
+   * Enabled FCS calculations. If false, fcs is set to 0 and checkFCS
+   * returns true.
+   */
+  static bool m_calcFcs;
+  uint32_t m_fcs; /// Value of the fcs contained in the trailer
+
+};
+
+}; // namespace ns3
+
+
+#endif /* ETHERNET_TRAILER_H */
--- a/src/node/ipv4-address.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/ipv4-address.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -156,8 +156,20 @@
   }
 }
 
+Ipv4Address
+Ipv4Address::CombineMask (Ipv4Mask const &mask) const
+{
+  return Ipv4Address (GetHostOrder () & mask.GetHostOrder ());
+}
+
+bool
+Ipv4Address::IsBroadcast (void) const
+{
+  return (m_address == 0xffffffffU);
+}
+
 bool 
-Ipv4Address::IsMulticast (void)
+Ipv4Address::IsMulticast (void) const
 {
   // XXX
   return false;
--- a/src/node/ipv4-address.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/ipv4-address.h	Fri Aug 03 08:29:24 2007 -0700
@@ -27,6 +27,8 @@
 
 namespace ns3 {
 
+class Ipv4Mask;
+
 /** Ipv4 addresses are stored in host order in
   * this class.
   */
@@ -96,8 +98,18 @@
    */
   void Print (std::ostream &os) const;
 
-  bool IsBroadcast (void);
-  bool IsMulticast (void);
+  bool IsBroadcast (void) const;
+  bool IsMulticast (void) const;
+  /**
+   * \brief Combine this address with a network mask
+   *
+   * This method returns an IPv4 address that is this address combined
+   * (bitwise and) with a network mask, yielding an IPv4 network
+   * address.
+   *
+   * \param a network mask 
+   */
+  Ipv4Address CombineMask (Ipv4Mask const &mask) const;
 
   static Ipv4Address GetZero (void);
   static Ipv4Address GetAny (void);
--- a/src/node/ipv4.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/ipv4.h	Fri Aug 03 08:29:24 2007 -0700
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include "ns3/ipv4-address.h"
 #include "ns3/object.h"
+#include "ns3/callback.h"
 #include "ipv4-route.h"
 
 namespace ns3 {
@@ -31,6 +32,78 @@
 class NetDevice;
 class Packet;
 class Ipv4Route;
+class Ipv4Header; // FIXME: ipv4-header.h needs to move from module
+                  // "internet-node" to module "node"
+
+/**
+ * \brief Base class for IPv4 routing protocols.
+ *
+ * This class represents the interface between the IPv4 routing core
+ * and a specific IPv4 routing protocol.  The interface is
+ * asynchronous (callback based) in order to support reactive routing
+ * protocols (e.g. AODV).
+ */
+class Ipv4RoutingProtocol : public Object
+{
+public:
+  // void (*RouteReply) (bool found, Ipv4Route route, Packet packet, Ipv4Header const &ipHeader);
+
+
+  /**
+   * \brief Callback to be invoked when route discovery is completed
+   *
+   * \param bool flag indicating whether a route was actually found;
+   * when this is false, the Ipv4Route parameter is ignored
+   *
+   * \param Ipv4Route the route found
+   *
+   * \param Packet the packet for which a route was requested; can be
+   * modified by the routing protocol
+   *
+   * \param Ipv4Header the IP header supplied to the route request
+   * method (possibly modified in case a new routing header is
+   * inserted and consequently the protocol type has to change).
+   *
+   */
+  typedef Callback<void, bool, const Ipv4Route&, Packet, const Ipv4Header&> RouteReplyCallback;
+
+  /**
+   * \brief Asynchronously requests a route for a given packet and IP header
+   *
+   * \param ipHeader IP header of the packet
+   * \param packet packet that is being sent or forwarded
+   * \param routeReply callback that will receive the route reply
+   *
+   * \returns true if the routing protocol should be able to get the
+   * route, false otherwise.
+   *
+   * This method is called whenever a node's IPv4 forwarding engine
+   * needs to lookup a route for a given packet and IP header.
+   *
+   * The routing protocol implementation may determine immediately it
+   * should not be handling this particular the route request.  For
+   * instance, a routing protocol may decline to search for routes for
+   * certain classes of addresses, like link-local.  In this case,
+   * RequestRoute() should return false and the routeReply callback
+   * must not be invoked.
+   *
+   * If the routing protocol implementations assumes it can provide
+   * the requested route, then it should return true, and the
+   * routeReply callback must be invoked, either immediately before
+   * returning true (synchronously), or in the future (asynchronous).
+   * The routing protocol may use any information available in the IP
+   * header and packet as routing key, although most routing protocols
+   * use only the destination address (as given by
+   * ipHeader.GetDestination ()).  The routing protocol is also
+   * allowed to add a new header to the packet, which will appear
+   * immediately after the IP header, although most routing do not
+   * insert any extra header.
+   */
+  virtual bool RequestRoute (const Ipv4Header &ipHeader,
+                             Packet packet,
+                             RouteReplyCallback routeReply) = 0;
+};
+
 /**
  * \brief Access to the Ipv4 forwarding table and to the ipv4 interfaces
  *
@@ -47,7 +120,20 @@
   static const InterfaceId iid;
   Ipv4 ();
   virtual ~Ipv4 ();
-    
+
+  /**
+   * \brief Register a new routing protocol to be used in this IPv4 stack
+   * 
+   * \param routingProtocol new routing protocol implementation object
+   * \param priority priority to give to this routing protocol.
+   * Values may range between -32768 and +32767.  The priority 0
+   * corresponds to static routing table lookups, higher values have
+   * more priority.  The order by which routing protocols with the
+   * same priority value are consulted is undefined.
+   */
+  virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
+                                   int16_t priority) = 0;
+  
   /**
    * \param dest destination address
    * \param nextHop address of next hop.
--- a/src/node/mac-address.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/mac-address.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -33,6 +33,9 @@
 
 namespace ns3 {
 
+// Static variables
+uint8_t MacAddress::g_nextAddress[MacAddress::MAX_LEN];
+
 static char
 AsciiToLowCase (char c)
 {
@@ -54,6 +57,13 @@
     }
 }
 
+MacAddress::MacAddress(uint8_t len) : m_len(len)
+{
+  NS_ASSERT (len <= MacAddress::MAX_LEN);
+  AdvanceAddress();
+  memcpy(m_address, g_nextAddress, len);
+}
+
 MacAddress::MacAddress (uint8_t const *address, uint8_t len)
 {
   NS_ASSERT (len <= MacAddress::MAX_LEN);
@@ -148,6 +158,17 @@
         m_len = len;
 }
 
+// Static methods
+void MacAddress::AdvanceAddress()
+  {
+    // Advance to next address, little end first
+    for(size_t i = 0; i < MAX_LEN; ++i)
+      {
+        if (++g_nextAddress[i] != 0) break;
+      }
+  }
+
+// Non-member operators
 bool operator == (MacAddress const&a, MacAddress const&b)
 {
 	return a.IsEqual (b);
--- a/src/node/mac-address.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/mac-address.h	Fri Aug 03 08:29:24 2007 -0700
@@ -47,6 +47,13 @@
    */
   MacAddress (void);
   /**
+   * \brief Construct a MacAddress using the next available
+   * address.
+   * \see MacAddres::Next
+   * \param len length, in bytes, of the desired address
+   */
+  MacAddress(uint8_t len);
+  /**
    * \brief Construct a MacAddress from a byte-array
    *
    * low byte should be first.
@@ -97,6 +104,14 @@
    */
   void Set (uint8_t const ad[MAX_LEN], uint8_t len);
 
+  // Static methods/members
+  /**
+   *
+   * Advance the global to the next available mac address.
+   */
+  static void AdvanceAddress();
+  static uint8_t g_nextAddress[MAX_LEN];
+
 private:
   uint8_t m_address[MAX_LEN];
   uint8_t m_len;
--- a/src/node/net-device.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/net-device.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -22,12 +22,15 @@
 #include <iostream>
 #include "ns3/assert.h"
 #include "ns3/object.h"
+#include "ns3/debug.h"
+
 
 #include "channel.h"
 #include "net-device.h"
-#include "llc-snap-header.h"
 #include "node.h"
 
+NS_DEBUG_COMPONENT_DEFINE ("NetDevice");
+
 namespace ns3 {
 
 const InterfaceId NetDevice::iid = MakeInterfaceId ("NetDevice", Object::iid);
@@ -172,10 +175,7 @@
 {
   if (m_isUp)
     {
-      LlcSnapHeader llc;
-      llc.SetType (protocolNumber);
-      p.AddHeader (llc);
-      return SendTo(p, dest);
+      return SendTo(p, dest, protocolNumber);
     }
   else
     {
@@ -195,18 +195,24 @@
   return DoGetChannel ();
 }
 
-// Receive packet from below
+// Receive packets from below
 bool
-NetDevice::ForwardUp (Packet& packet)
+NetDevice::ForwardUp(Packet& p, uint32_t param)
 {
   bool retval = false;
-  LlcSnapHeader llc;
-  packet.RemoveHeader (llc);
+  Packet packet = p;
+
+  NS_DEBUG ("NetDevice::ForwardUp: UID is " << packet.GetUid()
+            << " device is: " << GetName());
+  
   if (!m_receiveCallback.IsNull ())
     {
-      retval = m_receiveCallback (this, packet, llc.GetType ());
+      retval = m_receiveCallback (this, packet, param);
+    } else {
+      NS_DEBUG ("NetDevice::Receive call back is NULL");
     }
-  return retval;
+
+    return retval;
 }
 
 void 
--- a/src/node/net-device.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/net-device.h	Fri Aug 03 08:29:24 2007 -0700
@@ -17,6 +17,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Modified by Emmanuelle Laprise to remove dependance on LLC headers
  */
 #ifndef NET_DEVICE_H
 #define NET_DEVICE_H
@@ -227,6 +228,8 @@
 
   /**
    * \param p packet sent from below up to Network Device
+   * \param param Extra parameter extracted from header and needed by
+   * some protocols
    * \returns true if the packet was forwarded successfully,
    *          false otherwise.
    *
@@ -234,7 +237,8 @@
    * forwards it to the higher layers by calling this method
    * which is responsible for passing it up to the Rx callback.
    */
-  bool ForwardUp (Packet& p);
+  bool ForwardUp (Packet& p, uint32_t param);
+
 
   /**
    * The dispose method for this NetDevice class.
@@ -244,10 +248,13 @@
    */
   virtual void DoDispose (void);
 
+  Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t> m_receiveCallback;
+
  private:
   /**
    * \param p packet to send
    * \param dest address of destination to which packet must be sent
+   * \param protocolNumber Number of the protocol (used with some protocols)
    * \returns true if the packet could be sent successfully, false
    *          otherwise.
    *
@@ -255,7 +262,7 @@
    * method.  When the link is Up, this method is invoked to ask 
    * subclasses to forward packets. Subclasses MUST override this method.
    */
-  virtual bool SendTo (Packet& p, const MacAddress& dest) = 0;
+  virtual bool SendTo (Packet& p, const MacAddress &dest, uint16_t protocolNumber) = 0;
   /**
    * \returns true if this NetDevice needs the higher-layers
    *          to perform ARP over it, false otherwise.
@@ -279,7 +286,7 @@
    */
   virtual Ptr<Channel> DoGetChannel (void) const = 0;
 
-  Ptr<Node>         m_node;
+  Ptr<Node>     m_node;
   std::string   m_name;
   uint16_t      m_ifIndex;
   MacAddress    m_address;
@@ -290,7 +297,6 @@
   bool          m_isMulticast;
   bool          m_isPointToPoint;
   Callback<void> m_linkChangeCallback;
-  Callback<bool,Ptr<NetDevice>,const Packet &,uint16_t> m_receiveCallback;
 };
 
 }; // namespace ns3
--- a/src/node/node.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/node.h	Fri Aug 03 08:29:24 2007 -0700
@@ -160,7 +160,7 @@
    * at this point to setup the node's receive function for
    * the NetDevice packets.
    */
-  virtual void DoAddDevice (Ptr<NetDevice> device) const = 0;
+  virtual void DoAddDevice (Ptr<NetDevice> device) = 0;
 
   uint32_t    m_id;         // Node id for this node
   uint32_t    m_sid;        // System id for this node
--- a/src/node/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/node/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -1,9 +1,5 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
-def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-node')
-
-
 def build(bld):
     node = bld.create_obj('cpp', 'shlib')
     node.name = 'ns3-node'
@@ -14,7 +10,10 @@
         'ipv4-address.cc',
         'net-device.cc',
         'mac-address.cc',
+        'address-utils.cc',
         'llc-snap-header.cc',
+        'ethernet-header.cc',
+        'ethernet-trailer.cc',
         'ipv4-route.cc',
         'queue.cc',
         'drop-tail-queue.cc',
@@ -33,10 +32,13 @@
         'ipv4-address.h',
         'net-device.h',
         'mac-address.h',
+        'address-utils.h',
         'ipv4-route.h',
         'queue.h',
         'drop-tail-queue.h',
         'llc-snap-header.h',
+        'ethernet-header.h',
+        'ethernet-trailer.h',
         'channel.h',
         'node-list.h',
         'socket.h',
--- a/src/simulator/event-id.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/event-id.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -30,7 +30,7 @@
     m_uid (0)
 {}
   
-EventId::EventId (EventImpl *impl, uint64_t ts, uint32_t uid)
+EventId::EventId (const Ptr<EventImpl> &impl, uint64_t ts, uint32_t uid)
   : m_eventImpl (impl),
     m_ts (ts),
     m_uid (uid)
@@ -38,26 +38,22 @@
 void 
 EventId::Cancel (void)
 {
-  if (!IsExpired ())
-    {
-      m_eventImpl->Cancel ();
-      m_eventImpl = 0;
-    }
+  Simulator::Cancel (*this);
 }
 bool 
-EventId::IsExpired (void)
+EventId::IsExpired (void) const
 {
   return Simulator::IsExpired (*this);
 }
 bool 
-EventId::IsRunning (void)
+EventId::IsRunning (void) const
 {
   return !IsExpired ();
 }
 EventImpl *
-EventId::GetEventImpl (void) const
+EventId::PeekEventImpl (void) const
 {
-  return m_eventImpl;
+  return PeekPointer (m_eventImpl);
 }
 uint64_t 
 EventId::GetTs (void) const
@@ -70,5 +66,18 @@
   return m_uid;
 }
 
+bool operator == (const EventId &a, const EventId &b)
+{
+  return 
+    a.m_uid == b.m_uid && 
+    a.m_ts == b.m_ts && 
+    a.m_eventImpl == b.m_eventImpl;
+}
+bool operator != (const EventId &a, const EventId &b)
+{
+  return !(a == b);
+}
+
+
 
 }; // namespace ns3
--- a/src/simulator/event-id.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/event-id.h	Fri Aug 03 08:29:24 2007 -0700
@@ -22,6 +22,8 @@
 #define EVENT_ID_H
 
 #include <stdint.h>
+#include "ns3/ptr.h"
+#include "event-impl.h"
 
 namespace ns3 {
 
@@ -33,7 +35,7 @@
 class EventId {
 public:
   EventId ();
-  EventId (EventImpl *impl, uint64_t ts, uint32_t uid);
+  EventId (const Ptr<EventImpl> &impl, uint64_t ts, uint32_t uid);
   /**
    * This method is syntactic sugar for the ns3::Simulator::cancel
    * method.
@@ -44,22 +46,26 @@
    * method.
    * \returns true if the event has expired, false otherwise.
    */
-  bool IsExpired (void);
-  bool IsRunning (void);
+  bool IsExpired (void) const;
+  bool IsRunning (void) const;
 public:
   /* The following methods are semi-private
    * they are supposed to be invoked only by
    * subclasses of the Scheduler base class.
    */
-  EventImpl *GetEventImpl (void) const;
+  EventImpl *PeekEventImpl (void) const;
   uint64_t GetTs (void) const;
   uint32_t GetUid (void) const;
 private:
-  EventImpl *m_eventImpl;
+  friend bool operator == (const EventId &a, const EventId &b);
+  Ptr<EventImpl> m_eventImpl;
   uint64_t m_ts;
   uint32_t m_uid;
 };
 
+bool operator == (const EventId &a, const EventId &b);
+bool operator != (const EventId &a, const EventId &b);
+
 }; // namespace ns3
 
 #endif /* EVENT_ID_H */
--- a/src/simulator/event-impl.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/event-impl.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -29,7 +29,8 @@
 {}
 
 EventImpl::EventImpl ()
-  : m_cancel (false)
+  : m_cancel (false),
+    m_count (1)
 {}
 void 
 EventImpl::Invoke (void)
--- a/src/simulator/event-impl.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/event-impl.h	Fri Aug 03 08:29:24 2007 -0700
@@ -28,6 +28,8 @@
 class EventImpl {
 public:
   EventImpl ();
+  inline void Ref (void) const;
+  inline void Unref (void) const;
   virtual ~EventImpl () = 0;
   void Invoke (void);
   void Cancel (void);
@@ -37,8 +39,28 @@
 private:
   friend class Event;
   bool m_cancel;
+  mutable uint32_t m_count;
 };
 
 }; // namespace ns3
 
+namespace ns3 {
+
+void
+EventImpl::Ref (void) const
+{
+  m_count++;
+}
+void
+EventImpl::Unref (void) const
+{
+  m_count--;
+  if (m_count == 0)
+    {
+      delete this;
+    }
+}
+
+} // namespace ns3
+
 #endif /* EVENT_IMPL_H */
--- a/src/simulator/scheduler-heap.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-heap.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -170,7 +170,7 @@
 }
 
 bool
-SchedulerHeap::RealIsEmpty (void) const
+SchedulerHeap::IsEmpty (void) const
 {
   return (m_heap.size () == 1)?true:false;
 }
@@ -222,58 +222,58 @@
 }
 
 
-EventId
-SchedulerHeap::RealInsert (EventImpl *event, Scheduler::EventKey key)
+void
+SchedulerHeap::Insert (const EventId &id)
 {
+  // acquire single ref
+  EventImpl *event = id.PeekEventImpl ();
+  event->Ref ();
+  Scheduler::EventKey key;
+  key.m_ts = id.GetTs ();
+  key.m_uid = id.GetUid ();
   m_heap.push_back (std::make_pair (event, key));
   BottomUp ();
-  return EventId (event, key.m_ts, key.m_uid);
 }
 
-EventImpl *
-SchedulerHeap::RealPeekNext (void) const
+EventId
+SchedulerHeap::PeekNext (void) const
 {
-  return m_heap[Root ()].first;
+  std::pair<EventImpl *,Scheduler::EventKey> next = m_heap[Root ()];
+  return EventId (next.first, next.second.m_ts, next.second.m_uid);
 }
-Scheduler::EventKey
-SchedulerHeap::RealPeekNextKey (void) const
+EventId
+SchedulerHeap::RemoveNext (void)
 {
-  return m_heap[Root ()].second;
-}
-void     
-SchedulerHeap::RealRemoveNext (void)
-{
+  std::pair<EventImpl *,Scheduler::EventKey> next = m_heap[Root ()];
   Exch (Root (), Last ());
   m_heap.pop_back ();
   TopDown (Root ());
+  return EventId (Ptr<EventImpl> (next.first, false), next.second.m_ts, next.second.m_uid);
 }
 
 
-EventImpl *
-SchedulerHeap::RealRemove (EventId id, Scheduler::EventKey *key)
+bool
+SchedulerHeap::Remove (const EventId &id)
 {
-  key->m_ts = id.GetTs ();
-  key->m_uid = id.GetUid ();
+  uint32_t uid = id.GetUid ();
   for (uint32_t i = 1; i < m_heap.size (); i++)
     {
-      if (key->m_uid == m_heap[i].second.m_uid)
+      if (uid == m_heap[i].second.m_uid)
         {
-          EventImpl *retval = m_heap[i].first;
+          NS_ASSERT (m_heap[i].first == id.PeekEventImpl ());
+          std::pair<EventImpl *,Scheduler::EventKey> next = m_heap[i];
+          // release single ref
+          next.first->Unref ();
           Exch (i, Last ());
           m_heap.pop_back ();
           TopDown (i);
-          return retval;
+          return true;
         }
     }
   NS_ASSERT (false);
   // quiet compiler
-  return 0;
+  return false;
 }
 
-bool 
-SchedulerHeap::RealIsValid (EventId id)
-{
-  return true;
-}
 }; // namespace ns3
 
--- a/src/simulator/scheduler-heap.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-heap.h	Fri Aug 03 08:29:24 2007 -0700
@@ -35,15 +35,13 @@
   SchedulerHeap ();
   virtual ~SchedulerHeap ();
 
+  virtual void Insert (const EventId &id);
+  virtual bool IsEmpty (void) const;
+  virtual EventId PeekNext (void) const;
+  virtual EventId RemoveNext (void);
+  virtual bool Remove (const EventId &ev);
+
 private:
-  virtual EventId RealInsert (EventImpl *event, Scheduler::EventKey key);
-  virtual bool RealIsEmpty (void) const;
-  virtual EventImpl *RealPeekNext (void) const;
-  virtual Scheduler::EventKey RealPeekNextKey (void) const;
-  virtual void RealRemoveNext (void);
-  virtual EventImpl *RealRemove (EventId ev, Scheduler::EventKey *key);
-  virtual bool RealIsValid (EventId id);
-
   typedef std::vector<std::pair<EventImpl *, Scheduler::EventKey> > BinaryHeap;
 
   inline uint32_t Parent (uint32_t id) const;
--- a/src/simulator/scheduler-list.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-list.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -66,65 +66,61 @@
     }
 }
 
-EventId
-SchedulerList::RealInsert (EventImpl *event, Scheduler::EventKey key)
+void
+SchedulerList::Insert (const EventId &id)
 {
+  Scheduler::EventKey key;
+  // acquire refcount on EventImpl
+  EventImpl *event = id.PeekEventImpl ();
+  event->Ref ();
+  key.m_ts = id.GetTs ();
+  key.m_uid = id.GetUid ();
   for (EventsI i = m_events.begin (); i != m_events.end (); i++) 
     {
       if (IsLower (&key, &i->second))
         {
           m_events.insert (i, std::make_pair (event, key));
-          return EventId (event, key.m_ts, key.m_uid);
+          return;
         }
     }
   m_events.push_back (std::make_pair (event, key));
-  return EventId (event, key.m_ts, key.m_uid);
 }
 bool 
-SchedulerList::RealIsEmpty (void) const
+SchedulerList::IsEmpty (void) const
 {
   return m_events.empty ();
 }
-EventImpl *
-SchedulerList::RealPeekNext (void) const
+EventId
+SchedulerList::PeekNext (void) const
 {
-  return m_events.front ().first;
-}
-Scheduler::EventKey
-SchedulerList::RealPeekNextKey (void) const
-{
-  return m_events.front ().second;
+  std::pair<EventImpl *, EventKey> next = m_events.front ();
+  return EventId (next.first, next.second.m_ts, next.second.m_uid);
 }
 
-void
-SchedulerList::RealRemoveNext (void)
+EventId
+SchedulerList::RemoveNext (void)
 {
+  std::pair<EventImpl *, EventKey> next = m_events.front ();
   m_events.pop_front ();
+  return EventId (Ptr<EventImpl> (next.first,false), next.second.m_ts, next.second.m_uid);
 }
 
-EventImpl *
-SchedulerList::RealRemove (EventId id, Scheduler::EventKey *key)
+bool
+SchedulerList::Remove (const EventId &id)
 {
   for (EventsI i = m_events.begin (); i != m_events.end (); i++) 
     {
       if (i->second.m_uid == id.GetUid ())
         {
-          EventImpl *retval = i->first;
-          NS_ASSERT (id.GetEventImpl () == retval);
-          key->m_ts = id.GetTs ();
-          key->m_uid = id.GetUid ();
+          NS_ASSERT (id.PeekEventImpl () == i->first);
+          // release single acquire ref.
+          i->first->Unref ();
           m_events.erase (i);
-          return retval;
+          return true;
         }
     }
   NS_ASSERT (false);
-  return 0;
-}
-
-bool 
-SchedulerList::RealIsValid (EventId id)
-{
-  return true;
+  return false;
 }
 
 }; // namespace ns3
--- a/src/simulator/scheduler-list.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-list.h	Fri Aug 03 08:29:24 2007 -0700
@@ -37,15 +37,13 @@
   SchedulerList ();
   virtual ~SchedulerList ();
 
+  virtual void Insert (const EventId &id);
+  virtual bool IsEmpty (void) const;
+  virtual EventId PeekNext (void) const;
+  virtual EventId RemoveNext (void);
+  virtual bool Remove (const EventId &ev);
+
  private:
-  virtual EventId RealInsert (EventImpl *event, EventKey key);
-  virtual bool RealIsEmpty (void) const;
-  virtual EventImpl *RealPeekNext (void) const;
-  virtual Scheduler::EventKey RealPeekNextKey (void) const;
-  virtual void RealRemoveNext (void);
-  virtual EventImpl *RealRemove (EventId ev, Scheduler::EventKey *key);
-  virtual bool RealIsValid (EventId id);
-
   inline bool IsLower (Scheduler::EventKey const*a, Scheduler::EventKey const*b) const;
 
   typedef std::list<std::pair<EventImpl*, EventKey> > Events;
--- a/src/simulator/scheduler-map.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-map.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -87,57 +87,55 @@
 
 
 
-EventId
-SchedulerMap::RealInsert (EventImpl *event, Scheduler::EventKey key)
+void
+SchedulerMap::Insert (const EventId &id)
 {
+  // acquire a single ref
+  EventImpl *event = id.PeekEventImpl ();
+  event->Ref ();
+  Scheduler::EventKey key;
+  key.m_ts = id.GetTs ();
+  key.m_uid = id.GetUid ();
   std::pair<EventMapI,bool> result;
   result = m_list.insert (std::make_pair (key, event));
   NS_ASSERT (result.second);
-  return EventId (event, key.m_ts, key.m_uid);
 }
 
 bool
-SchedulerMap::RealIsEmpty (void) const
+SchedulerMap::IsEmpty (void) const
 {
   return m_list.empty ();
 }
 
-EventImpl *
-SchedulerMap::RealPeekNext (void) const
-{
-  EventMapCI i = m_list.begin ();
-  NS_ASSERT (i != m_list.end ());
-  return (*i).second;
-}
-Scheduler::EventKey
-SchedulerMap::RealPeekNextKey (void) const
+EventId
+SchedulerMap::PeekNext (void) const
 {
   EventMapCI i = m_list.begin ();
   NS_ASSERT (i != m_list.end ());
-  return (*i).first;
-}
-void
-SchedulerMap::RealRemoveNext (void)
-{
-  m_list.erase (m_list.begin ());
+  
+  return EventId (i->second, i->first.m_ts, i->first.m_uid);
 }
-
-EventImpl *
-SchedulerMap::RealRemove (EventId id, Scheduler::EventKey *key)
+EventId
+SchedulerMap::RemoveNext (void)
 {
-  key->m_ts = id.GetTs ();
-  key->m_uid = id.GetUid ();
-  EventMapI i = m_list.find (*key);
-  EventImpl *retval = i->second;
+  EventMapI i = m_list.begin ();
+  std::pair<Scheduler::EventKey, EventImpl*> next = *i;
   m_list.erase (i);
-  return retval;
+  return EventId (Ptr<EventImpl> (next.second, false), next.first.m_ts, next.first.m_uid);
 }
 
 bool
-SchedulerMap::RealIsValid (EventId id)
+SchedulerMap::Remove (const EventId &id)
 {
+  Scheduler::EventKey key;
+  key.m_ts = id.GetTs ();
+  key.m_uid = id.GetUid ();
+  EventMapI i = m_list.find (key);
+  NS_ASSERT (i->second == id.PeekEventImpl ());
+  // release single ref.
+  i->second->Unref ();
+  m_list.erase (i);
   return true;
 }
 
-
 }; // namespace ns3
--- a/src/simulator/scheduler-map.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler-map.h	Fri Aug 03 08:29:24 2007 -0700
@@ -36,14 +36,12 @@
   SchedulerMap ();
   virtual ~SchedulerMap ();
 
+  virtual void Insert (const EventId &id);
+  virtual bool IsEmpty (void) const;
+  virtual EventId PeekNext (void) const;
+  virtual EventId RemoveNext (void);
+  virtual bool Remove (const EventId &ev);
 private:
-  virtual EventId RealInsert (EventImpl *event, Scheduler::EventKey key);
-  virtual bool RealIsEmpty (void) const;
-  virtual EventImpl *RealPeekNext (void) const;
-  virtual Scheduler::EventKey RealPeekNextKey (void) const;
-  virtual void RealRemoveNext (void);
-  virtual EventImpl *RealRemove (EventId ev, Scheduler::EventKey *key);
-  virtual bool RealIsValid (EventId id);
 
   class EventKeyCompare {
   public:
@@ -56,7 +54,6 @@
 
 
   EventMap m_list;
-  uint32_t m_uid;
 };
 
 }; // namespace ns3
--- a/src/simulator/scheduler.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -27,39 +27,4 @@
 Scheduler::~Scheduler () 
 {}
 
-EventId 
-Scheduler::Insert (EventImpl *event, struct EventKey key)
-{
-  return RealInsert (event, key);
-}
-bool 
-Scheduler::IsEmpty (void) const
-{
-  return RealIsEmpty ();
-}
-EventImpl *
-Scheduler::PeekNext (void) const
-{
-  NS_ASSERT (!RealIsEmpty ());
-  return RealPeekNext ();
-}
-Scheduler::EventKey 
-Scheduler::PeekNextKey (void) const 
-{
-  NS_ASSERT (!RealIsEmpty ());
-  return RealPeekNextKey ();
-}
-void 
-Scheduler::RemoveNext (void)
-{
-  NS_ASSERT (!RealIsEmpty ());
-  return RealRemoveNext ();
-}
-EventImpl *
-Scheduler::Remove (EventId id, EventKey *key)
-{
-  NS_ASSERT (!RealIsEmpty ());
-  return RealRemove (id, key);
-}
-
 }; // namespace ns3
--- a/src/simulator/scheduler.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/scheduler.h	Fri Aug 03 08:29:24 2007 -0700
@@ -27,22 +27,18 @@
 
 namespace ns3 {
 
-class EventImpl;
-
 /**
  * \brief Maintain the event list
  *
  * This base class specifies the interface used to maintain the 
  * event list. If you want to provide a new event list scheduler, 
  * you need to create a subclass of this base class and implement 
- * all the private pure virtual methods defined here. Namely:
- *   - ns3::Scheduler::realInsert
- *   - ns3::Scheduler::realIsEmpty
- *   - ns3::Scheduler::realPeekNext
- *   - ns3::Scheduler::realPeekNextKey
- *   - ns3::Scheduler::realRemoveNext
- *   - ns3::Scheduler::realRemove
- *   - ns3::Scheduler::realIsValid
+ * all the pure virtual methods defined here. Namely:
+ *   - ns3::Scheduler::Insert
+ *   - ns3::Scheduler::IsEmpty
+ *   - ns3::Scheduler::PeekNext
+ *   - ns3::Scheduler::RemoveNext
+ *   - ns3::Scheduler::Remove
  *
  * If you need to provide a new event list scheduler without
  * editing the main simulator class, you need to also implement
@@ -61,14 +57,6 @@
 
   virtual ~Scheduler () = 0;
 
-  EventId Insert (EventImpl *event, EventKey key);
-  bool IsEmpty (void) const;
-  EventImpl *PeekNext (void) const;
-  Scheduler::EventKey PeekNextKey (void) const ;
-  void RemoveNext (void);
-  EventImpl *Remove (EventId id, EventKey *key);
-
-private:
   /**
    * \param event event to store in the event list
    * \param key timecode associated to this new event
@@ -76,29 +64,23 @@
    *
    * This method takes ownership of the event pointer.
    */
-  virtual EventId RealInsert (EventImpl *event, EventKey key) = 0;
+  virtual void Insert (const EventId &id) = 0;
   /**
    * \returns true if the event list is empty and false otherwise.
    */
-  virtual bool RealIsEmpty (void) const = 0;
+  virtual bool IsEmpty (void) const = 0;
   /**
    * \returns a pointer to the next earliest event. The caller
    *      takes ownership of the returned pointer.
    *
    * This method cannot be invoked if the list is empty.
    */
-  virtual EventImpl *RealPeekNext (void) const = 0;
-  /**
-   * \returns the timecode associated with the next earliest event.
-   *
-   * This method cannot be invoked if the list is empty.
-   */
-  virtual Scheduler::EventKey RealPeekNextKey (void) const = 0;
+  virtual EventId PeekNext (void) const = 0;
   /**
    * This method cannot be invoked if the list is empty.
    * Remove the next earliest event from the event list.
    */
-  virtual void RealRemoveNext (void) = 0;
+  virtual EventId RemoveNext (void) = 0;
   /**
    * \param id the id of the event to remove
    * \param key the timecode of the event removed
@@ -107,7 +89,7 @@
    *
    * This methods cannot be invoked if the list is empty.
    */
-  virtual EventImpl *RealRemove (EventId id, EventKey *key) = 0;
+  virtual bool Remove (const EventId &id) = 0;
 };
 
 }; // namespace ns3
--- a/src/simulator/simulator.cc	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/simulator.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -23,6 +23,7 @@
 #include "scheduler.h"
 #include "event-impl.h"
 
+#include "ns3/ptr.h"
 #include "ns3/assert.h"
 #include "ns3/default-value.h"
 
@@ -61,12 +62,12 @@
   Time Next (void) const;
   void Stop (void);
   void StopAt (Time const &time);
-  EventId Schedule (Time const &time, EventImpl *event);
-  void ScheduleNow (EventImpl *event);
-  void ScheduleDestroy (EventImpl *event);
-  void Remove (EventId ev);
-  void Cancel (EventId &ev);
-  bool IsExpired (EventId ev);
+  EventId Schedule (Time const &time, const Ptr<EventImpl> &event);
+  EventId ScheduleNow (const Ptr<EventImpl> &event);
+  EventId ScheduleDestroy (const Ptr<EventImpl> &event);
+  void Remove (const EventId &ev);
+  void Cancel (const EventId &ev);
+  bool IsExpired (const EventId &ev);
   void Run (void);
   Time Now (void) const;
 
@@ -74,8 +75,8 @@
   void ProcessOneEvent (void);
   uint64_t NextTs (void) const;
 
-  typedef std::list<std::pair<EventImpl *,uint32_t> > Events;
-  Events m_destroy;
+  typedef std::list<EventId> DestroyEvents;
+  DestroyEvents m_destroyEvents;
   uint64_t m_stopAt;
   bool m_stop;
   Scheduler *m_events;
@@ -98,8 +99,11 @@
   m_stop = false;
   m_stopAt = 0;
   m_events = events;
-  // uids are allocated from 1.
-  m_uid = 1; 
+  // uids are allocated from 4.
+  // uid 0 is "invalid" events
+  // uid 1 is "now" events
+  // uid 2 is "destroy" events
+  m_uid = 4; 
   // before ::Run is entered, the m_currentUid will be zero
   m_currentUid = 0;
   m_logEnable = false;
@@ -109,13 +113,15 @@
 
 SimulatorPrivate::~SimulatorPrivate ()
 {
-  while (!m_destroy.empty ()) 
+  while (!m_destroyEvents.empty ()) 
     {
-      EventImpl *ev = m_destroy.front ().first;
-      m_destroy.pop_front ();
+      Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
+      m_destroyEvents.pop_front ();
       TRACE ("handle destroy " << ev);
-      ev->Invoke ();
-      delete ev;
+      if (!ev->IsCancelled ())
+        {
+          ev->Invoke ();
+        }
     }
   delete m_events;
   m_events = (Scheduler *)0xdeadbeaf;
@@ -132,22 +138,20 @@
 void
 SimulatorPrivate::ProcessOneEvent (void)
 {
-  EventImpl *nextEv = m_events->PeekNext ();
-  Scheduler::EventKey nextKey = m_events->PeekNextKey ();
-  m_events->RemoveNext ();
+  EventId next = m_events->RemoveNext ();
 
-  NS_ASSERT (nextKey.m_ts >= m_currentTs);
+  NS_ASSERT (next.GetTs () >= m_currentTs);
   --m_unscheduledEvents;
 
   TRACE ("handle " << nextEv);
-  m_currentTs = nextKey.m_ts;
-  m_currentUid = nextKey.m_uid;
+  m_currentTs = next.GetTs ();
+  m_currentUid = next.GetUid ();
   if (m_logEnable) 
     {
-      m_log << "e "<<nextKey.m_uid << " " << nextKey.m_ts << std::endl;
+      m_log << "e "<<next.GetUid () << " " << next.GetTs () << std::endl;
     }
-  nextEv->Invoke ();
-  delete nextEv;
+  EventImpl *event = next.PeekEventImpl ();
+  event->Invoke ();
 }
 
 bool 
@@ -159,8 +163,8 @@
 SimulatorPrivate::NextTs (void) const
 {
   NS_ASSERT (!m_events->IsEmpty ());
-  Scheduler::EventKey nextKey = m_events->PeekNextKey ();
-  return nextKey.m_ts;
+  EventId id = m_events->PeekNext ();
+  return id.GetTs ();
 }
 Time
 SimulatorPrivate::Next (void) const
@@ -198,12 +202,12 @@
   m_stopAt = at.GetTimeStep ();
 }
 EventId
-SimulatorPrivate::Schedule (Time const &time, EventImpl *event)
+SimulatorPrivate::Schedule (Time const &time, const Ptr<EventImpl> &event)
 {
   NS_ASSERT (time.IsPositive ());
   NS_ASSERT (time >= TimeStep (m_currentTs));
   uint64_t ts = (uint64_t) time.GetTimeStep ();
-  Scheduler::EventKey key = {ts, m_uid};
+  EventId id (event, ts, m_uid);
   if (m_logEnable) 
     {
       m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
@@ -211,32 +215,35 @@
     }
   m_uid++;
   ++m_unscheduledEvents;
-  return m_events->Insert (event, key);
+  m_events->Insert (id);
+  return id;
 }
-void 
-SimulatorPrivate::ScheduleNow (EventImpl *event)
+EventId
+SimulatorPrivate::ScheduleNow (const Ptr<EventImpl> &event)
 {
-  uint64_t ts = m_currentTs;
-  Scheduler::EventKey key = {ts, m_uid};
+  EventId id (event, m_currentTs, m_uid);
   if (m_logEnable) 
     {
       m_log << "i "<<m_currentUid<<" "<<m_currentTs<<" "
-            <<m_uid<<" "<<ts << std::endl;
+            <<m_uid<<" "<<m_currentTs << std::endl;
     }
   m_uid++;
   ++m_unscheduledEvents;
-  m_events->Insert (event, key);
+  m_events->Insert (id);
+  return id;
 }
-void 
-SimulatorPrivate::ScheduleDestroy (EventImpl *event)
+EventId
+SimulatorPrivate::ScheduleDestroy (const Ptr<EventImpl> &event)
 {
-  m_destroy.push_back (std::make_pair (event, m_uid));  
+  EventId id (event, m_currentTs, 2);
+  m_destroyEvents.push_back (id);
   if (m_logEnable) 
   {
     m_log << "id " << m_currentUid << " " << Now ().GetTimeStep () << " "
           << m_uid << std::endl;
   }
   m_uid++;
+  return id;
 }
 
 Time
@@ -246,33 +253,65 @@
 }
 
 void
-SimulatorPrivate::Remove (EventId ev)
+SimulatorPrivate::Remove (const EventId &ev)
 {
-  Scheduler::EventKey key;
-  EventImpl *impl = m_events->Remove (ev, &key);
-  delete impl;
+  if (ev.GetUid () == 2)
+    {
+      // destroy events.
+      for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
+        {
+          if (*i == ev)
+            {
+              m_destroyEvents.erase (i);
+              break;
+            }
+         }
+      return;
+    }
+  if (IsExpired (ev))
+    {
+      return;
+    }
+  m_events->Remove (ev);
+  Cancel (ev);
+
   if (m_logEnable) 
     {
       m_log << "r " << m_currentUid << " " << m_currentTs << " "
-            << key.m_uid << " " << key.m_ts << std::endl;
+            << ev.GetUid () << " " << ev.GetTs () << std::endl;
     }
   --m_unscheduledEvents;
 }
 
 void
-SimulatorPrivate::Cancel (EventId &id)
+SimulatorPrivate::Cancel (const EventId &id)
 {
-  id.Cancel ();
+  if (!IsExpired (id))
+    {
+      id.PeekEventImpl ()->Cancel ();
+    }
 }
 
 bool
-SimulatorPrivate::IsExpired (EventId ev)
+SimulatorPrivate::IsExpired (const EventId &ev)
 {
-  if (ev.GetEventImpl () == 0 ||
+  if (ev.GetUid () == 2)
+    {
+      // destroy events.
+      for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
+        {
+          if (*i == ev)
+            {
+              return false;
+            }
+         }
+      return true;
+    }
+  if (ev.PeekEventImpl () == 0 ||
       ev.GetTs () < m_currentTs ||
       (ev.GetTs () == m_currentTs &&
        ev.GetUid () <= m_currentUid) ||
-      ev.GetEventImpl ()->IsCancelled ()) 
+      ev.PeekEventImpl ()->IsCancelled ()) 
     {
       return true;
     }
@@ -373,53 +412,53 @@
   return GetPriv ()->Now ();
 }
 
-EventImpl *
+Ptr<EventImpl>
 Simulator::MakeEvent (void (*f) (void))
 {
     // zero arg version
   class EventFunctionImpl0 : public EventImpl {
   public:
-  	typedef void (*F)(void);
+    typedef void (*F)(void);
       
-  	EventFunctionImpl0 (F function) 
-  		: m_function (function)
-  	{}
-  	virtual ~EventFunctionImpl0 () {}
+    EventFunctionImpl0 (F function) 
+      : m_function (function)
+    {}
+    virtual ~EventFunctionImpl0 () {}
   protected:
-  	virtual void Notify (void) { 
-  		(*m_function) (); 
-      }
+    virtual void Notify (void) { 
+      (*m_function) (); 
+    }
   private:
   	F m_function;
   } *ev = new EventFunctionImpl0 (f);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 EventId
-Simulator::Schedule (Time const &time, EventImpl *ev)
+Simulator::Schedule (Time const &time, const Ptr<EventImpl> &ev)
 {
   return GetPriv ()->Schedule (Now () + time, ev);
 }
-void
-Simulator::ScheduleNow (EventImpl *ev)
+EventId
+Simulator::ScheduleNow (const Ptr<EventImpl> &ev)
 {
-  GetPriv ()->ScheduleNow (ev);
+  return GetPriv ()->ScheduleNow (ev);
 }
-void
-Simulator::ScheduleDestroy (EventImpl *ev)
+EventId
+Simulator::ScheduleDestroy (const Ptr<EventImpl> &ev)
 {
-  GetPriv ()->ScheduleDestroy (ev);
+  return GetPriv ()->ScheduleDestroy (ev);
 }  
 EventId
 Simulator::Schedule (Time const &time, void (*f) (void))
 {
   return Schedule (time, MakeEvent (f));
 }
-void
+EventId
 Simulator::ScheduleNow (void (*f) (void))
 {
   return ScheduleNow (MakeEvent (f));
 }
-void
+EventId
 Simulator::ScheduleDestroy (void (*f) (void))
 {
   return ScheduleDestroy (MakeEvent (f));
@@ -427,18 +466,18 @@
 
 
 void
-Simulator::Remove (EventId ev)
+Simulator::Remove (const EventId &ev)
 {
   return GetPriv ()->Remove (ev);
 }
 
 void
-Simulator::Cancel (EventId &ev)
+Simulator::Cancel (const EventId &ev)
 {
   return GetPriv ()->Cancel (ev);
 }
 bool 
-Simulator::IsExpired (EventId id)
+Simulator::IsExpired (const EventId &id)
 {
   return GetPriv ()->IsExpired (id);
 }
@@ -469,7 +508,31 @@
 static void foo4 (int, int, int, int)
 {}
 static void foo5 (int, int, int, int, int)
-{}  
+{}
+
+#if 1
+static void ber1 (int &)
+{}
+static void ber2 (int &, int &)
+{}
+static void ber3 (int &, int &, int &)
+{}
+static void ber4 (int &, int &, int &, int &)
+{}
+static void ber5 (int &, int &, int &, int &, int &)
+{}
+#endif
+
+static void cber1 (const int &)
+{}
+static void cber2 (const int &, const int &)
+{}
+static void cber3 (const int &, const int &, const int &)
+{}
+static void cber4 (const int &, const int &, const int &, const int &)
+{}
+static void cber5 (const int &, const int &, const int &, const int &, const int &)
+{}
   
 
 class SimulatorTests : public Test {
@@ -493,12 +556,25 @@
   void bar3 (int, int, int);
   void bar4 (int, int, int, int);
   void bar5 (int, int, int, int, int);
+  void baz1 (int &);
+  void baz2 (int &, int &);
+  void baz3 (int &, int &, int &);
+  void baz4 (int &, int &, int &, int &);
+  void baz5 (int &, int &, int &, int &, int &);
+  void cbaz1 (const int &);
+  void cbaz2 (const int &, const int &);
+  void cbaz3 (const int &, const int &, const int &);
+  void cbaz4 (const int &, const int &, const int &, const int &);
+  void cbaz5 (const int &, const int &, const int &, const int &, const int &);
+  void destroy (void);
   
   bool m_b;
   bool m_a;
   bool m_c;
   bool m_d;
   EventId m_idC;
+  bool m_destroy;
+  EventId m_destroyId;
 };
 
 SimulatorTests::SimulatorTests ()
@@ -554,6 +630,14 @@
       m_d = true;
     }
 }
+void
+SimulatorTests::destroy (void)
+{
+  if (m_destroyId.IsExpired ())
+    {
+      m_destroy = true; 
+    }
+}
 void 
 SimulatorTests::bar0 (void)
 {}
@@ -573,6 +657,38 @@
 SimulatorTests::bar5 (int, int, int, int, int)
 {}
 
+void
+SimulatorTests::baz1 (int &)
+{}
+void
+SimulatorTests::baz2 (int &, int &)
+{}
+void
+SimulatorTests::baz3 (int &, int &, int &)
+{}
+void 
+SimulatorTests::baz4 (int &, int &, int &, int &)
+{}
+void 
+SimulatorTests::baz5 (int &, int &, int &, int &, int &)
+{}
+
+void
+SimulatorTests::cbaz1 (const int &)
+{}
+void
+SimulatorTests::cbaz2 (const int &, const int &)
+{}
+void
+SimulatorTests::cbaz3 (const int &, const int &, const int &)
+{}
+void 
+SimulatorTests::cbaz4 (const int &, const int &, const int &, const int &)
+{}
+void 
+SimulatorTests::cbaz5 (const int &, const int &, const int &, const int &, const int &)
+{}
+
 bool
 SimulatorTests::RunOneTest (void)
 {
@@ -638,6 +754,11 @@
   Simulator::Schedule (Seconds (0.0), &foo3, 0, 0, 0);
   Simulator::Schedule (Seconds (0.0), &foo4, 0, 0, 0, 0);
   Simulator::Schedule (Seconds (0.0), &foo5, 0, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &cber1, 0);
+  Simulator::Schedule (Seconds (0.0), &cber2, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &cber3, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &cber4, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &cber5, 0, 0, 0, 0, 0);
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar0, this);
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar1, this, 0);
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar2, this, 0, 0);
@@ -650,18 +771,33 @@
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar3, Ptr<SimulatorTests> (this), 0, 0, 0);
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar4, Ptr<SimulatorTests> (this), 0, 0, 0, 0);
   Simulator::Schedule (Seconds (0.0), &SimulatorTests::bar5, Ptr<SimulatorTests> (this), 0, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz1, this, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz2, this, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz3, this, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz4, this, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::cbaz5, this, 0, 0, 0, 0, 0);
   Simulator::ScheduleNow (&foo0);
   Simulator::ScheduleNow (&foo1, 0);
   Simulator::ScheduleNow (&foo2, 0, 0);
   Simulator::ScheduleNow (&foo3, 0, 0, 0);
   Simulator::ScheduleNow (&foo4, 0, 0, 0, 0);
   Simulator::ScheduleNow (&foo5, 0, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&cber1, 0);
+  Simulator::ScheduleNow (&cber2, 0, 0);
+  Simulator::ScheduleNow (&cber3, 0, 0, 0);
+  Simulator::ScheduleNow (&cber4, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&cber5, 0, 0, 0, 0, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar0, this);
   Simulator::ScheduleNow (&SimulatorTests::bar1, this, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar2, this, 0, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar3, this, 0, 0, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar4, this, 0, 0, 0, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar5, this, 0, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::cbaz1, this, 0);
+  Simulator::ScheduleNow (&SimulatorTests::cbaz2, this, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::cbaz3, this, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::cbaz4, this, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::cbaz5, this, 0, 0, 0, 0, 0);
   Simulator::ScheduleNow (&SimulatorTests::bar0, Ptr<SimulatorTests> (this));
   Simulator::ScheduleNow (&SimulatorTests::bar1, Ptr<SimulatorTests> (this), 0);
   Simulator::ScheduleNow (&SimulatorTests::bar2, Ptr<SimulatorTests> (this), 0, 0);
@@ -674,12 +810,22 @@
   Simulator::ScheduleDestroy (&foo3, 0, 0, 0);
   Simulator::ScheduleDestroy (&foo4, 0, 0, 0, 0);
   Simulator::ScheduleDestroy (&foo5, 0, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&cber1, 0);
+  Simulator::ScheduleDestroy (&cber2, 0, 0);
+  Simulator::ScheduleDestroy (&cber3, 0, 0, 0);
+  Simulator::ScheduleDestroy (&cber4, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&cber5, 0, 0, 0, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar0, this);
   Simulator::ScheduleDestroy (&SimulatorTests::bar1, this, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar2, this, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar3, this, 0, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar4, this, 0, 0, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar5, this, 0, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::cbaz1, this, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::cbaz2, this, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::cbaz3, this, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::cbaz4, this, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::cbaz5, this, 0, 0, 0, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar0, Ptr<SimulatorTests> (this));
   Simulator::ScheduleDestroy (&SimulatorTests::bar1, Ptr<SimulatorTests> (this), 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar2, Ptr<SimulatorTests> (this), 0, 0);
@@ -687,8 +833,73 @@
   Simulator::ScheduleDestroy (&SimulatorTests::bar4, Ptr<SimulatorTests> (this), 0, 0, 0, 0);
   Simulator::ScheduleDestroy (&SimulatorTests::bar5, Ptr<SimulatorTests> (this), 0, 0, 0, 0, 0);
 
+
+  // the code below does not compile, as expected.
+  //Simulator::Schedule (Seconds (0.0), &cber1, 0.0);
+
+#if 1
+  Simulator::Schedule (Seconds (0.0), &ber1, 0);
+  Simulator::Schedule (Seconds (0.0), &ber2, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &ber3, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &ber4, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &ber5, 0, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz1, this, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz2, this, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz3, this, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz4, this, 0, 0, 0, 0);
+  Simulator::Schedule (Seconds (0.0), &SimulatorTests::baz5, this, 0, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&ber1, 0);
+  Simulator::ScheduleNow (&ber2, 0, 0);
+  Simulator::ScheduleNow (&ber3, 0, 0, 0);
+  Simulator::ScheduleNow (&ber4, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&ber5, 0, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::baz1, this, 0);
+  Simulator::ScheduleNow (&SimulatorTests::baz2, this, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::baz3, this, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::baz4, this, 0, 0, 0, 0);
+  Simulator::ScheduleNow (&SimulatorTests::baz5, this, 0, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&ber1, 0);
+  Simulator::ScheduleDestroy (&ber2, 0, 0);
+  Simulator::ScheduleDestroy (&ber3, 0, 0, 0);
+  Simulator::ScheduleDestroy (&ber4, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&ber5, 0, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::baz1, this, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::baz2, this, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::baz3, this, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::baz4, this, 0, 0, 0, 0);
+  Simulator::ScheduleDestroy (&SimulatorTests::baz5, this, 0, 0, 0, 0, 0);
+#endif
+
+  EventId nowId = Simulator::ScheduleNow (&foo0);
+  m_destroyId = Simulator::ScheduleDestroy (&SimulatorTests::destroy, this);
+  if (m_destroyId.IsExpired ())
+    {
+      ok = false;
+    }
+
+  Simulator::Run ();
+  m_destroy = false;
+  Simulator::Destroy ();
+  if (!m_destroy) 
+    {
+      ok = false;
+    }
+
+  EventId anId = Simulator::ScheduleNow (&foo0);
+  EventId anotherId = anId;
+  if (anId.IsExpired () || anotherId.IsExpired ())
+    {
+      ok = false;
+    }
+  Simulator::Remove (anId);
+  if (!anId.IsExpired () || !anotherId.IsExpired ())
+    {
+      ok = false;
+    }
+
   Simulator::Run ();
   Simulator::Destroy ();
+  
 
   return ok;
 }
--- a/src/simulator/simulator.h	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/simulator.h	Fri Aug 03 08:29:24 2007 -0700
@@ -26,6 +26,7 @@
 #include "event-id.h"
 #include "event-impl.h"
 #include "nstime.h"
+#include "ns3/type-traits.h"
 
 namespace ns3 {
 
@@ -171,8 +172,8 @@
    * @param a1 the first argument to pass to the invoked method
    * @returns an id for the scheduled event.
    */
-  template <typename T, typename OBJ, typename T1>
-  static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
+  template <typename T, typename OBJ, typename U1, typename T1>
+  static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1), OBJ obj, T1 a1);
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -181,8 +182,8 @@
    * @param a2 the second argument to pass to the invoked method
    * @returns an id for the scheduled event.
    */
-  template <typename T, typename OBJ, typename T1, typename T2>
-  static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
+  template <typename T, typename OBJ, typename U1, typename U2, typename T1, typename T2>
+  static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2);
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -192,8 +193,10 @@
    * @param a3 the third argument to pass to the invoked method
    * @returns an id for the scheduled event.
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-  static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3);
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -204,8 +207,10 @@
    * @param a4 the fourth argument to pass to the invoked method
    * @returns an id for the scheduled event.
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-  static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
@@ -217,8 +222,10 @@
    * @param a5 the fifth argument to pass to the invoked method
    * @returns an id for the scheduled event.
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-  static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                            T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   /**
    * @param time the relative expiration time of the event.
@@ -232,8 +239,8 @@
    * @param a1 the first argument to pass to the function to invoke
    * @returns an id for the scheduled event.
    */
-  template <typename T1>
-  static EventId Schedule (Time const &time, void (*f) (T1), T1 a1);
+  template <typename U1, typename T1>
+  static EventId Schedule (Time const &time, void (*f) (U1), T1 a1);
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -241,8 +248,8 @@
    * @param a2 the second argument to pass to the function to invoke
    * @returns an id for the scheduled event.
    */
-  template <typename T1, typename T2>
-  static EventId Schedule (Time const &time, void (*f) (T1,T2), T1 a1, T2 a2);
+  template <typename U1, typename U2, typename T1, typename T2>
+  static EventId Schedule (Time const &time, void (*f) (U1,U2), T1 a1, T2 a2);
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -251,8 +258,8 @@
    * @param a3 the third argument to pass to the function to invoke
    * @returns an id for the scheduled event.
    */
-  template <typename T1, typename T2, typename T3>
-  static EventId Schedule (Time const &time, void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
+  template <typename U1, typename U2, typename U3, typename T1, typename T2, typename T3>
+  static EventId Schedule (Time const &time, void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -262,8 +269,9 @@
    * @param a4 the fourth argument to pass to the function to invoke
    * @returns an id for the scheduled event.
    */
-  template <typename T1, typename T2, typename T3, typename T4>
-  static EventId Schedule (Time const &time, void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename U1, typename U2, typename U3, typename U4, 
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId Schedule (Time const &time, void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param time the relative expiration time of the event.
    * @param f the function to invoke
@@ -274,8 +282,9 @@
    * @param a5 the fifth argument to pass to the function to invoke
    * @returns an id for the scheduled event.
    */
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  static EventId Schedule (Time const &time, void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+  template <typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId Schedule (Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
 
   /**
@@ -287,22 +296,26 @@
    * @param obj the object on which to invoke the member method
    */
   template <typename T, typename OBJ>
-  static void ScheduleNow (void (T::*mem_ptr) (void), OBJ obj);
+  static EventId ScheduleNow (void (T::*mem_ptr) (void), OBJ obj);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1>
-  static void ScheduleNow (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
+  template <typename T, typename OBJ, 
+            typename U1,  
+            typename T1>
+  static EventId ScheduleNow (void (T::*mem_ptr) (U1), OBJ obj, T1 a1);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
    * @param a2 the second argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2>
-  static void ScheduleNow (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2,
+            typename T1, typename T2>
+  static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -310,8 +323,10 @@
    * @param a2 the second argument to pass to the invoked method
    * @param a3 the third argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-  static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -320,8 +335,10 @@
    * @param a3 the third argument to pass to the invoked method
    * @param a4 the fourth argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-  static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, 
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, 
                            T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param mem_ptr member method pointer to invoke
@@ -332,34 +349,39 @@
    * @param a4 the fourth argument to pass to the invoked method
    * @param a5 the fifth argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-  static void ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                            T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   /**
    * @param f the function to invoke
    */
-  static void ScheduleNow (void (*f) (void));
+  static EventId ScheduleNow (void (*f) (void));
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    */
-  template <typename T1>
-  static void ScheduleNow (void (*f) (T1), T1 a1);
+  template <typename U1,
+            typename T1>
+  static EventId ScheduleNow (void (*f) (U1), T1 a1);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
    */
-  template <typename T1, typename T2>
-  static void ScheduleNow (void (*f) (T1,T2), T1 a1, T2 a2);
+  template <typename U1, typename U2,
+            typename T1, typename T2>
+  static EventId ScheduleNow (void (*f) (U1,U2), T1 a1, T2 a2);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
    * @param a3 the third argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3>
-  static void ScheduleNow (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
+  template <typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static EventId ScheduleNow (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -367,8 +389,9 @@
    * @param a3 the third argument to pass to the function to invoke
    * @param a4 the fourth argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3, typename T4>
-  static void ScheduleNow (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId ScheduleNow (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -377,8 +400,9 @@
    * @param a4 the fourth argument to pass to the function to invoke
    * @param a5 the fifth argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  static void ScheduleNow (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+  template <typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId ScheduleNow (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
 
   /**
@@ -391,22 +415,26 @@
    * @param obj the object on which to invoke the member method
    */
   template <typename T, typename OBJ>
-  static void ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj);
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1>
-  static void ScheduleDestroy (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
+  template <typename T, typename OBJ, 
+            typename U1,
+            typename T1>
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (U1), OBJ obj, T1 a1);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
    * @param a2 the second argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2>
-  static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
+  template <typename T, typename OBJ,
+            typename U1, typename U2,
+            typename T1, typename T2>
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -414,8 +442,10 @@
    * @param a2 the second argument to pass to the invoked method
    * @param a3 the third argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-  static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3);
   /**
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
@@ -424,8 +454,10 @@
    * @param a3 the third argument to pass to the invoked method
    * @param a4 the fourth argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-  static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, 
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, 
                                T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param mem_ptr member method pointer to invoke
@@ -436,34 +468,39 @@
    * @param a4 the fourth argument to pass to the invoked method
    * @param a5 the fifth argument to pass to the invoked method
    */
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-  static void ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                                T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   /**
    * @param f the function to invoke
    */
-  static void ScheduleDestroy (void (*f) (void));
+  static EventId ScheduleDestroy (void (*f) (void));
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    */
-  template <typename T1>
-  static void ScheduleDestroy (void (*f) (T1), T1 a1);
+  template <typename U1,
+            typename T1>
+  static EventId ScheduleDestroy (void (*f) (U1), T1 a1);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
    */
-  template <typename T1, typename T2>
-  static void ScheduleDestroy (void (*f) (T1,T2), T1 a1, T2 a2);
+  template <typename U1, typename U2,
+            typename T1, typename T2>
+  static EventId ScheduleDestroy (void (*f) (U1,U2), T1 a1, T2 a2);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
    * @param a3 the third argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3>
-  static void ScheduleDestroy (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
+  template <typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static EventId ScheduleDestroy (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -471,8 +508,9 @@
    * @param a3 the third argument to pass to the function to invoke
    * @param a4 the fourth argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3, typename T4>
-  static void ScheduleDestroy (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static EventId ScheduleDestroy (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
   /**
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
@@ -481,8 +519,9 @@
    * @param a4 the fourth argument to pass to the function to invoke
    * @param a5 the fifth argument to pass to the function to invoke
    */
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  static void ScheduleDestroy (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+  template <typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static EventId ScheduleDestroy (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
   /**
    * Remove an event from the event list. 
@@ -495,7 +534,7 @@
    *
    * @param id the event to remove from the list of scheduled events.
    */
-  static void Remove (EventId id);
+  static void Remove (const EventId &id);
   /**
    * Set the cancel bit on this event: the event's associated function
    * will not be invoked when it expires. 
@@ -508,7 +547,7 @@
    * 
    * @param id the event to cancel
    */
-  static void Cancel (EventId &id);
+  static void Cancel (const EventId &id);
   /**
    * This method has O(1) complexity.
    * Note that it is not possible to test for the expiration of
@@ -521,7 +560,7 @@
    * @param id the event to test for expiration
    * @returns true if the event has expired, false otherwise.
    */
-  static bool IsExpired (EventId id);
+  static bool IsExpired (const EventId &id);
   /**
    * Return the "current simulation time".
    */
@@ -529,35 +568,51 @@
 private:
   Simulator ();
   ~Simulator ();
+
   template <typename T, typename OBJ>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (void), OBJ obj);
-  template <typename T, typename OBJ, typename T1>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1);
-  template <typename T, typename OBJ, typename T1, typename T2>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2);
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3);
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
-  template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-  static EventImpl *MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (void), OBJ obj);
+  template <typename T, typename OBJ, 
+            typename U1,
+            typename T1>
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (U1), OBJ obj, T1 a1);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2,
+            typename T1, typename T2>
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename T, typename OBJ, 
+            typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static Ptr<EventImpl> MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                                T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
-  static EventImpl *MakeEvent (void (*f) (void));
-  template <typename T1>
-  static EventImpl *MakeEvent (void (*f) (T1), T1 a1);
-  template <typename T1, typename T2>
-  static EventImpl *MakeEvent (void (*f) (T1,T2), T1 a1, T2 a2);
-  template <typename T1, typename T2, typename T3>
-  static EventImpl *MakeEvent (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
-  template <typename T1, typename T2, typename T3, typename T4>
-  static EventImpl *MakeEvent (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  static EventImpl *MakeEvent (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+  static Ptr<EventImpl> MakeEvent (void (*f) (void));
+  template <typename U1, 
+            typename T1>
+  static Ptr<EventImpl> MakeEvent (void (*f) (U1), T1 a1);
+  template <typename U1, typename U2, 
+            typename T1, typename T2>
+  static Ptr<EventImpl> MakeEvent (void (*f) (U1,U2), T1 a1, T2 a2);
+  template <typename U1, typename U2, typename U3,
+            typename T1, typename T2, typename T3>
+  static Ptr<EventImpl> MakeEvent (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3);
+  template <typename U1, typename U2, typename U3, typename U4,
+            typename T1, typename T2, typename T3, typename T4>
+  static Ptr<EventImpl> MakeEvent (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4);
+  template <typename U1, typename U2, typename U3, typename U4, typename U5,
+            typename T1, typename T2, typename T3, typename T4, typename T5>
+  static Ptr<EventImpl> MakeEvent (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
   static SimulatorPrivate *GetPriv (void);
-  static EventId Schedule (Time const &time, EventImpl *event);
-  static void ScheduleDestroy (EventImpl *event);
-  static void ScheduleNow (EventImpl *event);
+  static EventId Schedule (Time const &time, const Ptr<EventImpl> &event);
+  static EventId ScheduleDestroy (const Ptr<EventImpl> &event);
+  static EventId ScheduleNow (const Ptr<EventImpl> &event);
   static SimulatorPrivate *m_priv;
 };
 
@@ -584,10 +639,10 @@
 namespace ns3 {
 
 template <typename T>
-struct EventMemberImplTraits;
+struct EventMemberImplObjTraits;
 
 template <typename T>
-struct EventMemberImplTraits<T *>
+struct EventMemberImplObjTraits<T *>
 {
   static T &GetReference (T *p) {
     return *p;
@@ -595,7 +650,7 @@
 };
 
 template <typename T, typename OBJ>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (void), OBJ obj) 
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (void), OBJ obj) 
 {
   // zero argument version
   class EventMemberImpl0 : public EventImpl {
@@ -608,22 +663,24 @@
     virtual ~EventMemberImpl0 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (); 
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (); 
     }
     OBJ m_obj;
     F m_function;
-  } *ev = new EventMemberImpl0 (obj, mem_ptr);
-  return ev;
+  } * ev = new EventMemberImpl0 (obj, mem_ptr);
+  return Ptr<EventImpl> (ev, false);
 }
 
 
-template <typename T, typename OBJ, typename T1>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1), OBJ obj, T1 a1) 
+template <typename T, typename OBJ, 
+          typename U1,
+          typename T1>
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (U1), OBJ obj, T1 a1)
 {
   // one argument version
   class EventMemberImpl1 : public EventImpl {
   public:
-    typedef void (T::*F)(T1);
+    typedef void (T::*F)(U1);
     EventMemberImpl1 (OBJ obj, F function, T1 a1) 
       : m_obj (obj), 
         m_function (function),
@@ -633,22 +690,24 @@
     virtual ~EventMemberImpl1 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1);
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1);
     }
     OBJ m_obj;
     F m_function;
-    T1 m_a1;
+    typename TypeTraits<T1>::ReferencedType m_a1;
   } *ev = new EventMemberImpl1 (obj, mem_ptr, a1);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T, typename OBJ, typename T1, typename T2>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2,
+          typename T1, typename T2>
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) 
 {
   // two argument version
   class EventMemberImpl2 : public EventImpl {
   public:
-    typedef void (T::*F)(T1, T2);
+    typedef void (T::*F)(U1, U2);
       
     EventMemberImpl2 (OBJ obj, F function, T1 a1, T2 a2) 
       : m_obj (obj), 
@@ -660,23 +719,25 @@
     virtual ~EventMemberImpl2 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2);
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2);
     }
     OBJ m_obj;
     F m_function;
-    T1 m_a1;
-    T2 m_a2;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
   } *ev = new EventMemberImpl2 (obj, mem_ptr, a1, a2);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) 
 {
   // three argument version
   class EventMemberImpl3 : public EventImpl {
   public:
-    typedef void (T::*F)(T1, T2, T3);
+    typedef void (T::*F)(U1,U2,U3);
       
     EventMemberImpl3 (OBJ obj, F function, T1 a1, T2 a2, T3 a3) 
       : m_obj (obj), 
@@ -689,24 +750,26 @@
     virtual ~EventMemberImpl3 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3);
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3);
     }
     OBJ m_obj;
     F m_function;
-    T1 m_a1;
-    T2 m_a2;
-    T3 m_a3;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
   } *ev = new EventMemberImpl3 (obj, mem_ptr, a1, a2, a3);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
 {
   // four argument version
   class EventMemberImpl4 : public EventImpl {
   public:
-    typedef void (T::*F)(T1, T2, T3, T4);
+    typedef void (T::*F)(U1, U2, U3, U4);
           
     EventMemberImpl4 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4) 
       : m_obj (obj), 
@@ -720,26 +783,28 @@
     virtual ~EventMemberImpl4 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4);
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4);
     }
     OBJ m_obj;
     F m_function;
-    T1 m_a1;
-    T2 m_a2;
-    T3 m_a3;
-    T4 m_a4;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
+    typename TypeTraits<T4>::ReferencedType m_a4;
   } *ev = new EventMemberImpl4 (obj, mem_ptr, a1, a2, a3, a4);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-EventImpl *Simulator::MakeEvent (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+Ptr<EventImpl> Simulator::MakeEvent (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                                  T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
   // five argument version
   class EventMemberImpl5 : public EventImpl {
   public:
-    typedef void (T::*F)(T1, T2, T3, T4, T5);
+    typedef void (T::*F)(U1, U2, U3, U4, U5);
       
     EventMemberImpl5 (OBJ obj, F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
       : m_obj (obj), 
@@ -754,157 +819,160 @@
     virtual ~EventMemberImpl5 () {}
   private:
     virtual void Notify (void) { 
-      (EventMemberImplTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
+      (EventMemberImplObjTraits<OBJ>::GetReference (m_obj).*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
     }
     OBJ m_obj;
     F m_function;
-    T1 m_a1;
-    T2 m_a2;
-    T3 m_a3;
-    T4 m_a4;
-    T5 m_a5;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
+    typename TypeTraits<T4>::ReferencedType m_a4;
+    typename TypeTraits<T5>::ReferencedType m_a5;
   } *ev = new EventMemberImpl5 (obj, mem_ptr, a1, a2, a3, a4, a5);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T1>
-EventImpl *Simulator::MakeEvent (void (*f) (T1), T1 a1) 
+template <typename U1, typename T1>
+Ptr<EventImpl> Simulator::MakeEvent (void (*f) (U1), T1 a1) 
 {
   // one arg version
   class EventFunctionImpl1 : public EventImpl {
   public:
-  	typedef void (*F)(T1);
+    typedef void (*F)(U1);
       
-  	EventFunctionImpl1 (F function, T1 a1) 
-  		: m_function (function),
-  		  m_a1 (a1)
-  	{ }
+    EventFunctionImpl1 (F function, T1 a1) 
+      : m_function (function),
+        m_a1 (a1)
+    { }
   protected:
-  	virtual ~EventFunctionImpl1 () {}
+    virtual ~EventFunctionImpl1 () {}
   private:
-  	virtual void Notify (void) { 
-  		(*m_function) (m_a1);
-  	}
-  	F m_function;
-  	T1 m_a1;
-  } *ev = new EventFunctionImpl1(f, a1);
-  return ev;
+    virtual void Notify (void) { 
+      (*m_function) (m_a1);
+    }
+    F m_function;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+  } *ev = new EventFunctionImpl1 (f, a1);
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T1, typename T2>
-EventImpl *Simulator::MakeEvent (void (*f) (T1,T2), T1 a1, T2 a2) 
+template <typename U1, typename U2, typename T1, typename T2>
+Ptr<EventImpl> Simulator::MakeEvent (void (*f) (U1,U2), T1 a1, T2 a2) 
 {
   // two arg version
   class EventFunctionImpl2 : public EventImpl {
   public:
-  	typedef void (*F)(T1, T2);
+    typedef void (*F)(U1, U2);
       
-  	EventFunctionImpl2 (F function, T1 a1, T2 a2) 
-  		: m_function (function),
-  		  m_a1 (a1),
-  		  m_a2 (a2)
-  	{ }
+    EventFunctionImpl2 (F function, T1 a1, T2 a2) 
+      : m_function (function),
+        m_a1 (a1),
+        m_a2 (a2)
+    {}
   protected:
-  	virtual ~EventFunctionImpl2 () {}
+    virtual ~EventFunctionImpl2 () {}
   private:
-  	virtual void Notify (void) { 
-  		(*m_function) (m_a1, m_a2);
-  	}
-  	F m_function;
-  	T1 m_a1;
-  	T2 m_a2;
+    virtual void Notify (void) { 
+      (*m_function) (m_a1, m_a2);
+    }
+    F m_function;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
   } *ev = new EventFunctionImpl2 (f, a1, a2);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T1, typename T2, typename T3>
-EventImpl *Simulator::MakeEvent (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3)
+template <typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+Ptr<EventImpl> Simulator::MakeEvent (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3)
 {
   // three arg version
   class EventFunctionImpl3 : public EventImpl {
   public:
-  	typedef void (*F)(T1, T2, T3);
+    typedef void (*F)(U1, U2, U3);
       
-  	EventFunctionImpl3 (F function, T1 a1, T2 a2, T3 a3) 
-  		: m_function (function),
-  		  m_a1 (a1),
-  		  m_a2 (a2),
-  		  m_a3 (a3)
-  	{ }
+    EventFunctionImpl3 (F function, T1 a1, T2 a2, T3 a3) 
+      : m_function (function),
+        m_a1 (a1),
+        m_a2 (a2),
+        m_a3 (a3)
+    { }
   protected:
-  	virtual ~EventFunctionImpl3 () {}
+    virtual ~EventFunctionImpl3 () {}
   private:
-  	virtual void Notify (void) { 
-  		(*m_function) (m_a1, m_a2, m_a3);
-  	}
-  	F m_function;
-  	T1 m_a1;
-  	T2 m_a2;
-  	T3 m_a3;
+    virtual void Notify (void) { 
+      (*m_function) (m_a1, m_a2, m_a3);
+    }
+    F m_function;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
   } *ev = new EventFunctionImpl3 (f, a1, a2, a3);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T1, typename T2, typename T3, typename T4>
-EventImpl *Simulator::MakeEvent (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+Ptr<EventImpl> Simulator::MakeEvent (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4) 
 {
   // four arg version
   class EventFunctionImpl4 : public EventImpl {
   public:
-  	typedef void (*F)(T1, T2, T3, T4);
+    typedef void (*F)(U1, U2, U3, U4);
       
-  	EventFunctionImpl4 (F function, T1 a1, T2 a2, T3 a3, T4 a4) 
-  		: m_function (function),
-  		  m_a1 (a1),
-  		  m_a2 (a2),
-  		  m_a3 (a3),
-  		  m_a4 (a4)
-  	{ }
+    EventFunctionImpl4 (F function, T1 a1, T2 a2, T3 a3, T4 a4) 
+      : m_function (function),
+        m_a1 (a1),
+        m_a2 (a2),
+        m_a3 (a3),
+        m_a4 (a4)
+    { }
   protected:
-  	virtual ~EventFunctionImpl4 () {}
+    virtual ~EventFunctionImpl4 () {}
   private:
-  	virtual void Notify (void) { 
-  		(*m_function) (m_a1, m_a2, m_a3, m_a4);
-  	}
-  	F m_function;
-  	T1 m_a1;
-  	T2 m_a2;
-  	T3 m_a3;
-  	T4 m_a4;
+    virtual void Notify (void) { 
+      (*m_function) (m_a1, m_a2, m_a3, m_a4);
+    }
+    F m_function;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
+    typename TypeTraits<T4>::ReferencedType m_a4;
   } *ev = new EventFunctionImpl4 (f, a1, a2, a3, a4);
-  return ev;
+  return Ptr<EventImpl> (ev, false);
 }
 
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-EventImpl *Simulator::MakeEvent (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+template <typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+Ptr<EventImpl> Simulator::MakeEvent (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
   // five arg version
   class EventFunctionImpl5 : public EventImpl {
   public:
-  	typedef void (*F)(T1, T2, T3, T4, T5);
+    typedef void (*F)(U1,U2,U3,U4,U5);
       
-  	EventFunctionImpl5 (F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
-  		: m_function (function),
-  		  m_a1 (a1),
-  		  m_a2 (a2),
-  		  m_a3 (a3),
-  		  m_a4 (a4),
-  		  m_a5 (a5)
-  	{ }
+    EventFunctionImpl5 (F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+      : m_function (function),
+        m_a1 (a1),
+        m_a2 (a2),
+        m_a3 (a3),
+        m_a4 (a4),
+        m_a5 (a5)
+    {}
   protected:
-  	virtual ~EventFunctionImpl5 () {}
+    virtual ~EventFunctionImpl5 () {}
   private:
-  	virtual void Notify (void) { 
-  		(*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
-  	}
-  	F m_function;
-  	T1 m_a1;
-  	T2 m_a2;
-  	T3 m_a3;
-  	T4 m_a4;
-  	T5 m_a5;
+    virtual void Notify (void) { 
+      (*m_function) (m_a1, m_a2, m_a3, m_a4, m_a5);
+    }
+    F m_function;
+    typename TypeTraits<T1>::ReferencedType m_a1;
+    typename TypeTraits<T2>::ReferencedType m_a2;
+    typename TypeTraits<T3>::ReferencedType m_a3;
+    typename TypeTraits<T4>::ReferencedType m_a4;
+    typename TypeTraits<T5>::ReferencedType m_a5;
   } *ev = new EventFunctionImpl5 (f, a1, a2, a3, a4, a5);
-  return ev; 
+  return Ptr<EventImpl> (ev, false);
 }
 
 template <typename T, typename OBJ>
@@ -914,63 +982,77 @@
 }
 
 
-template <typename T, typename OBJ, typename T1>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1), OBJ obj, T1 a1) 
+template <typename T, typename OBJ,
+          typename U1,
+          typename T1>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1), OBJ obj, T1 a1) 
 {
   return Schedule (time, MakeEvent (mem_ptr, obj, a1));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2,
+          typename T1, typename T2>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2)
 {
   return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3) 
+template <typename T, typename OBJ,
+          typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) 
 {
   return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
 {
   return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId Simulator::Schedule (Time const &time, void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
   						 T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
   return Schedule (time, MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
 }
 
-template <typename T1>
-EventId Simulator::Schedule (Time const &time, void (*f) (T1), T1 a1) 
+template <typename U1, typename T1>
+EventId Simulator::Schedule (Time const &time, void (*f) (U1), T1 a1) 
 {
   return Schedule (time, MakeEvent (f, a1));
 }
 
-template <typename T1, typename T2>
-EventId Simulator::Schedule (Time const &time, void (*f) (T1,T2), T1 a1, T2 a2) 
+template <typename U1, typename U2, 
+          typename T1, typename T2>
+EventId Simulator::Schedule (Time const &time, void (*f) (U1,U2), T1 a1, T2 a2) 
 {
   return Schedule (time, MakeEvent (f, a1, a2));
 }
 
-template <typename T1, typename T2, typename T3>
-EventId Simulator::Schedule (Time const &time, void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3)
+template <typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId Simulator::Schedule (Time const &time, void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3)
 {
   return Schedule (time, MakeEvent (f, a1, a2, a3));
 }
 
-template <typename T1, typename T2, typename T3, typename T4>
-EventId Simulator::Schedule (Time const &time, void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId Simulator::Schedule (Time const &time, void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4) 
 {
   return Schedule (time, MakeEvent (f, a1, a2, a3, a4));
 }
 
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-EventId Simulator::Schedule (Time const &time, void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+template <typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId Simulator::Schedule (Time const &time, void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
   return Schedule (time, MakeEvent (f, a1, a2, a3, a4, a5));
 }
@@ -979,163 +1061,193 @@
 
 
 template <typename T, typename OBJ>
-void
+EventId
 Simulator::ScheduleNow (void (T::*mem_ptr) (void), OBJ obj) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj));
+  return ScheduleNow (MakeEvent (mem_ptr, obj));
 }
 
 
-template <typename T, typename OBJ, typename T1>
-void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1), OBJ obj, T1 a1) 
+template <typename T, typename OBJ, 
+          typename U1,
+          typename T1>
+EventId
+Simulator::ScheduleNow (void (T::*mem_ptr) (U1), OBJ obj, T1 a1) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj, a1));
+  return ScheduleNow (MakeEvent (mem_ptr, obj, a1));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2>
-void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2,
+          typename T1, typename T2>
+EventId
+Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2));
+  return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId
+Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3));
+  return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId
+Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
+  return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-void
-Simulator::ScheduleNow (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId
+Simulator::ScheduleNow (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                         T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
-  ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
+  return ScheduleNow (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
 }
 
-template <typename T1>
-void
-Simulator::ScheduleNow (void (*f) (T1), T1 a1) 
+template <typename U1,
+          typename T1>
+EventId
+Simulator::ScheduleNow (void (*f) (U1), T1 a1) 
 {
-  ScheduleNow (MakeEvent (f, a1));
+  return ScheduleNow (MakeEvent (f, a1));
 }
 
-template <typename T1, typename T2>
-void
-Simulator::ScheduleNow (void (*f) (T1,T2), T1 a1, T2 a2) 
+template <typename U1, typename U2,
+          typename T1, typename T2>
+EventId
+Simulator::ScheduleNow (void (*f) (U1,U2), T1 a1, T2 a2) 
 {
-  ScheduleNow (MakeEvent (f, a1, a2));
+  return ScheduleNow (MakeEvent (f, a1, a2));
 }
 
-template <typename T1, typename T2, typename T3>
-void
-Simulator::ScheduleNow (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3)
+template <typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId
+Simulator::ScheduleNow (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3)
 {
-  ScheduleNow (MakeEvent (f, a1, a2, a3));
+  return ScheduleNow (MakeEvent (f, a1, a2, a3));
 }
 
-template <typename T1, typename T2, typename T3, typename T4>
-void
-Simulator::ScheduleNow (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId
+Simulator::ScheduleNow (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4) 
 {
-  ScheduleNow (MakeEvent (f, a1, a2, a3, a4));
+  return ScheduleNow (MakeEvent (f, a1, a2, a3, a4));
 }
 
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-void
-Simulator::ScheduleNow (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+template <typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId
+Simulator::ScheduleNow (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
-  ScheduleNow (MakeEvent (f, a1, a2, a3, a4, a5));
+  return ScheduleNow (MakeEvent (f, a1, a2, a3, a4, a5));
 }
 
 
 
 template <typename T, typename OBJ>
-void
+EventId
 Simulator::ScheduleDestroy (void (T::*mem_ptr) (void), OBJ obj) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj));
 }
 
 
-template <typename T, typename OBJ, typename T1>
-void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1), OBJ obj, T1 a1) 
+template <typename T, typename OBJ, 
+          typename U1,
+          typename T1>
+EventId
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1), OBJ obj, T1 a1) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj, a1));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2>
-void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2), OBJ obj, T1 a1, T2 a2) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2,
+          typename T1, typename T2>
+EventId
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2), OBJ obj, T1 a1, T2 a2) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3>
-void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3), OBJ obj, T1 a1, T2 a2, T3 a3) 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3), OBJ obj, T1 a1, T2 a2, T3 a3) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4>
-void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename T, typename OBJ,
+          typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4), OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4));
 }
 
-template <typename T, typename OBJ, typename T1, typename T2, typename T3, typename T4, typename T5>
-void
-Simulator::ScheduleDestroy (void (T::*mem_ptr) (T1,T2,T3,T4,T5), OBJ obj, 
+template <typename T, typename OBJ, 
+          typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId
+Simulator::ScheduleDestroy (void (T::*mem_ptr) (U1,U2,U3,U4,U5), OBJ obj, 
                             T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
-  ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
+  return ScheduleDestroy (MakeEvent (mem_ptr, obj, a1, a2, a3, a4, a5));
 }
 
-template <typename T1>
-void
-Simulator::ScheduleDestroy (void (*f) (T1), T1 a1) 
+template <typename U1,
+          typename T1>
+EventId
+Simulator::ScheduleDestroy (void (*f) (U1), T1 a1) 
 {
-  ScheduleDestroy (MakeEvent (f, a1));
+  return ScheduleDestroy (MakeEvent (f, a1));
 }
 
-template <typename T1, typename T2>
-void
-Simulator::ScheduleDestroy (void (*f) (T1,T2), T1 a1, T2 a2) 
+template <typename U1, typename U2,
+          typename T1, typename T2>
+EventId
+Simulator::ScheduleDestroy (void (*f) (U1,U2), T1 a1, T2 a2) 
 {
-  ScheduleDestroy (MakeEvent (f, a1, a2));
+  return ScheduleDestroy (MakeEvent (f, a1, a2));
 }
 
-template <typename T1, typename T2, typename T3>
-void
-Simulator::ScheduleDestroy (void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3)
+template <typename U1, typename U2, typename U3,
+          typename T1, typename T2, typename T3>
+EventId
+Simulator::ScheduleDestroy (void (*f) (U1,U2,U3), T1 a1, T2 a2, T3 a3)
 {
-  ScheduleDestroy (MakeEvent (f, a1, a2, a3));
+  return ScheduleDestroy (MakeEvent (f, a1, a2, a3));
 }
 
-template <typename T1, typename T2, typename T3, typename T4>
-void
-Simulator::ScheduleDestroy (void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4) 
+template <typename U1, typename U2, typename U3, typename U4,
+          typename T1, typename T2, typename T3, typename T4>
+EventId
+Simulator::ScheduleDestroy (void (*f) (U1,U2,U3,U4), T1 a1, T2 a2, T3 a3, T4 a4) 
 {
-  ScheduleDestroy (MakeEvent (f, a1, a2, a3, a4));
+  return ScheduleDestroy (MakeEvent (f, a1, a2, a3, a4));
 }
 
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-void
-Simulator::ScheduleDestroy (void (*f) (T1,T2,T3,T4,T5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
+template <typename U1, typename U2, typename U3, typename U4, typename U5,
+          typename T1, typename T2, typename T3, typename T4, typename T5>
+EventId
+Simulator::ScheduleDestroy (void (*f) (U1,U2,U3,U4,U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) 
 {
-  ScheduleDestroy (MakeEvent (f, a1, a2, a3, a4, a5));
+  return ScheduleDestroy (MakeEvent (f, a1, a2, a3, a4, a5));
 }
 
 }; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/time-default-value.cc	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,106 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 "time-default-value.h"
+
+namespace ns3 {
+
+TimeDefaultValue::TimeDefaultValue (const std::string name,
+				    const std::string help,
+				    Time defaultValue)
+  : DefaultValueBase (name, help),
+    m_defaultValue (defaultValue),
+    m_value (defaultValue)
+{
+  DefaultValueList::Add (this);
+}
+Time 
+TimeDefaultValue::GetValue (void) const
+{
+  return m_value;
+}
+bool 
+TimeDefaultValue::DoParseValue (const std::string &value)
+{
+  std::string::size_type n = value.find_first_not_of("0123456789.");
+  if (n == std::string::npos)
+    {
+      return false;
+    }
+  std::string trailer = value.substr(n, std::string::npos);
+  std::istringstream iss;
+  iss.str (value.substr(0, n));
+
+  if (trailer == std::string("s"))
+    {
+      double v;
+      iss >> v;
+      m_value = Seconds (v);
+      return !iss.bad () && !iss.fail ();
+    }
+  uint64_t integer;
+  iss >> integer;
+  if (iss.bad () || iss.fail ())
+    {
+      return false;
+    }
+  if (trailer == std::string("ms"))
+    {
+      m_value = MilliSeconds (integer);
+      return true;
+    }
+  if (trailer == std::string("us"))
+    {
+      m_value = MicroSeconds (integer);
+      return true;
+    }
+  if (trailer == std::string("ns"))
+    {
+      m_value = NanoSeconds (integer);
+      return true;
+    }
+  if (trailer == std::string("ps"))
+    {
+      m_value = PicoSeconds (integer);
+      return true;
+    }
+  if (trailer == std::string("fs"))
+    {
+      m_value = FemtoSeconds (integer);
+      return true;
+    }
+  return false;
+}
+std::string 
+TimeDefaultValue::DoGetType (void) const
+{
+  return "(s|ms|us|ns|ps|fs)";
+}
+std::string 
+TimeDefaultValue::DoGetDefaultValue (void) const
+{
+  std::ostringstream oss;
+  oss << m_value.GetSeconds () << "s";
+  return oss.str ();
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/time-default-value.h	Fri Aug 03 08:29:24 2007 -0700
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 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 TIME_DEFAULT_VALUE_H
+#define TIME_DEFAULT_VALUE_H
+
+#include "ns3/default-value.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup config
+ * \brief a ns3::Time variable for ns3::Bind
+ *
+ * Every instance of this type is automatically 
+ * registered in the variable pool which is used
+ * by ns3::Bind. 
+ */
+class TimeDefaultValue : public DefaultValueBase
+{
+public:
+  /**
+   * \param name name of variable
+   * \param help help text which explains the purpose
+   *        and the semantics of this variable
+   * \param defaultValue the default value to assign
+   *        to this variable.
+   *
+   * Unless the user invokes ns3::Bind with the right arguments,
+   * the GetValue method will return the default value. Otherwise,
+   * it will return the user-specified value.
+   */
+  TimeDefaultValue (const std::string name,
+		    const std::string help,
+		    Time defaultValue);
+  /**
+   * \returns the default value for this variable or a
+   *          user-provided overriden variable.
+   */
+  Time GetValue (void) const;
+private:
+  virtual bool DoParseValue (const std::string &value);
+  virtual std::string DoGetType (void) const;
+  virtual std::string DoGetDefaultValue (void) const;
+
+  Time m_defaultValue;
+  Time m_value;
+};
+
+} // namespace ns3
+
+#endif /* TIME_DEFAULT_VALUE_H */
--- a/src/simulator/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/simulator/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -15,8 +15,6 @@
 
 
 def configure(conf):
-    conf.env.append_value('NS3_MODULES', 'ns3-simulator')
-
     if Params.g_options.high_precision_as_double:
         conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1)
         conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1
@@ -65,7 +63,9 @@
         'scheduler-map.cc',
         'event-impl.cc',
         'simulator.cc',
+        'time-default-value.cc',
         ]
+
     headers = bld.create_obj('ns3header')
     headers.source = [
         'high-precision.h',
@@ -76,6 +76,7 @@
         'scheduler.h',
         'scheduler-factory.h',
         'simulation-singleton.h',
+        'time-default-value.h',
         ]
 
     env = bld.env_of_name('default')
--- a/src/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/src/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -9,37 +9,51 @@
 import Params
 
 
-all_modules = [
+all_modules = (
     'core',
     'common',
     'simulator',
     'node',
     'internet-node',
-    'devices/p2p',
+    'devices/point-to-point',
+    'devices/csma-cd',
     'applications',
     'routing/global',
-    ]
-
+    'mobility',
+    )
 
 def set_options(opt):
     opt.sub_options('simulator')
-    
+
+    opt.add_option('--enable-rpath',
+                   help=("Link programs with rpath"
+                         " (normally not needed, see "
+                         " --run and --shell; moreover, only works in some"
+                         " specific platforms, such as Linux and Solaris)"),
+                   action="store_true", dest='enable_rpath', default=False)
+
+
 def configure(conf):
     conf.sub_config('core')
     conf.sub_config('simulator')
 
     blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
     for module in all_modules:
-        conf.sub_config(module)
-        conf.env.append_value('NS3_MODULE_PATH', os.path.join(blddir, 'src', module))
+        module_path = os.path.join(blddir, 'src', module)
+        conf.env.append_value('NS3_MODULE_PATH', module_path)
+        if Params.g_options.enable_rpath:
+            conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (module_path,))
+
+    ## Used to link the 'run-tests' program with all of ns-3 code
+    conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
+
 
 
 def build(bld):
     Object.register('ns3header', Ns3Header)
-    Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE')
+    Action.Action('ns3header', func=_ns3_headers_inst, color='BLUE')
     
-    bld.add_subdirs(all_modules)
-
+    bld.add_subdirs(list(all_modules))
 
 class Ns3Header(Object.genobj):
     """A set of NS-3 header files"""
@@ -53,19 +67,15 @@
 
     def apply(self):
         ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
-        inputs = []
-        outputs = []
         for filename in self.to_list(self.source):
             src_node = self.path.find_source(filename)
             if src_node is None:
                 Params.fatal("source ns3 header file %s not found" % (filename,))
             dst_node = ns3_dir_node.find_build(os.path.basename(filename))
             assert dst_node is not None
-            inputs.append(src_node)
-            outputs.append(dst_node)
-        task = self.create_task('ns3_headers', self.env, 1)
-        task.set_inputs(inputs)
-        task.set_outputs(outputs)
+            task = self.create_task('ns3header', self.env, 1)
+            task.set_inputs([src_node])
+            task.set_outputs([dst_node])
 
     def install(self):
         for i in self.m_tasks:
--- a/wscript	Fri Aug 03 08:23:23 2007 -0700
+++ b/wscript	Fri Aug 03 08:29:24 2007 -0700
@@ -1,5 +1,4 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-import os
 import sys
 import shlex
 import shutil
@@ -8,6 +7,7 @@
 import Object
 import pproc as subprocess
 import optparse
+import os.path
 
 Params.g_autoconfig = 1
 
@@ -20,8 +20,8 @@
 blddir = 'build'
 
 def dist_hook(srcdir, blddir):
-    shutil.rmtree("doc/html")
-    shutil.rmtree("doc/latex")
+    shutil.rmtree("doc/html", True)
+    shutil.rmtree("doc/latex", True)
 
 def set_options(opt):
 
@@ -65,8 +65,14 @@
                    dest='doxygen')
 
     opt.add_option('--run',
-                   help=('Run a locally built program'),
+                   help=('Run a locally built program; argument can be a program name,'
+                         ' or a command starting with the program name.'),
                    type="string", default='', dest='run')
+    opt.add_option('--command-template',
+                   help=('Template of the command used to run the program given by --run;'
+                         ' It should be a shell command string containing %s inside,'
+                         ' which will be replaced by the actual program.'),
+                   type="string", default=None, dest='command_template')
 
     opt.add_option('--shell',
                    help=('Run a shell with an environment suitably modified to run locally built programs'),
@@ -105,13 +111,23 @@
 
     variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
     
-    if os.path.basename(conf.env['CXX']).startswith("g++"):
+    if (os.path.basename(conf.env['CXX']).startswith("g++")
+        and 'CXXFLAGS' not in os.environ):
         variant_env.append_value('CXXFLAGS', ['-Wall', '-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')
 
+    ## In optimized builds we still want debugging symbols, e.g. for
+    ## profiling, and at least partially usable stack traces.
+    if ('optimized' in Params.g_options.debug_level.lower() 
+        and 'CXXFLAGS' not in os.environ):
+        for flag in variant_env['CXXFLAGS_DEBUG']:
+            ## this probably doesn't work for MSVC
+            if flag.startswith('-g'):
+                variant_env.append_value('CXXFLAGS', flag)
+
     if sys.platform == 'win32':
         if os.path.basename(conf.env['CXX']).startswith("g++"):
             variant_env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
@@ -126,7 +142,9 @@
 
     if Params.g_options.shell:
         run_shell()
-        return
+        raise SystemExit(0)
+
+    check_shell()
 
     # process subfolders from here
     bld.add_subdirs('src')
@@ -152,68 +170,126 @@
         doxygen()
 
     if Params.g_options.run:
-        run_program(Params.g_options.run)
+        run_program(Params.g_options.run, Params.g_options.command_template)
+        raise SystemExit(0)
 
-def _find_program(program_name):
+    if Params.g_options.command_template:
+        Params.fatal("Option --command-template requires the option --run to be given")
+
+def _find_program(program_name, env):
+    launch_dir = os.path.abspath(Params.g_cwd_launch)
     found_programs = []
     for obj in Object.g_allobjs:
         if obj.m_type != 'program' or not obj.target:
             continue
+
+        ## filter out programs not in the subtree starting at the launch dir
+        if not (obj.path.abspath().startswith(launch_dir)
+                or obj.path.abspath(env).startswith(launch_dir)):
+            continue
+        
         found_programs.append(obj.target)
         if obj.target == program_name:
             return obj
     raise ValueError("program '%s' not found; available programs are: %r"
                      % (program_name, found_programs))
 
-def _run_argv(argv):
+def _run_argv(argv, os_env=None):
     env = Params.g_build.env_of_name('default')
     if sys.platform == 'linux2':
         pathvar = 'LD_LIBRARY_PATH'
-        pathsep = ':'
     elif sys.platform == 'darwin':
         pathvar = 'DYLD_LIBRARY_PATH'
-        pathsep = ':'
     elif sys.platform == 'win32':
         pathvar = 'PATH'
-        pathsep = ';'
     elif sys.platform == 'cygwin':
         pathvar = 'PATH'
-        pathsep = ':'
     else:
         Params.warning(("Don't know how to configure "
                         "dynamic library path for the platform '%s'") % (sys.platform,))
         pathvar = None
-        pathsep = None
 
-    os_env = dict(os.environ)
+    proc_env = dict(os.environ)
+    if os_env is not None:
+        proc_env.update(os_env)
+
     if pathvar is not None:
-        if pathvar in os_env:
-            os_env[pathvar] = pathsep.join([os_env[pathvar]] + list(env['NS3_MODULE_PATH']))
+        if pathvar in proc_env:
+            proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']) + [proc_env[pathvar]])
         else:
-            os_env[pathvar] = pathsep.join(list(env['NS3_MODULE_PATH']))
+            proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']))
 
-    retval = subprocess.Popen(argv, env=os_env).wait()
+    retval = subprocess.Popen(argv, env=proc_env).wait()
     if retval:
-        raise SystemExit(retval)
+        Params.fatal("Command %s exited with code %i" % (argv, retval))
 
 
-def run_program(program_string):
+def run_program(program_string, command_template=None):
+    """
+    if command_template is not None, then program_string == program
+    name and argv is given by command_template with %s replaced by the
+    full path to the program.  Else, program_string is interpreted as
+    a shell command with first name being the program name.
+    """
     env = Params.g_build.env_of_name('default')
-    argv = shlex.split(program_string)
-    program_name = argv[0]
+
+    if command_template is None:
+        argv = shlex.split(program_string)
+        program_name = argv[0]
+
+        try:
+            program_obj = _find_program(program_name, env)
+        except ValueError, ex:
+            Params.fatal(str(ex))
+
+        try:
+            program_node, = program_obj.m_linktask.m_outputs
+        except AttributeError:
+            Params.fatal("%s does not appear to be a program" % (program_name,))
+
+        execvec = [program_node.abspath(env)] + argv[1:]
 
+    else:
+
+        program_name = program_string
+        try:
+            program_obj = _find_program(program_name, env)
+        except ValueError, ex:
+            Params.fatal(str(ex))
+        try:
+            program_node, = program_obj.m_linktask.m_outputs
+        except AttributeError:
+            Params.fatal("%s does not appear to be a program" % (program_name,))
+
+        execvec = shlex.split(command_template % (program_node.abspath(env),))
+
+
+    former_cwd = os.getcwd()
+    os.chdir(Params.g_cwd_launch)
     try:
-        program_obj = _find_program(program_name)
-    except ValueError, ex:
-        Params.fatal(str(ex))
+        retval = _run_argv(execvec)
+    finally:
+        os.chdir(former_cwd)
+
+    return retval
 
-    try:
-        program_node, = program_obj.m_linktask.m_outputs
-    except AttributeError:
-        Params.fatal("%s does not appear to be a program" % (program_name,))
-
-    execvec = [program_node.abspath(env)] + argv[1:]
-    return _run_argv(execvec)
+def check_shell():
+    if 'NS3_MODULE_PATH' not in os.environ:
+        return
+    env = Params.g_build.env_of_name('default')
+    correct_modpath = os.pathsep.join(env['NS3_MODULE_PATH'])
+    found_modpath = os.environ['NS3_MODULE_PATH']
+    if found_modpath != correct_modpath:
+        msg = ("Detected shell (waf --shell) with incorrect configuration\n"
+               "=========================================================\n"
+               "Possible reasons for this problem:\n"
+               "  1. You switched to another ns-3 tree from inside this shell\n"
+               "  2. You switched ns-3 debug level (waf configure --debug)\n"
+               "  3. You modified the list of built ns-3 modules\n"
+               "You should correct this situation before running any program.  Possible solutions:\n"
+               "  1. Exit this shell, and start a new one\n"
+               "  2. Run a new nested shell")
+        Params.fatal(msg)
 
 
 def run_shell():
@@ -221,7 +297,9 @@
         shell = os.environ.get("COMSPEC", "cmd.exe")
     else:
         shell = os.environ.get("SHELL", "/bin/sh")
-    _run_argv([shell])
+
+    env = Params.g_build.env_of_name('default')
+    _run_argv([shell], {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
 
 
 def doxygen():