merge
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Fri, 17 Apr 2009 17:45:16 +0200
changeset 4361 5e4790eea56f
parent 4360 bf9c03ebc855 (current diff)
parent 4356 08cfbddc55f9 (diff)
child 4365 f71fd5bfc4ad
merge
bindings/python/ns3_module_node.py
--- a/.hgtags	Mon Mar 23 13:16:09 2009 +0100
+++ b/.hgtags	Fri Apr 17 17:45:16 2009 +0200
@@ -31,3 +31,4 @@
 58ae52c5845ff03ba08dc921e13e6cf3604c810a ns-3.3-RC5
 4267fd454004f5a60e517496f43a01000ccebc72 ns-3.3-RC6
 2efae18e73794c0acd8061a9bd5c74b69f1b0d93 ns-3.3
+5396ecd09060bcb1e7b1f750bb170cbfde7a77c2 ns-3.4
--- a/AUTHORS	Mon Mar 23 13:16:09 2009 +0100
+++ b/AUTHORS	Fri Apr 17 17:45:16 2009 +0200
@@ -14,4 +14,14 @@
 Mehdi Benamor (mehdi.benamor@telecom-bretagne.eu)
 Angelos Chatzipapas (chatzipa@ceid.upatras.gr)
 Luis Cortes (cortes@gatech.edu)
+Kulin Shah (m.kulin@gmail.com)
+Sam Jansen (sam.jansen@gmail.com)
+Timo Bingmann (timo.bingmann@student.kit.edu)
+Kirill V. Andreev (kirillano@yandex.ru)
+Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu)
+Mauro Tortonesi (mauro.tortonesi@unife.it)
+Aleksey Kovalenko (kovalenko@iitp.ru)
+Liu Jian (liujatp@gmail.com)
+Andrey Hippo (ahippo@yandex.ru)
+Francesco Malandrino (francesco.malandrino@gmail.com)
 
--- a/CHANGES.html	Mon Mar 23 13:16:09 2009 +0100
+++ b/CHANGES.html	Fri Apr 17 17:45:16 2009 +0200
@@ -44,53 +44,100 @@
 us a note on ns-developers mailing list.  </p>
 
 <hr>
-<h1>changes from ns-3.3 to ns-3.4</h1>
+<h1>Changes from ns-3.3 to ns-3.4</h1>
 
-<h2>new API:</h2>
+<h2>Changes to build system</h2>
 <ul>
-<li>ConstantAccelerationMobilityModel in src/mobility/constant-acceleration-mobility-model.h</li>
+<li>A major option regarding the downloading and building of ns-3 has been
+added for ns-3.4 -- the ns-3-allinone feature.  This allows a user to
+get the most common options for ns-3 downloaded and built with a minimum
+amount of trouble.  See the ns-3 tutorial for a detailed explanation of
+how to use this new feature.</li>
+
+<li>The build system now runs build items in parallel by default.  This includes
+the regression tests.</li>
 </ul>
 
+<h2>New API:</h2>
 <ul>
-<li>A new emulation mode is supported with the TapBridge net device (see</li>
-<li>src/devices/tap-bridge)</li>
-</ul>
+<li>XML support has been added to the ConfigStore in /src/contrib/config-store.cc</li>
+
+<li>The ns-2 calendar queue scheduler option has been ported to src/simulator</li>
+
+<li>A ThreeLogDistancePropagationLossModel has been added to src/devices/wifi</li>
+
+<li>ConstantAccelerationMobilityModel in src/mobility/constant-acceleration-mobility-model.h</li>
 
-<ul>
-<li>A new facility for naming ns-3 Objects is included (see</li>
-<li>src/core/names.{cc,h})</li>
+<li>A new emulation mode is supported with the TapBridge net device (see
+src/devices/tap-bridge)</li>
+
+<li>A new facility for naming ns-3 Objects is included (see
+src/core/names.{cc,h})</li>
+
+<li>Wifi multicast support has been added in src/devices/wifi</li>
 </ul>
 
-<h2>changes to existing API:</h2>
+<h2>Changes to existing API:</h2>
 
 <ul>
-<li>The trace sources in the various NetDevice classes has been completely</li>
-<li>reworked to allow for a consistent set of trace sources across the</li>
-<li>devices.  The names of the trace sources have been changed to provide</li>
-<li>some context with respect to the level at which the trace occurred.</li>
-<li>A new set of trace sources has been added which emulates the behavior</li>
-<li>of packet sniffers.  These sources have been used to implement tcpdump-</li>
-<li>like functionality and are plumbed up into the helper classes.  The </li>
-<li>user-visible changes are the trace source name changes and the ability </li>
-<li>to do promiscuous-mode pcap tracing via helpers.  For further information</li>
-<li>regarding these changes, please see the ns-3 manual</li>
+<li>Some fairly significant changes have been made to the API of the
+random variable code.  Please see the ns-3 manual and src/core/random-variable.cc
+for details.</li>
+
+<li>The trace sources in the various NetDevice classes has been completely
+reworked to allow for a consistent set of trace sources across the
+devices.  The names of the trace sources have been changed to provide
+some context with respect to the level at which the trace occurred.
+A new set of trace sources has been added which emulates the behavior
+of packet sniffers.  These sources have been used to implement tcpdump-
+like functionality and are plumbed up into the helper classes.  The 
+user-visible changes are the trace source name changes and the ability
+to do promiscuous-mode pcap tracing via helpers.  For further information
+regarding these changes, please see the ns-3 manual</li>
+
+<li>StaticMobilityModel has been renamed ConstantPositionMobilityModel
+StaticSpeedMobilityModel has been renamed ConstantVelocityMobilityModel</li>
+
+<li>The Callback templates have been extended to support more parameters.
+See src/core/callback.h</li>
+
+<li>Many helper API have been changed to allow passing Object-based parameters
+as string names to ease working with the object name service.</li>
+
+<li>The Config APIs now accept path segments that are names defined by the
+object name service.</li>
+
+<li>Minor changes were made to make the system build under the Intel C++ compiler.</li>
+
+<li>Trace hooks for association and deassociation to/from an access point were
+added to src/devices/wifi/nqsta-wifi-mac.cc</li>
 </ul>
 
+<h2>Changed behavior:</h2>
+
 <ul>
-<li>StaticMobilityModel has been renamed ConstantPositionMobilityModel</li>
-<li>StaticSpeedMobilityModel has been renamed ConstantVelocityMobilityModel</li>
+<li>The tracing system rework has introduced some significant changes in the
+behavior of some trace sources, specifically in the positioning of trace sources
+in the device code.  For example, there were cases where the packet transmit 
+trace source was hit before the packet was enqueued on the device transmit quueue.
+This now happens just before the packet is transmitted over the channel medium.
+The scope of the changes is too large to be included here.  If you have concerns
+regarding trace semantics, please consult the net device documentation for details.
+As is usual, the ultimate source for documentation is the net device source code.</li>
 </ul>
 
 <hr>
-<h1>changes from ns-3.2 to ns-3.3</h1>
+<h1>Changes from ns-3.2 to ns-3.3</h1>
 
-<h2>new API:</h2>
+<h2>New API:</h2>
 <ul>
-<li> ns-3 ABORT macros in src/core/abort.h</li>
-<li> Config::MatchContainer </li>
-<li> ConstCast and DynamicCast helper functions for Ptr casting</li>
-<li> StarTopology added to several topology helpers </li>
-<li> NetDevice::IsBridge () </li>
+<li>
+ns-3 ABORT macros in src/core/abort.h
+Config::MatchContainer
+ConstCast and DynamicCast helper functions for Ptr casting
+StarTopology added to several topology helpers
+NetDevice::IsBridge () 
+</li>
 
 <li>17-11-2008; changeset 
 <a href="http://code.nsnam.org/ns-3-dev/rev/4c1c3f6bcd03">4c1c3f6bcd03</a></li>
@@ -120,7 +167,7 @@
 </ul>
 
 </ul>
-<h2>changes to existing API:</h2>
+<h2>Changes to existing API:</h2>
 <ul>
 
 <li> NetDevice::MakeMulticastAddress() was renamed to NetDevice::GetMulticast()
@@ -187,9 +234,9 @@
 </ul>
 
 <hr>
-<h1>changes from ns-3.1 to ns-3.2</h1>
+<h1>Changes from ns-3.1 to ns-3.2</h1>
 
-<h2>new API:</h2>
+<h2>New API:</h2>
 <ul>
 
 <li>26-08-2008; changeset 
@@ -213,7 +260,7 @@
 </ul>
 
 </ul>
-<h2>new API in existing classes:</h2>
+<h2>New API in existing classes:</h2>
 <ul>
 
 <li>01-08-2008; changeset 
@@ -226,7 +273,7 @@
 </li>
 
 </ul>
-<h2>changes to existing API:</h2>
+<h2>Changes to existing API:</h2>
 <ul>
 
 <li>05-09-2008; changeset 
@@ -364,7 +411,7 @@
 </li>
 
 </ul>
-<h2>changed behavior:</h2>
+<h2>Changed behavior:</h2>
 <ul>
 
 <li>07-09-2008; changeset 
--- a/RELEASE_NOTES	Mon Mar 23 13:16:09 2009 +0100
+++ b/RELEASE_NOTES	Fri Apr 17 17:45:16 2009 +0200
@@ -8,8 +8,8 @@
 including tutorials:
 http://www.nsnam.org/tutorials.html
 
-Release 3.4 (pending)
-=====================
+Release 3.4
+===========
 
 Availability
 ------------
@@ -18,7 +18,7 @@
 
 Supported platforms
 -------------------
-ns-3.2 has been tested on the following platforms:
+ns-3.4 has been tested on the following platforms:
   - linux x86 gcc 4.2, 4.1, and, 3.4.6.
   - linux x86_64 gcc 4.3.2, 4.2.3, 4.2.1, 4.1.3, 3.4.6
   - MacOS X ppc and x86
@@ -34,6 +34,19 @@
      propagation loss model based on the ns-2 models. Fabian Mauchle contributed
      multicast support.
 
+  b) Object Name Service:  A facility allowing ns-3 Objects to be assigned
+     names has been added.
+
+  c) Tap Bridge:  A second option for integrating ns-3 with real-world hosts
+     has been added.  This allows for real hosts to talk over ns-3 net devices
+     and simulated networks.
+
+  d) A new build option (ns-3-allinone) has been provided to make it easier for
+     users to download and bulid commonly used ns-3 configurations.
+
+  e) The ns-3 calendar queue scheduler has been ported to ns-3.
+
+  f) XML support has been added to the ConfigStore.
 
 API changes from ns-3.3
 -----------------------
@@ -56,7 +69,8 @@
 Our next release, which is expected to happen in 2 to 4 months from now, will
 feature the merging of some of our projects currently in development including
 fuller IPv6 support, and IPv4 and routing protocol refactoring, and some smaller
-features such as an object naming facility and a new Global ARP package.
+features such as a new Global ARP package and possibly a new Testing and Validation
+suite,
 
 Release 3.3
 ===========
@@ -68,7 +82,7 @@
 
 Supported platforms
 -------------------
-ns-3.2 has been tested on the following platforms:
+ns-3.3 has been tested on the following platforms:
   - linux x86 gcc 4.2, 4.1, and, 3.4.6.
   - linux x86_64 gcc 4.3.2, 4.2.3, 4.2.1, 4.1.3, 3.4.6
   - MacOS X ppc and x86
--- a/bindings/python/ns3_module_bridge.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_bridge.py	Fri Apr 17 17:45:16 2009 +0200
@@ -103,16 +103,6 @@
                    'ns3::Ptr< ns3::NetDevice >', 
                    [param('uint32_t', 'n')], 
                    is_const=True)
-    ## bridge-net-device.h: void ns3::BridgeNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## bridge-net-device.h: std::string ns3::BridgeNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## bridge-net-device.h: void ns3::BridgeNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_core.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_core.py	Fri Apr 17 17:45:16 2009 +0200
@@ -115,8 +115,12 @@
     module.add_class('EnumChecker', parent=root_module['ns3::AttributeChecker'])
     ## enum.h: ns3::EnumValue [class]
     module.add_class('EnumValue', parent=root_module['ns3::AttributeValue'])
+    ## random-variable.h: ns3::ErlangVariable [class]
+    module.add_class('ErlangVariable', parent=root_module['ns3::RandomVariable'])
     ## random-variable.h: ns3::ExponentialVariable [class]
     module.add_class('ExponentialVariable', parent=root_module['ns3::RandomVariable'])
+    ## random-variable.h: ns3::GammaVariable [class]
+    module.add_class('GammaVariable', parent=root_module['ns3::RandomVariable'])
     ## random-variable.h: ns3::IntEmpiricalVariable [class]
     module.add_class('IntEmpiricalVariable', parent=root_module['ns3::EmpiricalVariable'])
     ## integer.h: ns3::IntegerValue [class]
@@ -261,7 +265,9 @@
     register_Ns3EmptyAttributeValue_methods(root_module, root_module['ns3::EmptyAttributeValue'])
     register_Ns3EnumChecker_methods(root_module, root_module['ns3::EnumChecker'])
     register_Ns3EnumValue_methods(root_module, root_module['ns3::EnumValue'])
+    register_Ns3ErlangVariable_methods(root_module, root_module['ns3::ErlangVariable'])
     register_Ns3ExponentialVariable_methods(root_module, root_module['ns3::ExponentialVariable'])
+    register_Ns3GammaVariable_methods(root_module, root_module['ns3::GammaVariable'])
     register_Ns3IntEmpiricalVariable_methods(root_module, root_module['ns3::IntEmpiricalVariable'])
     register_Ns3IntegerValue_methods(root_module, root_module['ns3::IntegerValue'])
     register_Ns3LogNormalVariable_methods(root_module, root_module['ns3::LogNormalVariable'])
@@ -479,34 +485,34 @@
     cls.add_constructor([param('ns3::Names const &', 'arg0')])
     ## names.h: ns3::Names::Names() [constructor]
     cls.add_constructor([])
-    ## names.h: static bool ns3::Names::Add(std::string name, ns3::Ptr<ns3::Object> obj) [member function]
+    ## names.h: static void ns3::Names::Add(std::string name, ns3::Ptr<ns3::Object> obj) [member function]
     cls.add_method('Add', 
-                   'bool', 
+                   'void', 
                    [param('std::string', 'name'), param('ns3::Ptr< ns3::Object >', 'obj')], 
                    is_static=True)
-    ## names.h: static bool ns3::Names::Add(std::string path, std::string name, ns3::Ptr<ns3::Object> object) [member function]
+    ## names.h: static void ns3::Names::Add(std::string path, std::string name, ns3::Ptr<ns3::Object> object) [member function]
     cls.add_method('Add', 
-                   'bool', 
+                   'void', 
                    [param('std::string', 'path'), param('std::string', 'name'), param('ns3::Ptr< ns3::Object >', 'object')], 
                    is_static=True)
-    ## names.h: static bool ns3::Names::Add(ns3::Ptr<ns3::Object> context, std::string name, ns3::Ptr<ns3::Object> object) [member function]
+    ## names.h: static void ns3::Names::Add(ns3::Ptr<ns3::Object> context, std::string name, ns3::Ptr<ns3::Object> object) [member function]
     cls.add_method('Add', 
-                   'bool', 
+                   'void', 
                    [param('ns3::Ptr< ns3::Object >', 'context'), param('std::string', 'name'), param('ns3::Ptr< ns3::Object >', 'object')], 
                    is_static=True)
-    ## names.h: static bool ns3::Names::Rename(std::string oldpath, std::string newname) [member function]
+    ## names.h: static void ns3::Names::Rename(std::string oldpath, std::string newname) [member function]
     cls.add_method('Rename', 
-                   'bool', 
+                   'void', 
                    [param('std::string', 'oldpath'), param('std::string', 'newname')], 
                    is_static=True)
-    ## names.h: static bool ns3::Names::Rename(std::string path, std::string oldname, std::string newname) [member function]
+    ## names.h: static void ns3::Names::Rename(std::string path, std::string oldname, std::string newname) [member function]
     cls.add_method('Rename', 
-                   'bool', 
+                   'void', 
                    [param('std::string', 'path'), param('std::string', 'oldname'), param('std::string', 'newname')], 
                    is_static=True)
-    ## names.h: static bool ns3::Names::Rename(ns3::Ptr<ns3::Object> context, std::string oldname, std::string newname) [member function]
+    ## names.h: static void ns3::Names::Rename(ns3::Ptr<ns3::Object> context, std::string oldname, std::string newname) [member function]
     cls.add_method('Rename', 
-                   'bool', 
+                   'void', 
                    [param('ns3::Ptr< ns3::Object >', 'context'), param('std::string', 'oldname'), param('std::string', 'newname')], 
                    is_static=True)
     ## names.h: static std::string ns3::Names::FindName(ns3::Ptr<ns3::Object> object) [member function]
@@ -1497,6 +1503,25 @@
                    is_virtual=True)
     return
 
+def register_Ns3ErlangVariable_methods(root_module, cls):
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable(ns3::ErlangVariable const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::ErlangVariable const &', 'arg0')])
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable() [constructor]
+    cls.add_constructor([])
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable(unsigned int k, double lambda) [constructor]
+    cls.add_constructor([param('unsigned int', 'k'), param('double', 'lambda')])
+    ## random-variable.h: double ns3::ErlangVariable::GetValue() const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [], 
+                   is_const=True)
+    ## random-variable.h: double ns3::ErlangVariable::GetValue(unsigned int k, double lambda) const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [param('unsigned int', 'k'), param('double', 'lambda')], 
+                   is_const=True)
+    return
+
 def register_Ns3ExponentialVariable_methods(root_module, cls):
     ## random-variable.h: ns3::ExponentialVariable::ExponentialVariable(ns3::ExponentialVariable const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::ExponentialVariable const &', 'arg0')])
@@ -1508,6 +1533,25 @@
     cls.add_constructor([param('double', 'm'), param('double', 'b')])
     return
 
+def register_Ns3GammaVariable_methods(root_module, cls):
+    ## random-variable.h: ns3::GammaVariable::GammaVariable(ns3::GammaVariable const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::GammaVariable const &', 'arg0')])
+    ## random-variable.h: ns3::GammaVariable::GammaVariable() [constructor]
+    cls.add_constructor([])
+    ## random-variable.h: ns3::GammaVariable::GammaVariable(double alpha, double beta) [constructor]
+    cls.add_constructor([param('double', 'alpha'), param('double', 'beta')])
+    ## random-variable.h: double ns3::GammaVariable::GetValue() const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [], 
+                   is_const=True)
+    ## random-variable.h: double ns3::GammaVariable::GetValue(double alpha, double beta) const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [param('double', 'alpha'), param('double', 'beta')], 
+                   is_const=True)
+    return
+
 def register_Ns3IntEmpiricalVariable_methods(root_module, cls):
     ## random-variable.h: ns3::IntEmpiricalVariable::IntEmpiricalVariable(ns3::IntEmpiricalVariable const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::IntEmpiricalVariable const &', 'arg0')])
@@ -1984,7 +2028,7 @@
     cls.add_method('ConnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Connect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -1992,7 +2036,7 @@
     cls.add_method('DisconnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Disconnect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -2140,7 +2184,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['long'])
+                        template_parameters=['long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
@@ -2160,7 +2204,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['unsigned long'])
+                        template_parameters=['unsigned long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
--- a/bindings/python/ns3_module_csma.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_csma.py	Fri Apr 17 17:45:16 2009 +0200
@@ -273,16 +273,6 @@
     cls.add_method('GetEncapsulationMode', 
                    'ns3::CsmaNetDevice::EncapsulationMode', 
                    [])
-    ## csma-net-device.h: void ns3::CsmaNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## csma-net-device.h: std::string ns3::CsmaNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## csma-net-device.h: void ns3::CsmaNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_emu.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_emu.py	Fri Apr 17 17:45:16 2009 +0200
@@ -80,16 +80,6 @@
     cls.add_method('SetAddress', 
                    'void', 
                    [param('ns3::Mac48Address', 'addr')])
-    ## emu-net-device.h: void ns3::EmuNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## emu-net-device.h: std::string ns3::EmuNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## emu-net-device.h: void ns3::EmuNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_helper.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_helper.py	Fri Apr 17 17:45:16 2009 +0200
@@ -946,6 +946,8 @@
 def register_Ns3TapBridgeHelper_methods(root_module, cls):
     ## tap-bridge-helper.h: ns3::TapBridgeHelper::TapBridgeHelper(ns3::TapBridgeHelper const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::TapBridgeHelper const &', 'arg0')])
+    ## tap-bridge-helper.h: ns3::TapBridgeHelper::TapBridgeHelper() [constructor]
+    cls.add_constructor([])
     ## tap-bridge-helper.h: ns3::TapBridgeHelper::TapBridgeHelper(ns3::Ipv4Address gateway) [constructor]
     cls.add_constructor([param('ns3::Ipv4Address', 'gateway')])
     ## tap-bridge-helper.h: void ns3::TapBridgeHelper::SetAttribute(std::string n1, ns3::AttributeValue const & v1) [member function]
@@ -968,6 +970,10 @@
     cls.add_method('Install', 
                    'ns3::Ptr< ns3::NetDevice >', 
                    [param('std::string', 'nodeName'), param('std::string', 'ndName')])
+    ## tap-bridge-helper.h: ns3::Ptr<ns3::NetDevice> ns3::TapBridgeHelper::Install(ns3::Ptr<ns3::Node> node, ns3::Ptr<ns3::NetDevice> nd, ns3::AttributeValue const & v1) [member function]
+    cls.add_method('Install', 
+                   'ns3::Ptr< ns3::NetDevice >', 
+                   [param('ns3::Ptr< ns3::Node >', 'node'), param('ns3::Ptr< ns3::NetDevice >', 'nd'), param('ns3::AttributeValue const &', 'v1')])
     return
 
 def register_Ns3UdpEchoClientHelper_methods(root_module, cls):
--- a/bindings/python/ns3_module_node.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_node.py	Fri Apr 17 17:45:16 2009 +0200
@@ -2311,16 +2311,6 @@
                    is_static=True)
     ## channel.h: ns3::Channel::Channel() [constructor]
     cls.add_constructor([])
-    ## channel.h: ns3::Channel::Channel(std::string name) [constructor]
-    cls.add_constructor([param('std::string', 'name')])
-    ## channel.h: void ns3::Channel::SetName(std::string arg0) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string', 'arg0')])
-    ## channel.h: std::string ns3::Channel::GetName() [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [])
     ## channel.h: uint32_t ns3::Channel::GetNDevices() const [member function]
     cls.add_method('GetNDevices', 
                    'uint32_t', 
@@ -2750,16 +2740,6 @@
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## net-device.h: void ns3::NetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## net-device.h: std::string ns3::NetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
     ## net-device.h: void ns3::NetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
@@ -3016,16 +2996,6 @@
     cls.add_method('SetAddress', 
                    'void', 
                    [param('ns3::Mac48Address', 'address')])
-    ## simple-net-device.h: void ns3::SimpleNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## simple-net-device.h: std::string ns3::SimpleNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## simple-net-device.h: void ns3::SimpleNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_point_to_point.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_point_to_point.py	Fri Apr 17 17:45:16 2009 +0200
@@ -175,16 +175,6 @@
                    'uint16_t', 
                    [], 
                    is_const=True)
-    ## point-to-point-net-device.h: void ns3::PointToPointNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## point-to-point-net-device.h: std::string ns3::PointToPointNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## point-to-point-net-device.h: void ns3::PointToPointNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_tap_bridge.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_tap_bridge.py	Fri Apr 17 17:45:16 2009 +0200
@@ -5,6 +5,8 @@
     
     ## tap-bridge.h: ns3::TapBridge [class]
     module.add_class('TapBridge', parent=root_module['ns3::NetDevice'])
+    ## tap-bridge.h: ns3::TapBridge::Mode [enumeration]
+    module.add_enum('Mode', ['ILLEGAL', 'CONFIGURE_LOCAL', 'USE_LOCAL', 'USE_BRIDGE'], outer_class=root_module['ns3::TapBridge'])
     
     ## Register a nested module for the namespace Config
     
@@ -76,16 +78,14 @@
     cls.add_method('Stop', 
                    'void', 
                    [param('ns3::Time', 'tStop')])
-    ## tap-bridge.h: void ns3::TapBridge::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
+    ## tap-bridge.h: void ns3::TapBridge::SetMode(ns3::TapBridge::Mode mode) [member function]
+    cls.add_method('SetMode', 
                    'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## tap-bridge.h: std::string ns3::TapBridge::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
+                   [param('ns3::TapBridge::Mode', 'mode')])
+    ## tap-bridge.h: ns3::TapBridge::Mode ns3::TapBridge::GetMode() [member function]
+    cls.add_method('GetMode', 
+                   'ns3::TapBridge::Mode', 
+                   [])
     ## tap-bridge.h: void ns3::TapBridge::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_wifi.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3_module_wifi.py	Fri Apr 17 17:45:16 2009 +0200
@@ -228,8 +228,8 @@
                    'ns3::Ptr< ns3::ErrorRateModel >', 
                    [], 
                    is_const=True)
-    ## interference-helper.h: double ns3::InterferenceHelper::GetNoiseFloorW() const [member function]
-    cls.add_method('GetNoiseFloorW', 
+    ## interference-helper.h: double ns3::InterferenceHelper::GetNoiseFigure() const [member function]
+    cls.add_method('GetNoiseFigure', 
                    'double', 
                    [], 
                    is_const=True)
@@ -237,10 +237,10 @@
     cls.add_method('SetErrorRateModel', 
                    'void', 
                    [param('ns3::Ptr< ns3::ErrorRateModel >', 'rate')])
-    ## interference-helper.h: void ns3::InterferenceHelper::SetNoiseFloorW(double noiseFloor) [member function]
-    cls.add_method('SetNoiseFloorW', 
+    ## interference-helper.h: void ns3::InterferenceHelper::SetNoiseFigure(double value) [member function]
+    cls.add_method('SetNoiseFigure', 
                    'void', 
-                   [param('double', 'noiseFloor')])
+                   [param('double', 'value')])
     return
 
 def register_Ns3InterferenceHelperSnrPer_methods(root_module, cls):
@@ -727,8 +727,8 @@
 def register_Ns3ArfWifiRemoteStation_methods(root_module, cls):
     ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::ArfWifiRemoteStation const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::ArfWifiRemoteStation const &', 'arg0')])
-    ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::Ptr<ns3::ArfWifiManager> stations, int minTimerTimeout, int minSuccessThreshold) [constructor]
-    cls.add_constructor([param('ns3::Ptr< ns3::ArfWifiManager >', 'stations'), param('int', 'minTimerTimeout'), param('int', 'minSuccessThreshold')])
+    ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::Ptr<ns3::ArfWifiManager> manager) [constructor]
+    cls.add_constructor([param('ns3::Ptr< ns3::ArfWifiManager >', 'manager')])
     ## arf-wifi-manager.h: void ns3::ArfWifiRemoteStation::DoReportRxOk(double rxSnr, ns3::WifiMode txMode) [member function]
     cls.add_method('DoReportRxOk', 
                    'void', 
@@ -1667,6 +1667,11 @@
                    'bool', 
                    [], 
                    is_const=True)
+    ## wifi-remote-station-manager.h: ns3::WifiMode ns3::WifiRemoteStationManager::GetNonUnicastMode() const [member function]
+    cls.add_method('GetNonUnicastMode', 
+                   'ns3::WifiMode', 
+                   [], 
+                   is_const=True)
     ## wifi-remote-station-manager.h: ns3::WifiRemoteStation * ns3::WifiRemoteStationManager::Lookup(ns3::Mac48Address address) [member function]
     cls.add_method('Lookup', 
                    'ns3::WifiRemoteStation *', 
@@ -1707,10 +1712,10 @@
     cls.add_method('SetStandard', 
                    'void', 
                    [param('ns3::WifiPhyStandard', 'standard')])
-    ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetRxNoise(double ratio) [member function]
-    cls.add_method('SetRxNoise', 
+    ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetRxNoiseFigure(double noiseFigureDb) [member function]
+    cls.add_method('SetRxNoiseFigure', 
                    'void', 
-                   [param('double', 'ratio')])
+                   [param('double', 'noiseFigureDb')])
     ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetTxPowerStart(double start) [member function]
     cls.add_method('SetTxPowerStart', 
                    'void', 
@@ -1751,8 +1756,8 @@
     cls.add_method('SetMobility', 
                    'void', 
                    [param('ns3::Ptr< ns3::Object >', 'mobility')])
-    ## yans-wifi-phy.h: double ns3::YansWifiPhy::GetRxNoise() const [member function]
-    cls.add_method('GetRxNoise', 
+    ## yans-wifi-phy.h: double ns3::YansWifiPhy::GetRxNoiseFigure() const [member function]
+    cls.add_method('GetRxNoiseFigure', 
                    'double', 
                    [], 
                    is_const=True)
@@ -1900,8 +1905,8 @@
 def register_Ns3AarfWifiRemoteStation_methods(root_module, cls):
     ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::AarfWifiRemoteStation const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::AarfWifiRemoteStation const &', 'arg0')])
-    ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::Ptr<ns3::AarfWifiManager> stations, uint32_t minTimerThreshold, uint32_t minSuccessThreshold, double successK, uint32_t maxSuccessThreshold, double timerK) [constructor]
-    cls.add_constructor([param('ns3::Ptr< ns3::AarfWifiManager >', 'stations'), param('uint32_t', 'minTimerThreshold'), param('uint32_t', 'minSuccessThreshold'), param('double', 'successK'), param('uint32_t', 'maxSuccessThreshold'), param('double', 'timerK')])
+    ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::Ptr<ns3::AarfWifiManager> stations) [constructor]
+    cls.add_constructor([param('ns3::Ptr< ns3::AarfWifiManager >', 'stations')])
     ## aarf-wifi-manager.h: void ns3::AarfWifiRemoteStation::ReportRecoveryFailure() [member function]
     cls.add_method('ReportRecoveryFailure', 
                    'void', 
@@ -1912,6 +1917,11 @@
                    'void', 
                    [], 
                    visibility='private', is_virtual=True)
+    ## aarf-wifi-manager.h: ns3::Ptr<ns3::WifiRemoteStationManager> ns3::AarfWifiRemoteStation::GetManager() const [member function]
+    cls.add_method('GetManager', 
+                   'ns3::Ptr< ns3::WifiRemoteStationManager >', 
+                   [], 
+                   is_const=True, visibility='private', is_virtual=True)
     return
 
 def register_Ns3AdhocWifiMac_methods(root_module, cls):
@@ -2697,16 +2707,6 @@
                    'ns3::Ptr< ns3::WifiRemoteStationManager >', 
                    [], 
                    is_const=True)
-    ## wifi-net-device.h: void ns3::WifiNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## wifi-net-device.h: std::string ns3::WifiNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## wifi-net-device.h: void ns3::WifiNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3modulegen.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/ns3modulegen.py	Fri Apr 17 17:45:16 2009 +0200
@@ -145,6 +145,7 @@
     if 'TapBridge' not in enabled_features:
         for clsname in ['TapBridge', 'TapBridgeHelper']:
             root_module.classes.remove(root_module['ns3::%s' % clsname])
+        root_module.enums.remove(root_module['ns3::TapBridge::Mode'])
 
     root_module.generate(out, '_ns3')
 
--- a/bindings/python/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/bindings/python/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -273,7 +273,7 @@
 
     def apply(self):
         ## get all of the ns3 headers
-        ns3_dir_node = Build.bld.path.find_dir("ns3")
+        ns3_dir_node = self.bld.path.find_dir("ns3")
         all_headers_inputs = []
 
         for filename in self.to_list(self.source):
@@ -284,7 +284,7 @@
 
         ## if self.source was empty, include all ns3 headers in enabled modules
         if not all_headers_inputs:
-            for ns3headers in Build.bld.all_task_gen:
+            for ns3headers in self.bld.all_task_gen:
                 if type(ns3headers).__name__ == 'ns3header_taskgen': # XXX: find less hackish way to compare
                     ## skip headers not part of enabled modules
                     if self.env['NS3_ENABLED_MODULES']:
@@ -307,7 +307,7 @@
         pass
 
 
-def get_modules_and_headers():
+def get_modules_and_headers(bld):
     """
     Gets a dict of
        module_name => ([module_dep1, module_dep2, ...], [module_header1, module_header2, ...])
@@ -315,13 +315,13 @@
     """
 
     retval = {}
-    for module in Build.bld.all_task_gen:
+    for module in bld.all_task_gen:
         if not module.name.startswith('ns3-'):
             continue
         module_name = module.name[4:] # strip the ns3- prefix
         ## find the headers object for this module
         headers = []
-        for ns3headers in Build.bld.all_task_gen:
+        for ns3headers in bld.all_task_gen:
             if type(ns3headers).__name__ != 'ns3header_taskgen': # XXX: find less hackish way to compare
                 continue
             if ns3headers.module != module_name:
@@ -338,8 +338,9 @@
     """
     after = 'gen_everything_h_task'
     before = 'cc cxx'
-    def __init__(self, curdirnode, env):
-        super(python_scan_task, self).__init__()
+    def __init__(self, curdirnode, env, bld):
+        self.bld = bld
+        super(python_scan_task, self).__init__(generator=self)
         self.curdirnode = curdirnode
         self.env = env
 
@@ -356,7 +357,7 @@
             os.path.join(self.curdirnode.abspath(), 'ns3modulegen_generated.py'), # output file
             ]
         scan = subprocess.Popen(argv, stdin=subprocess.PIPE)
-        scan.stdin.write(repr(get_modules_and_headers()))
+        scan.stdin.write(repr(get_modules_and_headers(self.bld)))
         scan.stdin.close()
         retval = scan.wait()
         print "Scan finished with exit code", retval
@@ -365,7 +366,7 @@
         # signal stop (we generated files into the source dir and WAF
         # can't cope with it, so we have to force the user to restart
         # WAF)
-        Build.bld.generator.stop = 1
+        self.bld.generator.stop = 1
         return 0
 
 
@@ -384,7 +385,7 @@
     if Options.options.python_scan:
         if not env['ENABLE_PYTHON_SCANNING']:
             raise Utils.WafError("Cannot re-scan python bindings: (py)gccxml not available")
-        python_scan_task(bld.path, env)
+        python_scan_task(bld.path, env, bld)
         return
 
     ## Get a list of scanned modules; the set of scanned modules
@@ -412,7 +413,7 @@
             'ns3modulegen.log',
             ]
         argv = ['NS3_ENABLED_FEATURES=${FEATURES}', '${PYTHON}', '${SRC[0]}', '${TGT[0]}']
-        argv.extend(get_modules_and_headers().iterkeys())
+        argv.extend(get_modules_and_headers(bld).iterkeys())
         for module in scanned_modules:
             source.append("ns3_module_%s.py" % module)
             local = "ns3_module_%s__local.py" % module
@@ -429,16 +430,13 @@
             if was_enabled:
                 features.append(name)
 
-        bindgen = bld.new_task_gen('command', source=source, target=target,
-                                   command=argv, variables=dict(FEATURES=(','.join(features))))
+        bindgen = bld.new_task_gen('command', source=source, target=target, command=argv)
+        bindgen.env['FEATURES'] = ','.join(features)
+        bindgen.dep_vars = ['FEATURES']
         bindgen.before = 'cxx'
         bindgen.after = 'gen_everything_h_task'
+        bindgen.name = "pybindgen-command"
 
-    ## we build python bindings if either we have the tools to
-    ## generate them or if the pregenerated source file is already
-    ## present in the source dir.
-    if env['ENABLE_PYTHON_BINDINGS'] \
-            or os.path.exists(os.path.join(bld.path.abspath(), 'ns3module.cc')):
         pymod = bld.new_task_gen('cxx', 'shlib', 'pyext')
         pymod.source = ['ns3module.cc', 'ns3module_helpers.cc']
         pymod.includes = '.'
--- a/doc/tutorial/building-topologies.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/building-topologies.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -53,6 +53,17 @@
 Just as in the @code{first.cc} example (and in all ns-3 examples) the file
 begins with an emacs mode line and some GPL boilerplate.
 
+The actual code begins by loading module include files just as was done in the
+@code{first.cc} example.
+
+@verbatim
+  #include "ns3/core-module.h"
+  #include "ns3/simulator-module.h"
+  #include "ns3/node-module.h"
+  #include "ns3/helper-module.h"
+  #include "ns3/global-routing-module.h"
+@end verbatim
+
 One thing that can be surprisingly useful is a small bit of ASCII art that
 shows a cartoon of the network topology constructed in the example.  You will
 find a similar ``drawing'' in most of our examples.
@@ -75,53 +86,47 @@
 //                      LAN 10.1.2.0
 @end verbatim
 
-The actual code begins by loading module include files just as was done in the
-@code{first.cc} example.  Then the ns-3 namespace is @code{used} and a logging
-component is defined.  This is all just as it was in @code{first.cc}, so there
-is nothing new yet.
+Then the ns-3 namespace is @code{used} and a logging component is defined.
+This is all just as it was in @code{first.cc}, so there is nothing new yet.
 
-@verbatim
-  #include "ns3/core-module.h"
-  #include "ns3/simulator-module.h"
-  #include "ns3/node-module.h"
-  #include "ns3/helper-module.h"
-  #include "ns3/global-routing-module.h"
-  
+@verbatim  
   using namespace ns3;
   
   NS_LOG_COMPONENT_DEFINE ("SecondScriptExample");
 @end verbatim
 
-The main program begins by enabling the @code{UdpEchoClientApplication} and
-@code{UdpEchoServerApplication} logging components at @code{INFO} level so
-we can see some output when we run the example.  This should be entirely 
-familiar to you so far.
+The main program begins with a slightly different twist.  We use a verbose
+flag to determine whether or not the @code{UdpEchoClientApplication} and
+@code{UdpEchoServerApplication} logging components are enabled.  This flag
+defaults to true (the logging components are enabled) but allows us to turn
+off logging during regression testing of this example.
+
+You will see some familiar code that will allow you to change the number
+of devices on the CSMA network via command line argument.  We did something
+similar when we allowed the number of packets sent to be changed in the section
+on command line arguments.  The last line makes sure you have at least one
+``extra'' node.
+
+The code consists of variations of previously covered API so you should be
+entirely comfortable with the following code at this point in the tutorial.
 
 @verbatim
-  int
-  main (int argc, char *argv[])
-  {
-    LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
-    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
-@end verbatim
+  bool verbose = true;
+  uint32_t nCsma = 3;
 
-A fixed seed is provided to the random number generators so that they will
-generate repeatable results.
+  CommandLine cmd;
+  cmd.AddValue (``nCsma'', ``Number of \"extra\" CSMA nodes/devices'', nCsma);
+  cmd.AddValue (``verbose'', ``Tell echo applications to log if true'', verbose);
 
-@verbatim
-  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
-@end verbatim
+  cmd.Parse (argc,argv);
 
-Next, you will see some familiar code that will allow you to change the number
-of devices on the CSMA network via command line argument.  We did something
-similar when we allowed the number of packets sent to be changed in the section
-on command line arguments.
+  if (verbose)
+    {
+      LogComponentEnable(``UdpEchoClientApplication'', LOG_LEVEL_INFO);
+      LogComponentEnable(``UdpEchoServerApplication'', LOG_LEVEL_INFO);
+    }
 
-@verbatim
-  uint32_t nCsma = 3;
-  CommandLine cmd;
-  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
-  cmd.Parse (argc,argv);
+  nCsma = nCsma == 0 ? 1 : nCsma;
 @end verbatim
 
 The next step is to create two nodes that we will connect via the 
@@ -147,12 +152,15 @@
 from the point-to-point node container and adds it to the container of nodes
 that will get CSMA devices.  The node in question is going to end up with a 
 point-to-point device @emph{and} a CSMA device.  We then create a number of 
-``extra'' nodes that compose the remainder of the CSMA network.
+``extra'' nodes that compose the remainder of the CSMA network.  Since we 
+already have one node in the CSMA network -- the one that will have both a
+point-to-point and CSMA net device, the number of ``extra'' nodes means the
+number nodes you desire in the CSMA section minus one.
 
 The next bit of code should be quite familiar by now.  We instantiate a
-@code{PointToPointHelper} and set the associated default attributes so that
-we create a five megabit per second transmitter on devices created using the
-helper and a two millisecond delay on channels created by the helper.
+@code{PointToPointHelper} and set the associated default @code{Attributes} so
+that we create a five megabit per second transmitter on devices created using
+the helper and a two millisecond delay on channels created by the helper.
 
 @verbatim
   PointToPointHelper pointToPoint;
@@ -171,13 +179,13 @@
 channels, and the next lines introduce them.  The @code{CsmaHelper} works just
 like a @code{PointToPointHelper}, but it creates and connects CSMA devices and
 channels.  In the case of a CSMA device and channel pair, notice that the data
-rate is specified by a @emph{channel} attribute instead of a device attribute.
-This is because a real CSMA network does not allow one to mix, for example, 
-10Base-T and 100Base-T devices on a given channel.  We first set the data rate
-to 100 megabits per second, and then set the speed-of-light delay of the channel
-to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot over a 100
-meter segment).  Notice that you can set an attribute using its native data 
-type.
+rate is specified by a @emph{channel} @code{Attribute} instead of a device 
+@code{Attribute}.  This is because a real CSMA network does not allow one to mix,
+for example, 10Base-T and 100Base-T devices on a given channel.  We first set 
+the data rate to 100 megabits per second, and then set the speed-of-light delay
+of the channel to 6560 nano-seconds (arbitrarily chosen as 1 nanosecond per foot
+over a 100 meter segment).  Notice that you can set an @code{Attribute} using 
+its native data type.
 
 @verbatim
   CsmaHelper csma;
@@ -244,8 +252,8 @@
 point-to-point device.
 
 First, we set up the echo server.  We create a @code{UdpEchoServerHelper} and
-provide a required attribute value to the constructor which is the server port
-number.  Recall that this port can be changed later using the 
+provide a required @code{Attribute} value to the constructor which is the server
+port number.  Recall that this port can be changed later using the 
 @code{SetAttribute} method if desired, but we require it to be provided to
 the constructor.
 
@@ -268,7 +276,7 @@
 code.
 
 The client application is set up exactly as we did in the @code{first.cc}
-example script.  Again, we provide required attributes to the 
+example script.  Again, we provide required @code{Attributes} to the 
 @code{UdpEchoClientHelper} in the constructor (in this case the remote address
 and port).  We tell the client to send packets to the server we just installed
 on the last of the ``extra'' CSMA nodes.  We install the client on the 
@@ -286,7 +294,7 @@
 @end verbatim
 
 Since we have actually built an internetwork here, we need some form of 
-internetwork routing.  @command{Ns-3} provides what we call a global route 
+internetwork routing.  @command{ns-3} provides what we call a global route 
 manager to set up the routing tables on nodes.  This route manager has a 
 global function that runs though the nodes created for the simulation and does
 the hard work of setting up routing for you.  
@@ -302,15 +310,40 @@
   GlobalRouteManager::PopulateRoutingTables ();
 @end verbatim
 
-The remainder of the script should be very familiar to you.  We just enable
-pcap tracing, run the simulation and exit the script.  Notice that enabling
-pcap tracing using the CSMA helper is done in the same way as for the pcap
-tracing with the point-to-point helper.
+Next we enable pcap tracing.  The first line of code to enable pcap tracing 
+in the point-to-point helper should be familiar to you by now.  The second
+line enables pcap tracing in the CSMA helper and there is an extra parameter
+you haven't encountered yet.
 
 @verbatim
-    PointToPointHelper::EnablePcapAll ("second");
-    CsmaHelper::EnablePcapAll ("second");
-  
+  PointToPointHelper::EnablePcapAll ("second");
+  CsmaHelper::EnablePcap ("second", csmaDevices.Get (0), true);
+@end verbatim
+
+The CSMA network is a multi-point-to-point network.  This means that there 
+can (and are in this case) multiple endpoints on a shared medium.  Each of 
+these endpoints has a net device associated with it.  There are two basic
+alternatives to gathering trace information from such a network.  One way 
+is to create a trace file for each net device and store only the packets
+that are emitted or consumed by that net device.  Another way is to pick 
+one of the devices and place it in promiscuous mode.  That single device
+then ``sniffs'' the network for all packets and stores them in a single
+pcap file.  This is how @code{tcpdump}, for example, works.  That final 
+parameter tells the CSMA helper whether or not to capture packets in 
+promiscuous mode.  
+
+In this example, we are going to select one of the devices on the CSMA
+network and ask it to perform a promiscuous sniff of the network, thereby
+emulating what @code{tcpdump} would do.  If you were on a Linux machine
+you might do something like @code{tcpdump -i eth0} to get the trace.  
+In this case, we specify the device using @code{csmaDevices.Get(0)}, 
+which selects the zeroth device in the container.  Setting the final
+parameter to true enables promiscuous captures.
+
+The last section of code just runs and cleans up the simulation just like
+the @code{first.cc} example.
+
+@verbatim
     Simulator::Run ();
     Simulator::Destroy ();
     return 0;
@@ -318,27 +351,40 @@
 @end verbatim
 
 In order to run this example, you have to copy the @code{second.cc} example
-script into the scratch directory and use Waf to build just as you did with
+script into the scratch directory and use waf to build just as you did with
 the @code{first.cc} example.  If you are in the top-level directory of the
 repository you would type,
 
 @verbatim
-  cp examples/second.cc scratch/
+  cp examples/second.cc scratch/mysecond.cc
   ./waf
-  ./waf --run scratch/second
 @end verbatim
 
+Warning:  We use the file @code{second.cc} as one of our regression tests to
+verify that it works exactly as we think it should in order to make your
+tutorial experience a positive one.  This means that an executable named 
+@code{second} already exists in the project.  To avoid any confusion
+about what you are executing, please do the renaming to @code{mysecond.cc}
+suggested above.
+
+If you are following the tutorial religiously (you are, aren't you) you will
+still have the NS_LOG variable set, so go ahead and clear that variable and
+run the program.
+
+@verbatim
+  export NS_LOG=
+  ./waf --run scratch/mysecond
+#end verbatim
+
 Since we have set up the UDP echo applications to log just as we did in 
 @code{first.cc}, you will see similar output when you run the script.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/second
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Sent 1024 bytes to 10.1.2.4
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.2.4
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Recall that the first message, @code{Sent 1024 bytes to 10.1.2.4} is the 
@@ -349,38 +395,41 @@
 is from the echo client, indicating that it has received its echo back from
 the server.
 
-If you now go and look in the top level directory, you will find a number of
-trace files:
+If you now go and look in the top level directory, you will find two trace 
+files:
 
 @verbatim
-  ~/repos/ns-3-dev > ls *.pcap
-  second-0-0.pcap  second-1-1.pcap  second-3-0.pcap
-  second-1-0.pcap  second-2-0.pcap  second-4-0.pcap
-  ~/repos/ns-3-dev >
+  second-0-0.pcap  second-1-0.pcap  second-2-0.pcap
 @end verbatim
 
 Let's take a moment to look at the naming of these files.  They all have the 
 same form, @code{<name>-<node>-<device>.pcap}.  For example, the first file
 in the listing is @code{second-0-0.pcap} which is the pcap trace from node 
-zero - device zero.  There are no other devices on node zero so this is the
-only trace from that node.  
+zero, device zero.  This is the point-to-point net device on node zero.  The 
+file @code{second-1-0.pcap} is the pcap trace for device zero on node one,
+also a point-to-point net device; and the file @code{second-2-0.pcap} is the
+pcap trace for device zero on node two.
 
-Now look at @code{second-1-0.pcap} and @code{second-1-1.pcap}.  The former is
-the pcap trace for device zero on node one and the latter is the trace file 
-for device one on node one.  If you refer back to the topology illustration at
-the start of the section, you will see that node one is the node that has
-both a point-to-point device and a CSMA device, so we should expect two pcap
-traces for that node.
+If you refer back to the topology illustration at the start of the section, 
+you will see that node zero is the leftmost node of the point-to-point link
+and node one is the node that has both a point-to-point device and a CSMA 
+device.  You will see that node two is the first ``extra'' node on the CSMA
+network and its device zero was selected as the device to capture the 
+promiscuous-mode trace.
 
 Now, let's follow the echo packet through the internetwork.  First, do a 
 tcpdump of the trace file for the leftmost point-to-point node --- node zero.
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r second-0-0.pcap -nn -tt
+  tcpdump -nn -tt -r second-0-0.pcap
+@end verbatim
+
+You should see the contents of the pcap file displayed:
+
+@verbatim
   reading from file second-0-0.pcap, link-type PPP (PPP)
   2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-  2.007382 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
+  2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
 @end verbatim
 
 The first line of the dump indicates that the link type is PPP (point-to-point)
@@ -391,134 +440,163 @@
 one.  Let's take a look:
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r second-1-0.pcap -nn -tt
-  reading from file second-1-0.pcap, link-type PPP (PPP)
-  2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-  2.003695 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
+  tcpdump -nn -tt -r second-1-0.pcap
+@end verbatim
+
+You should now see the pcap trace output of the other side of the point-to-point
+link:
+
+@verbatim
+reading from file second-1-0.pcap, link-type PPP (PPP)
+2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
 @end verbatim
 
 Here we see that the link type is also PPP as we would expect.  You see the
-packet from IP address 10.1.1.1 headed toward 10.1.2.4 appear on this 
-interface.  Now, internally to this node, the packet will be forwarded to the
-CSMA interface and we should see it pop out the other device headed for its
-ultimate destination.  Let's then look at second-1-1.pcap and see if its there.
+packet from IP address 10.1.1.1 (that was sent at 2.000000 seconds) headed 
+toward IP address 10.1.2.4 appear on this interface.  Now, internally to this 
+node, the packet will be forwarded to the CSMA interface and we should see it 
+pop out on that device headed for its ultimate destination.  
+
+Remember that we selected node 2 as the promiscuous sniffer node for the CSMA
+network so let's then look at second-2-0.pcap and see if its there.
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r second-1-1.pcap -nn -tt
-  reading from file second-1-1.pcap, link-type EN10MB (Ethernet)
-  2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
-  2.003687 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
-  2.003687 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-  2.003691 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
-  2.003691 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
-  2.003695 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
+  tcpdump -nn -tt -r second-2-0.pcap
+@end verbatim
+
+You should now see the promiscuous dump of node two, device zero:
+
+@verbatim
+  reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
+  2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+  2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+  2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+  2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+  2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+  2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
 @end verbatim
 
 As you can see, the link type is now ``Ethernet''.  Something new has appeared,
 though.  The bus network needs @code{ARP}, the Address Resolution Protocol.
-The node knows it needs to send the packet to IP address 10.1.2.4, but it
+Node one knows it needs to send the packet to IP address 10.1.2.4, but it
 doesn't know the MAC address of the corresponding node.  It broadcasts on the
 CSMA network (ff:ff:ff:ff:ff:ff) asking for the device that has IP address
 10.1.2.4.  In this case, the rightmost node replies saying it is at MAC address
-00:00:00:00:00:06.  This exchange is seen in the following lines,
+00:00:00:00:00:06.  (Note that node two is not directly involved in this 
+exchange, but is sniffing the network and reporting all of the traffic it sees.)
+
+This exchange is seen in the following lines,
 
 @verbatim
-  2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
-  2.003687 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+  2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+  2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
 @end verbatim
 
 Then node one, device one goes ahead and sends the echo packet to the UDP echo
-server at IP address 10.1.2.4.  We can now look at the pcap trace for the 
-echo server,
+server at IP address 10.1.2.4. 
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r second-4-0.pcap -nn -tt
-  reading from file second-4-0.pcap, link-type EN10MB (Ethernet)
-  2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
-  2.003686 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
-  2.003690 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
-  2.003690 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
-  2.003692 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
-  2.003692 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
+  2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+@end verbatim
+
+The server receives the echo request and turns the packet around trying to send
+it back to the source.  The server knows that this address is on another network
+that it reaches via IP address 10.1.2.1.  This is because we initialized global
+routing and it has figured all of this out for us.  But, the echo server node
+doesn't know the MAC address of the first CSMA node, so it has to ARP for it
+just like the first CSMA node had to do.
+
+@verbatim
+  2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+  2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+@end verbatim
+
+The server then sends the echo back to the forwarding node.
+
+@verbatim
+  2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
 @end verbatim
 
-Again, you see that the link type is ``Ethernet''.  The first two entries are
-the ARP exchange we just explained.  The third packet is the echo packet 
-being delivered to its final destination.
+Looking back at the rightmost node of the point-to-point link,
 
-The echo server turns the packet around and needs to send it back to the echo
-client on 10.1.1.1 but it knows that this address is on another network that 
-it reaches via IP address 10.1.2.1.  This is because we initialized global
-routing and it has figured all of this out for us.  But, the echo server node
-doesn't know the MAC address of the first CSMA node, so it has to ARP for it
-just like the first CSMA node had to do.  We leave it as an exercise for you
-to find the entries corresponding to the packet returning back on its way to
-the client (we have already dumped the traces and you can find them in those
-tcpdumps above.
+@verbatim
+  tcpdump -nn -tt -r second-1-0.pcap
+@end verbatim
 
-Let's take a look at one of the CSMA nodes that wasn't involved in the packet 
-exchange:
+You can now see the echoed packet coming back onto the point-to-point link as
+the last line of the trace dump.
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r second-2-0.pcap -nn -tt
-  reading from file second-2-0.pcap, link-type EN10MB (Ethernet)
-  2.003686 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
-  2.003691 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
-  ~/repos/ns-3-dev >
+reading from file second-1-0.pcap, link-type PPP (PPP)
+2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
 @end verbatim
 
-You can see that the CSMA channel is a broadcast medium and so all of the 
-devices see the ARP requests involved in the packet exchange.  The remaining
-pcap trace will be identical to this one.
+Lastly, you can look back at the node that originated the echo
+@verbatim
+  tcpdump -nn -tt -r second-0-0.pcap
+@end verbatim
+
+and see that the echoed packet arrives back at the source at 2.007602 seconds,
+
+@verbatim
+  reading from file second-0-0.pcap, link-type PPP (PPP)
+  2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024
+  2.007602 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024
+@end verbatim
 
 Finally, recall that we added the ability to control the number of CSMA devices
 in the simulation by command line argument.  You can change this argument in
 the same way as when we looked at changing the number of packets echoed in the
-@code{first.cc} example.  Try setting the number of ``extra'' devices to four:
+@code{first.cc} example.  Try running the program with the number of ``extra'' 
+devices set to four:
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run "scratch/second --nCsma=4"
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  ./waf --run "scratch/mysecond --nCsma=4"
+@end verbatim
+
+You should now see,
+
+@verbatim
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Sent 1024 bytes to 10.1.2.5
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.2.5
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Notice that the echo server has now been relocated to the last of the CSMA
-nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.  You can 
-increase the number to your hearts content, but remember that you will get a
-pcap trace file for every node in the simulation.  One thing you can do to
-keep from getting all of those pcap traces with nothing but ARP exchanges in 
-them is to be more specific about which nodes and devices you want to trace.
+nodes, which is 10.1.2.5 instead of the default case, 10.1.2.4.
 
-Let's take a look at @code{scratch/second.cc} and add that code enabling us
-to be more specific.  The file we provided used the @code{EnablePcapAll} 
-methods of the helpers to enable pcap on all devices.  We now want to use the
-more specific method, @code{EnablePcap}, which takes a node number and device
-number as parameters.  Go ahead and replace the @code{EnablePcapAll} calls 
-with the calls below.
+It is possible that you may not be satisfied with a trace file generated by
+a bystander in the CSMA network.  You may really want to get a trace from
+a single device and you may not be interested in any other traffic on the 
+network.  You can do this,
+
+Let's take a look at @code{scratch/mysecond.cc} and add that code enabling us
+to be more specific.  @code{ns-3} helpers provide methods that take a node
+number and device number as parameters.  Go ahead and replace the 
+@code{EnablePcap} calls with the calls below.
 
 @verbatim
   PointToPointHelper::EnablePcap ("second", p2pNodes.Get (0)->GetId (), 0);
-  CsmaHelper::EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0);
+  CsmaHelper::EnablePcap ("second", csmaNodes.Get (nCsma)->GetId (), 0, false);
+  CsmaHelper::EnablePcap ("second", csmaNodes.Get (nCsma-1)->GetId (), 0, false);
 @end verbatim
 
 We know that we want to create a pcap file with the base name "second" and
 we also know that the device of interest in both cases is going to be zero,
-so those parameters are not really interesting.  In order to get the node
-number, you have two choices:  first, nodes are numbered in a monotonically
-increasing fashion starting from zero in the order in which you created them.
-One way to get a node number is to figure this number out ``manually'' by
-contemplating the order of node creation.  If you take a look at the network 
-topology illustration at the beginning of the file, we did this for you and
-you can see that the last CSMA node is going to be node number 
-@code{nCsma + 1}.  This approach can become annoyingly difficult in larger 
-simulations.  
+so those parameters are not really interesting.
+
+In order to get the node number, you have two choices:  first, nodes are 
+numbered in a monotonically increasing fashion starting from zero in the 
+order in which you created them.  One way to get a node number is to figure 
+this number out ``manually'' by contemplating the order of node creation.  
+If you take a look at the network topology illustration at the beginning of 
+the file, we did this for you and you can see that the last CSMA node is 
+going to be node number @code{nCsma + 1}.  This approach can become 
+annoyingly difficult in larger simulations.  
 
 An alternate way, which we use here, is to realize that the
 @code{NodeContainers} contain pointers to @command{ns-3} @code{Node} Objects.
@@ -537,35 +615,54 @@
 documentation for the method.  Using the @code{GetId} method can make 
 determining node numbers much easier in complex topologies.
 
-Now that we have got some trace filtering in place, it is reasonable to start
-increasing the number of CSMA devices in our simulation.  If you build the 
-new script and run the simulation setting @code{nCsma} to 100, you will see 
-the following output:
+If you build the new script and run the simulation setting @code{nCsma} to 100,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run "scratch/second --nCsma=100"
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  ./waf --run "scratch/mysecond --nCsma=100"
+@end verbatim
+
+you will see the following output:
+
+@verbatim
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Sent 1024 bytes to 10.1.2.101
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.2.101
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Note that the echo server is now located at 10.1.2.101 which corresponds to
 having 100 ``extra'' CSMA nodes with the echo server on the last one.  If you
-list the pcap files in the top level directory,
+list the pcap files in the top level directory you will see,
 
 @verbatim
-  ~/repos/ns-3-dev > ls *.pcap
-  second-0-0.pcap  second-101-0.pcap
-  ~/repos/ns-3-dev >
+  second-0-0.pcap  second-100-0.pcap  second-101-0.pcap
 @end verbatim
 
-you will see that we have, in fact, only created two trace files.  The trace
-file @code{second-0-0.pcap} is the ``leftmost'' point-to-point device which is
-the echo packet source.  The file @code{second-101-0.pcap} corresponds to the
-rightmost CSMA device which is where the echo server resides.
+The trace file @code{second-0-0.pcap} is the ``leftmost'' point-to-point device
+which is the echo packet source.  The file @code{second-101-0.pcap} corresponds
+to the rightmost CSMA device which is where the echo server resides.  You may 
+have noticed that the final parameter on the call to enable pcap tracing on the 
+echo server node was false.  This means that the trace gathered on that node
+was in non-promiscuous mode.
+
+To illustrate the difference between promiscuous and non-promiscuous traces, we
+also requested a non-promiscuous trace for the next-to-last node.  Go ahead and
+take a look at the @code{tcpdump} for @code{second-10-0.pcap}.
+
+@verbatim
+  tcpdump -nn -tt -r second-100-0.pcap
+@end verbatim
+
+You can now see that node 100 is really a bystander in the echo exchange.  The
+only packets that it receives are the ARP requests which are broadcast to the
+entire CSMA network.
+
+@verbatim
+reading from file second-100-0.pcap, link-type EN10MB (Ethernet)
+2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.101
+@end verbatim
 
 @c ========================================================================
 @c Building a Wireless Network Topology
@@ -651,36 +748,27 @@
   NS_LOG_COMPONENT_DEFINE ("ThirdScriptExample");
 @end verbatim
 
-As has become the norm in this tutorial, the main program begins by enabling
-the @code{UdpEchoClientApplication} and @code{UdpEchoServerApplication} 
-logging components at @code{INFO} level so we can see some output when we run
-the simulation.
+The main program begins just like @code{second.cc} by adding some command line
+parameters for enabling or disabling logging components and for changing the 
+number of devices created.
 
 @verbatim
-  int
-  main (int argc, char *argv[])
-  {
-    LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
-    LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
-@end verbatim
-
-A fixed seed is provided to the random number generators so that they will
-generate repeatable results.
-
-@verbatim
-  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
-@end verbatim
-
-Next, you will see more familiar code that will allow you to change the number
-of devices on the CSMA and Wifi networks via command line argument.
-
-@verbatim
+  bool verbose = true;
   uint32_t nCsma = 3;
   uint32_t nWifi = 3;
+
   CommandLine cmd;
-  cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
-  cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
+  cmd.AddValue (``nCsma'', ``Number of \"extra\" CSMA nodes/devices'', nCsma);
+  cmd.AddValue (``nWifi'', ``Number of wifi STA devices'', nWifi);
+  cmd.AddValue (``verbose'', ``Tell echo applications to log if true'', verbose);
+
   cmd.Parse (argc,argv);
+
+  if (verbose)
+    {
+      LogComponentEnable(``UdpEchoClientApplication'', LOG_LEVEL_INFO);
+      LogComponentEnable(``UdpEchoServerApplication'', LOG_LEVEL_INFO);
+    }
 @end verbatim
 
 Just as in all of the previous examples, the next step is to create two nodes
@@ -692,8 +780,8 @@
 @end verbatim
 
 Next, we see an old friend.  We instantiate a @code{PointToPointHelper} and 
-set the associated default attributes so that we create a five megabit per 
-second transmitter on devices created using the helper and a two millisecond 
+set the associated default @code{Attributes} so that we create a five megabit 
+per second transmitter on devices created using the helper and a two millisecond 
 delay on channels created by the helper.  We then @code{Intall} the devices
 on the nodes and the channel between them.
 
@@ -721,8 +809,8 @@
 point-to-point device and a CSMA device.  We then create a number of ``extra''
 nodes that compose the remainder of the CSMA network.
 
-We then instantiate a @code{CsmaHelper} and set its attributes as we did in
-the previous example.  We create a @code{NetDeviceContainer} to keep track of
+We then instantiate a @code{CsmaHelper} and set its @code{Attributes} as we did
+in the previous example.  We create a @code{NetDeviceContainer} to keep track of
 the created CSMA net devices and then we @code{Install} CSMA devices on the 
 selected nodes.
 
@@ -775,7 +863,6 @@
   wifi.SetRemoteStationManager ("ns3::AarfWifiManager");
 @end verbatim
 
-
 The @code{SetRemoteStationManager} method tells the helper the type of 
 rate control algorithm to use.  Here, it is asking the helper to use the AARF
 algorithm --- details are, of course, available in Doxygen.
@@ -795,8 +882,8 @@
 layer implementation.  The particular kind of MAC layer is specified by
 @code{Attribute} as being of the "ns3::NqstaWifiMac" type.  This means that 
 the MAC will use a ``non-QoS station'' (nqsta) state machine.  Finally, the 
-``ActiveProbing'' attribute is set to false.  This means that probe requests
-will not be sent by MACs created by this helper.
+``ActiveProbing'' @code{Attribute} is set to false.  This means that probe
+requests will not be sent by MACs created by this helper.
 
 Once all the station-specific parameters are fully configured, both at the
 MAC and PHY layers, we can invoke our now-familiar @code{Install} method to 
@@ -821,11 +908,11 @@
 
 In this case, the @code{WifiHelper} is going to create MAC layers of the 
 ``ns3::NqapWifiMac'' (Non-Qos Access Point) type.  We set the 
-``BeaconGeneration'' attribute to true and also set an interval between 
+``BeaconGeneration'' @code{Attribute} to true and also set an interval between 
 beacons of 2.5 seconds.
 
 The next lines create the single AP which shares the same set of PHY-level
-attributes (and channel) as the stations:
+@code{Attributes} (and channel) as the stations:
 
 @verbatim
   NetDeviceContainer apDevices;
@@ -835,8 +922,8 @@
 Now, we are going to add mobility models.  We want the STA nodes to be mobile,
 wandering around inside a bounding box, and we want to make the AP node 
 stationary.  We use the @code{MobilityHelper} to make this easy for us.
-First, we instantiate a @code{MobilityHelper} object and set some attributes
-controlling the ``position allocator'' functionality.
+First, we instantiate a @code{MobilityHelper} object and set some 
+@code{Attributes} controlling the ``position allocator'' functionality.
 
 @verbatim
   MobilityHelper mobility;
@@ -873,10 +960,10 @@
 
 We want the access point to remain in a fixed position during the simulation.
 We accomplish this by setting the mobility model for this node to be the 
-@code{ns3::StaticMobilityModel}:
+@code{ns3::ConstantPositionMobilityModel}:
 
 @verbatim
-  mobility.SetMobilityModel ("ns3::StaticMobilityModel");
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
   mobility.Install (wifiApNode);
 @end verbatim
 
@@ -960,18 +1047,20 @@
   Simulator::Stop (Seconds (10.0));
 @end verbatim
 
-We use the same trick as in the @code{second.cc} script to only generate 
-pcap traces from the nodes we find interesting.  Note that we use the same
-``formula'' to get pcap tracing enabled on Wifi devices as we did on the
-CSMA and point-to-point devices.
+We create just enough tracing to cover all three networks:
 
 @verbatim
-  WifiHelper::EnablePcap ("third",
-    wifiStaNodes.Get (nWifi - 1)->GetId (), 0);
-  CsmaHelper::EnablePcap ("third",
-    csmaNodes.Get (nCsma)->GetId (), 0);
+  PointToPointHelper::EnablePcapAll ("third");
+  YansWifiPhyHelper::EnablePcap ("third", apDevices.Get (0));
+  CsmaHelper::EnablePcap ("third", csmaDevices.Get (0), true);
 @end verbatim
 
+These three lines of code will start pcap tracing on both of the point-to-point
+nodes that serves as our backbone, will start a promiscuous (monitor) mode 
+trace on the Wifi network, and will start a promiscuous trace on the CSMA 
+network.  This will let us see all of the traffic with a minimum number of 
+trace files.
+
 Finally, we actually run the simulation, clean up and then exit the program.
 
 @verbatim
@@ -987,22 +1076,20 @@
 repository you would type,
 
 @verbatim
-  cp examples/third.cc scratch/
+  cp examples/third.cc scratch/mythird.cc
   ./waf
-  ./waf --run scratch/third
+  ./waf --run scratch/mythird
 @end verbatim
 
 Since we have set up the UDP echo applications just as we did in the 
 @code{second.cc} script, you will see similar output.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/third
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone-dev/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Sent 1024 bytes to 10.1.2.4
   Received 1024 bytes from 10.1.3.3
   Received 1024 bytes from 10.1.2.4
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Recall that the first message, @code{Sent 1024 bytes to 10.1.2.4} is the 
@@ -1013,74 +1100,123 @@
 @code{Received 1024 bytes from 10.1.2.4} is from the echo client, indicating
 that it has received its echo back from the server.
 
-If you now go and look in the top level directory, you will find two trace 
-files:
-
-@verbatim
-  ~/repos/ns-3-dev > ls *.pcap
-  third-4-0.pcap  third-7-0.pcap
-  ~/repos/ns-3-dev >
-@end verbatim
-
-The file ``third-4-0.pcap'' corresponds to the pcap trace for node four -
-device zero.  This is the CSMA network node that acted as the echo server.
-Take a look at the tcpdump for this device:
+If you now go and look in the top level directory, you will find four trace 
+files, two from node zero and two from node one:
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r third-4-0.pcap -nn -tt
-  reading from file third-4-0.pcap, link-type EN10MB (Ethernet)
-  2.005855 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
-  2.005855 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
-  2.005859 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
-  2.005859 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
-  2.005861 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
-  2.005861 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
+third-0-0.pcap  third-0-1.pcap  third-1-0.pcap  third-1-1.pcap
 @end verbatim
 
-This should be familiar and easily understood.  If you've forgotten, go back 
-and look at the discussion in @code{second.cc}.  This is the same sequence.
+The file ``third-0-0.pcap'' corresponds to the point-to-point device on node
+zero -- the left side of the ``backbone.''  The file ``third-1-0.pcap'' 
+corresponds to the point-to-point device on node one -- the right side of the
+``backbone.''  The file ``third-0-1.pcap'' will be the promiscuous (monitor
+mode) trace from the Wifi network and the file ``third-1-1.pcap'' will be the
+promiscuous trace from the CSMA network.  Can you verify this by inspecting
+the code?
 
-Now, take a look at the other trace file, ``third-7-0.pcap.''  This is the
-trace file for the wireless STA node that acts as the echo client.
+Since the echo client is on the Wifi network, let's start there.  Let's take
+a look at the promiscuous (monitor mode) trace we captured on that network.
+
+@verbatim
+  tcpdump -nn -tt -r third-0-1.pcap
+@end verbatim
+
+You should see some wifi-looking contents you haven't seen here before:
 
 @verbatim
-  ~/repos/ns-3-dev > tcpdump -r third-7-0.pcap -nn -tt
-  reading from file third-7-0.pcap, link-type IEEE802_11 (802.11)
-  0.000146 Beacon (ns-3-ssid) ...
-  H: 0
-  0.000180 Assoc Request (ns-3-ssid) ...
-  0.000336 Acknowledgment RA:00:00:00:00:00:07
-  0.000454 Assoc Response AID(0) :: Succesful
-  0.000514 Acknowledgment RA:00:00:00:00:00:0a
-  0.000746 Assoc Request (ns-3-ssid) ...
-  0.000902 Acknowledgment RA:00:00:00:00:00:09
-  0.001020 Assoc Response AID(0) :: Succesful
-  0.001036 Acknowledgment RA:00:00:00:00:00:0a
-  0.001219 Assoc Request (ns-3-ssid) ...
-  0.001279 Acknowledgment RA:00:00:00:00:00:08
-  0.001478 Assoc Response AID(0) :: Succesful
-  0.001538 Acknowledgment RA:00:00:00:00:00:0a
-  2.000000 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
-  2.000172 Acknowledgment RA:00:00:00:00:00:09
-  2.000318 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
-  2.000581 arp reply 10.1.3.4 is-at 00:00:00:00:00:0a
-  2.000597 Acknowledgment RA:00:00:00:00:00:0a
-  2.000693 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
-  2.002229 Acknowledgment RA:00:00:00:00:00:09
-  2.009663 arp who-has 10.1.3.3 (ff:ff:ff:ff:ff:ff) tell 10.1.3.4
-  2.009697 arp reply 10.1.3.3 is-at 00:00:00:00:00:09
-  2.009869 Acknowledgment RA:00:00:00:00:00:09
-  2.011487 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
-  2.011503 Acknowledgment RA:00:00:00:00:00:0a
-  2.500112 Beacon[|802.11]
-  5.000112 Beacon[|802.11]
-  7.500112 Beacon[|802.11]
-  ~/repos/ns-3-dev >
+  reading from file third-0-1.pcap, link-type IEEE802_11 (802.11)
+  0.000025 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+  0.000263 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+  0.000279 Acknowledgment RA:00:00:00:00:00:07
+  0.000357 Assoc Response AID(0) :: Succesful
+  0.000501 Acknowledgment RA:00:00:00:00:00:0a
+  0.000748 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+  0.000764 Acknowledgment RA:00:00:00:00:00:08
+  0.000842 Assoc Response AID(0) :: Succesful
+  0.000986 Acknowledgment RA:00:00:00:00:00:0a
+  0.001242 Assoc Request () [6.0 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit]
+  0.001258 Acknowledgment RA:00:00:00:00:00:09
+  0.001336 Assoc Response AID(0) :: Succesful
+  0.001480 Acknowledgment RA:00:00:00:00:00:0a
+  2.000112 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
+  2.000128 Acknowledgment RA:00:00:00:00:00:09
+  2.000206 arp who-has 10.1.3.4 (ff:ff:ff:ff:ff:ff) tell 10.1.3.3
+  2.000487 arp reply 10.1.3.4 is-at 00:00:00:00:00:0a
+  2.000659 Acknowledgment RA:00:00:00:00:00:0a
+  2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+  2.002185 Acknowledgment RA:00:00:00:00:00:09
+  2.009771 arp who-has 10.1.3.3 (ff:ff:ff:ff:ff:ff) tell 10.1.3.4
+  2.010029 arp reply 10.1.3.3 is-at 00:00:00:00:00:09
+  2.010045 Acknowledgment RA:00:00:00:00:00:09
+  2.010231 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+  2.011767 Acknowledgment RA:00:00:00:00:00:0a
+  2.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+  5.000000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+  7.500000 Beacon () [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS
+@end verbatim
+
+You can see that the link type is now 802.11 as you would expect.  You can 
+probably understand what is going on and find the IP echo request and response
+packets in this trace.  We leave it as an exercise to completely parse the 
+trace dump.
+
+Now, look at the pcap file of the right side of the point-to-point link,
+
+@verbatim
+  tcpdump -nn -tt -r third-0-0.pcap
 @end verbatim
 
-You can see that the link type is now 802.11 as you would expect.  We leave
-it as an exercise to parse the dump and trace packets across the internetwork.
+Again, you should see some familiar looking contents:
+
+@verbatim
+  reading from file third-0-0.pcap, link-type PPP (PPP)
+  2.002169 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+  2.009771 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+@end verbatim
+
+This is the echo packet going from left to right (from Wifi to CSMA) and back
+again across the point-to-point link.
+
+Now, look at the pcap file of the right side of the point-to-point link,
+
+@verbatim
+  tcpdump -nn -tt -r third-1-0.pcap
+@end verbatim
+
+Again, you should see some familiar looking contents:
+
+@verbatim
+  reading from file third-1-0.pcap, link-type PPP (PPP)
+  2.005855 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+  2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+@end verbatim
+
+This is also the echo packet going from left to right (from Wifi to CSMA) and 
+back again across the point-to-point link with slightly different timings
+as you might expect.
+
+The echo server is on the CSMA network, let's look at the promiscuous trace 
+there:
+
+@verbatim
+  tcpdump -nn -tt -r third-1-1.pcap
+@end verbatim
+
+You should see some familiar looking contents:
+
+@verbatim
+  reading from file third-1-1.pcap, link-type EN10MB (Ethernet)
+  2.005855 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1
+  2.005877 arp reply 10.1.2.4 is-at 00:00:00:00:00:06
+  2.005877 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024
+  2.005980 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4
+  2.005980 arp reply 10.1.2.1 is-at 00:00:00:00:00:03
+  2.006084 IP 10.1.2.4.9 > 10.1.3.3.49153: UDP, length 1024
+@end verbatim
+
+This should be easily understood.  If you've forgotten, go back and look at
+the discussion in @code{second.cc}.  This is the same sequence.
 
 Now, we spent a lot of time setting up mobility models for the wireless network
 and so it would be a shame to finish up without even showing that the STA
@@ -1088,13 +1224,13 @@
 @code{MobilityModel} course change trace source.  This is usually considered
 a fairly advanced topic, but let's just go for it.
 
-As mentioned in the Tweaking Ns-3 section, the @command{ns-3} tracing system 
+As mentioned in the ``Tweaking ns-3'' section, the @command{ns-3} tracing system 
 is divided into trace sources and trace sinks, and we provide functions to 
 connect the two.  We will use the mobility model predefined course change 
 trace source to originate the trace events.  We will need to write a trace 
 sink to connect to that source that will display some pretty information for 
 us.  Despite its reputation as being difficult, it's really quite simple.
-Just before the main program of the @code{scratch/third.cc} script, add the 
+Just before the main program of the @code{scratch/mythird.cc} script, add the 
 following function:
 
 @verbatim
@@ -1150,41 +1286,40 @@
 they happen.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/third
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Build finished successfully (00:00:01)
   /NodeList/7/$ns3::MobilityModel/CourseChange x = 10, y = 0
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.1304, y = 0.493761
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.70417, y = 1.39837
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.94799, y = 2.05274
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.82597, y = 1.57404
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.3003, y = 0.723347
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.41539, y = -0.811313
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.46199, y = -1.11303
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.52738, y = -1.46869
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.67099, y = -1.98503
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.6835, y = -2.14268
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.70932, y = -1.91689
   Sent 1024 bytes to 10.1.2.4
   Received 1024 bytes from 10.1.3.3
   Received 1024 bytes from 10.1.2.4
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.74083, y = 1.62109
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.00146, y = 0.655647
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.98731, y = 0.823279
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.50206, y = 1.69766
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.68108, y = 2.26862
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.25992, y = 1.45317
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.55655, y = 0.742346
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.21992, y = 1.68398
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.81273, y = 0.878638
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.83171, y = 1.07256
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.60027, y = 0.0997156
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.45367, y = 0.620978
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.68484, y = 1.26043
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.53659, y = 0.736479
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.51876, y = 0.548502
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.89778, y = 1.47389
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.98984, y = 1.893
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 9.91524, y = 1.51402
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.98761, y = 1.14054
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.16617, y = 0.570239
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.02954, y = 1.56086
-  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.09551, y = 2.55868
-  ~/repos/ns-3-dev >
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.53175, y = -2.48576
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.58021, y = -2.17821
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.18915, y = -1.25785
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.7572, y = -0.434856
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.62404, y = 0.556238
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 4.74127, y = 1.54934
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 5.73934, y = 1.48729
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.18521, y = 0.59219
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.58121, y = 1.51044
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.27897, y = 2.22677
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.42888, y = 1.70014
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.40519, y = 1.91654
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.51981, y = 1.45166
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.34588, y = 2.01523
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.81046, y = 2.90077
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 6.89186, y = 3.29596
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.46617, y = 2.47732
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.05492, y = 1.56579
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 8.00393, y = 1.25054
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.00968, y = 1.35768
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.33503, y = 2.30328
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.18682, y = 3.29223
+  /NodeList/7/$ns3::MobilityModel/CourseChange x = 7.96865, y = 2.66873
 @end verbatim
 
 If you are feeling brave, there is a list of all trace sources in the 
@@ -1194,7 +1329,8 @@
 sources.''  You may find it interesting to try and hook some of these 
 traces yourself.  Additionally in the ``Modules'' documentation, there is
 a link to ``The list of all attributes.''  You can set the default value of 
-any of these attributes via the command line as we have previously discussed.
+any of these @code{Attributes} via the command line as we have previously 
+discussed.
 
 We have just scratched the surface of @command{ns-3} in this tutorial, but we 
 hope we have covered enough to get you started doing useful work.
--- a/doc/tutorial/conceptual-overview.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/conceptual-overview.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -362,21 +362,6 @@
 INFO level for echo clients and servers.  This will result in the application
 printing out messages as packets are sent and received during the simulation.
 
-The next line of code is used to give a fixed seed to the random number 
-generators so that they will generate repeatable results.  In the example
-programs, it allows us to thouroughly document the output of the trace files
-in a consistent way.  Having a fixed seed also allows us to use the examples 
-in our regression testing framework.
-
-@verbatim
-  RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
-@end verbatim
-
-Random variables are very important in understanding how to get repeatable
-results, so you are encouraged to read the Doxygen and manual sections to
-understand what is going on there.  For us, the main concern is in making 
-random backoff algorithms consistent across runs.
-
 Now we will get directly to the business of creating a topology and running 
 a simulation.  We use the topology helper objects to make this job as
 easy as possible.
@@ -439,7 +424,7 @@
     pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
 @end verbatim
 
-The first line 
+The first line,
 
 @verbatim
     PointToPointHelper pointToPoint;
@@ -461,12 +446,12 @@
 If you look at the Doxygen for class @code{ns3::PointToPointNetDevice} and 
 find the documentation for the @code{GetTypeId} method, you will find a list
 of  @code{Attributes} defined for the device.  Among these is the ``DataRate''
-attribute.  Most user-visible @command{ns-3} objects have similar lists of 
-attributes.  We use this mechanism to easily configure simulations without
+@code{Attribute}.  Most user-visible @command{ns-3} objects have similar lists of 
+@code{Attributes}.  We use this mechanism to easily configure simulations without
 recompiling as you will see in a following section.
 
 Similar to the ``DataRate'' on the @code{PointToPointNetDevice} you will find a
-``Delay'' attribute associated with the @code{PointToPointChannel}.  The 
+``Delay'' @code{Attribute} associated with the @code{PointToPointChannel}.  The 
 final line,
 
 @verbatim
@@ -502,8 +487,9 @@
 two for a point-to-point link) a @code{PointToPointNetDevice} is created and 
 saved in the device container.  A @code{PointToPointChannel} is created and 
 the two @code{PointToPointNetDevices} are attached.  When objects are created
-by the @code{PointToPointHelper}, the attributes previously set in the helper
-are used to initialize the corresponding attributes in the created objects.
+by the @code{PointToPointHelper}, the @code{Attributes} previously set in the 
+helper are used to initialize the corresponding @code{Attributes} in the 
+created objects.
 
 After executing the @code{pointToPoint.Install (nodes)} call we will have
 two nodes, each with an installed point-to-point net device and a 
@@ -590,13 +576,13 @@
 The first line of code in the above snippet declares the 
 @code{UdpEchoServerHelper}.  As usual, this isn't the application itself, it
 is an object used to help us create the actual applications.  One of our 
-conventions is to place required attributes in the helper constructor.  In this
-case, the helper can't do anything useful unless it is provided with a port
-number that the client also knows about.  Rather than just picking one and
-hoping it all works out, we require the port number as a parameter to the 
+conventions is to place required @code{Attributes} in the helper constructor.
+In this case, the helper can't do anything useful unless it is provided with
+a port number that the client also knows about.  Rather than just picking one 
+and hoping it all works out, we require the port number as a parameter to the 
 constructor.  The constructor, in turn, simply does a @code{SetAttribute}
-with the passed value.  You can, if desired, set the ``Port'' attribute to
-another value later.
+with the passed value.  You can, if desired, set the ``Port'' @code{Attribute}
+to another value later.
 
 Similar to many other helper objects, the @code{UdpEchoServerHelper} object 
 has an @code{Install} method.  It is the execution of this method that actually
@@ -649,12 +635,12 @@
     clientApps.Stop (Seconds (10.0));
 @end verbatim
 
-For the echo client, however, we need to set five different attributes.  The 
-first two attributes are set during construction of the 
+For the echo client, however, we need to set five different @code{Attributes}.
+The first two @code{Attributes} are set during construction of the 
 @code{UdpEchoClientHelper}.  We pass parameters that are used (internally to
-the helper) to set the ``RemoteAddress'' and ``RemotePort'' attributes in
-accordance with our convention to make required attributes parameters in the 
-helper constructors.  
+the helper) to set the ``RemoteAddress'' and ``RemotePort'' @code{Attributes}
+in accordance with our convention to make required @code{Attributes} parameters
+in the helper constructors.  
 
 Recall that we used an @code{Ipv4InterfaceContainer} to keep track of the IP 
 addresses we assigned to our devices.  The zeroth interface in the 
@@ -666,12 +652,12 @@
 to be  the IP address assigned to the node on which the server resides.  We 
 also tell it to arrange to send packets to port nine.
 
-The ``MaxPackets'' attribute tells the client the maximum number of packets 
-we allow it to send during the simulation.  The ``Interval'' attribute tells
-the client how long to wait between packets, and the ``PacketSize'' attribute
-tells the client how large its packet payloads should be.  With this 
-particular combination of attributes, we are telling the client to send one 
-1024-byte packet.
+The ``MaxPackets'' @code{Attribute} tells the client the maximum number of 
+packets we allow it to send during the simulation.  The ``Interval'' 
+@code{Attribute} tells the client how long to wait between packets, and the
+``PacketSize'' @code{Attribute} tells the client how large its packet payloads
+should be.  With this particular combination of @code{Attributes}, we are 
+telling the client to send one 1024-byte packet.
 
 Just as in the case of the echo server, we tell the echo client to @code{Start}
 and @code{Stop}, but here we start the client one second after the server is
@@ -738,34 +724,40 @@
 the @code{scratch} directory.
 
 @verbatim
-  ~/repos/ns-3-dev > cp examples/first.cc scratch/
+  ~/repos/ns-3-dev > cp examples/first.cc scratch/myfirst.cc
 @end verbatim
 
-and then build it using waf,
+Now build your first example script using waf:
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  [467/511] cxx: scratch/first.cc -> build/debug/scratch/first_1.o
-  [468/511] cxx: scratch/multiple-sources/simple-main.cc -> build/debug/scratch/multiple-sources/simple-main_2.o
-  [469/511] cxx: scratch/multiple-sources/simple-simulation.cc -> build/debug/scratch/multiple-sources/simple-simulation_2.o
-  [470/511] cxx: scratch/simple.cc -> build/debug/scratch/simple_3.o
-  [508/511] cxx_link: build/debug/scratch/first_1.o -> build/debug/scratch/first
-  Compilation finished successfully 
-  ~/repos/ns-3-dev >
+  ./waf
+@end verbatim
+
+You should see messages reporting that your @code{myfirst} example was built
+successfully.
+
+@verbatim
+  Entering directory `repos/ns-3-allinone-dev/ns-3-dev/build'
+  [563/648] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o
+  [646/648] cxx_link: build/debug/scratch/myfirst_3.o -> build/debug/scratch/myfirst
+  Build finished successfully (00:00:02)
 @end verbatim
 
 You can now run the example (note that if you build your program in the scratch
 directory you must run it out of the scratch directory):
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  ./waf --run scratch/myfirst
+@end verbatim
+
+You should see some output:
+
+@verbatim
+  Entering directory `repos/ns-3-allinone-dev/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Sent 1024 bytes to 10.1.1.2
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.1.2
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Here you see that the build system checks to make sure that the file has been
@@ -793,38 +785,42 @@
 
 The top-level directory for one of our @emph{repositories} will look 
 something like:
+
 @verbatim
-drwxr-xr-x  [up]   
-drwxr-xr-x         doc             manifest 
-drwxr-xr-x         examples        manifest 
-drwxr-xr-x         ns3             manifest 
-drwxr-xr-x         regression      manifest 
-drwxr-xr-x         samples         manifest 
-drwxr-xr-x         scratch         manifest 
-drwxr-xr-x         src             manifest 
-drwxr-xr-x         tutorial        manifest 
-drwxr-xr-x         utils           manifest 
--rw-r--r-- 135     .hgignore       file | revisions | annotate 
--rw-r--r-- 891     .hgtags         file | revisions | annotate 
--rw-r--r-- 441     AUTHORS         file | revisions | annotate 
--rw-r--r-- 17987   LICENSE         file | revisions | annotate 
--rw-r--r-- 4948    README          file | revisions | annotate 
--rw-r--r-- 4917    RELEASE_NOTES   file | revisions | annotate 
--rw-r--r-- 7       VERSION         file | revisions | annotate 
--rwxr-xr-x 99143   waf             file | revisions | annotate 
--rwxr-xr-x 28      waf.bat         file | revisions | annotate 
--rw-r--r-- 30584   wscript         file | revisions | annotate 
+drwxr-xr-x   [up]   
+drwxr-xr-x   bindings python                          files 
+drwxr-xr-x   doc                                      files 
+drwxr-xr-x   examples                                 files 
+drwxr-xr-x   ns3                                      files 
+drwxr-xr-x   regression                               files 
+drwxr-xr-x   samples                                  files 
+drwxr-xr-x   scratch                                  files 
+drwxr-xr-x   src                                      files 
+drwxr-xr-x   utils                                    files 
+-rw-r--r-- 2009-03-24 00:51 -0700 505   .hgignore     file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 1682  .hgtags       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 686   AUTHORS       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 14893 CHANGES.html  file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 17987 LICENSE       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 3742  README        file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 13505 RELEASE_NOTES file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 6     VERSION       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 9257  regression.py file | revisions | annotate 
+-rwxr-xr-x 2009-03-24 00:51 -0700 81285 waf           file | revisions | annotate 
+-rwxr-xr-x 2009-03-24 00:51 -0700 28    waf.bat       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 26270 wscript       file | revisions | annotate 
+-rw-r--r-- 2009-03-24 00:51 -0700 6636  wutils.py     file | revisions | annotate 
 @end verbatim
 
 The source code is mainly in the @code{src} directory.  You can view source
-code by clicking on the @code{manifest} link to the right of the directory 
-name.  If you click on the @code{manifest} link to the right of the src
-directory you will find a subdirectory.  If you click on the @code{manifest}
-link next to the @code{core} subdirectory in under @code{src}, you will find
-a list of files.  The first file you will find is @code{assert.h}.  If you 
-click on the @code{file} link, you will be sent to the source file for
-@code{assert.h}.
+code either by clicking on the directory name or by clicking on the @code{files}
+link to the right of the directory name.  If you click on the @code{src}
+directory you be taken to the lising of the @code{src} subdirectories.  If you 
+click on @code{core} subdirectory, you will find a list of files.  The first file
+you will find (as of this writing) is @code{abort.h}.  If you 
+click on @code{abort.h} link, you will be sent to the source file for @code{abort.h}.
 
 Our example scripts are in the @code{examples} directory.  The source code for
 the helpers we have used in this chapter can be found in the 
-@code{src/helpers} directory.
+@code{src/helpers} directory.  Feel free to poke around in the directory tree to
+get a feel for what is there and the style of @command{ns-3} programs.
--- a/doc/tutorial/getting-started.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/getting-started.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -44,78 +44,228 @@
 
 @cindex tarball
 The @command{ns-3} code is available in Mercurial repositories on the server
-code.nsnam.org.  You can download a tarball release at
+code.nsnam.org.  You can also download a tarball release at
 @uref{http://www.nsnam.org/releases/}, or you can work with repositories
-using Mercurial.
+using Mercurial.  We recommend using Mercurial unless there's a good reason
+not to.  See the end of this section for instructions on how to get a tarball
+release.
+
+@cindex repository
+The simplest way to get started using Mercurial repositories is to use the
+@code{ns-3-allinone} environment.  This is a set of scripts that manages the 
+downloading and building of various subystems of @command{ns-3} for you.  We 
+recommend that you begin your @command{ns-3} adventures in this environment
+as it can really simplify your life at this point.
+
+@subsection Downloading ns-3 Using Mercurial
+One practice is to create a directory called @code{repos} in one's home 
+directory under which one can keep local Mercurial repositories.  
+@emph{Hint:  we will assume you do this later in the tutorial.}  If you adopt
+that approach, you can get a copy of @code{ns-3-allinone} by typing the 
+following into your Linux shell (assuming you have installed Mercurial):
+
+@verbatim
+  cd
+  mkdir repos
+  cd repos
+  hg clone http://code.nsnam.org/ns-3-allinone
+@end verbatim
+
+As the hg (Mercurial) command executes, you should see something like the 
+following displayed,
+
+@verbatim
+  destination directory: ns-3-allinone
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 26 changesets with 40 changes to 7 files
+  7 files updated, 0 files merged, 0 files removed, 0 files unresolved
+@end verbatim
+
+After the clone command completes, you should have a directory called 
+@code{ns-3-allinone} under your @code{~/repos} directory, the contents of which should 
+look something like the following:
+
+@verbatim
+  build.py*  constants.py  dist.py*  download.py*  README  util.py
+@end verbatim
+
+Notice that you really just downloaded some Python scripts.  The next step
+will be to use those scripts to download and build the @command{ns-3}
+distribution of your choice.
 
 @cindex repository
 If you go to the following link: @uref{http://code.nsnam.org/},
 you will see a number of repositories.  Many are the private repositories of
 the @command{ns-3} development team.  The repositories of interest to you will
-be prefixed with ``ns-3''.  The current development snapshot (unreleased)
-of @command{ns-3} may be found at: @uref{http://code.nsnam.org/ns-3-dev/}.
-Official releases of @command{ns-3} will be numbered as @code{ns-3.<release>}
-with any required  hotfixes added as minor release numbers.  For example, a 
-second hotfix to a hypothetical release nine of @command{ns-3} would be
-numbered @code{ns-3.9.2}.
+be prefixed with ``ns-3''.  Official releases of @command{ns-3} will be 
+numbered as @code{ns-3.<release>.<hotfix>}.  For example, a second hotfix to a
+still hypothetical release nine of @command{ns-3} would be numbered as
+@code{ns-3.9.2}.
+
+We have had a regression testing framework in place since the first release.
+For each release, a set of output files that define ``good behavior'' are saved.
+These known good output files are called reference traces and are associated 
+with a given release by name.  For example, in @uref{http://code.nsnam.org/}
+you will find a repository named @code{ns-3.1} which is the first stable release
+of @command{ns-3}.  You will also find a separate repository named 
+@code{ns-3.1-ref-traces} that holds the reference traces for the @code{ns-3.1}
+release.  It is crucial to keep these files consistent if you want to do any
+regression testing of your repository.  This is a good idea to do at least once
+to verify everything has built correctly.
 
 The current development snapshot (unreleased) of @command{ns-3} may be found 
-at:  @uref{http://code.nsnam.org/ns-3-dev/}.  The developers attempt to keep
-this repository in a consistent, working state but it is a development area 
-with unreleased code present, so you may want to consider staying with an 
-official release if you do not need newly-introduced features.
+at @uref{http://code.nsnam.org/ns-3-dev/} and the associated reference traces
+may be found at @uref{http://code.nsnam.org/ns-3-dev-ref-traces/}.  The 
+developers attempt to keep these repository in consistent, working states but
+they are in a development area with unreleased code present, so you may want 
+to consider staying with an official release if you do not need newly-
+introduced features.
 
 Since the release numbers are going to be changing, I will stick with 
 the more constant ns-3-dev here in the tutorial, but you can replace the 
-string ``ns-3-dev'' with your choice of release (e.g., ns-3.2) in the text 
-below.  You can find the latest version  of the code either by inspection of 
-the repository list or by going to the ``Getting Started'' web page and 
-looking for the latest release identifier.
+string ``ns-3-dev'' with your choice of release (e.g., ns-3.4 and 
+ns-3.4-ref-traces) in the text below.  You can find the latest version  of the
+code either by inspection of the repository list or by going to the ``Getting 
+Started'' web page and looking for the latest release identifier.
 
-One practice is to create a directory called @code{repos} in one's home 
-directory under which one can keep local Mercurial repositories.  
-@emph{Hint:  we will assume you do this later in the tutorial.}  If you adopt
-that approach, you can get a copy of the development version of 
-@command{ns-3} by typing the following into your Linux shell (assuming you 
-have installed Mercurial):
+Go ahead and change into the @code{ns-3-allinone} directory you created when
+you cloned that repository.  We are now going to use the @code{download.py} 
+script to pull down the various pieces of @command{ns-3} you will be using/
+
+Go ahead and type the following into your shell (remember you can substitute
+the name of your chosen release number instead of @code{ns-3-dev} -- like
+@code{"ns-3.4"} and @code{"ns-3.4-ref-traces"} if you want to work with a 
+stable release).
 
 @verbatim
-  cd
-  mkdir repos
-  cd repos
-  hg clone http://code.nanam.org/ns-3-dev
+  ./download.py -n ns-3-dev -r ns-3-dev-ref-traces
 @end verbatim
 
 As the hg (Mercurial) command executes, you should see something like the 
 following,
 
 @verbatim
-  destination directory: ns-3-dev
+      #
+      # Get NS-3
+      #
+
+  Cloning ns-3 branch
+   =>  hg clone http://code.nsnam.org/ns-3-dev ns-3-dev
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4292 changesets with 15368 changes to 1671 files
+  823 files updated, 0 files merged, 0 files removed, 0 files unresolved
+@end verbatim
+
+This is output by the download script as it fetches the actual @code{ns-3}
+code from the repository.  Next, you should see something like,
+
+@verbatim
+      #
+      # Get the regression traces
+      #
+  
+  Synchronizing reference traces using Mercurial.
+   =>  hg clone http://code.nsnam.org/ns-3-dev-ref-traces ns-3-dev-ref-traces
   requesting all changes
   adding changesets
   adding manifests
   adding file changes
-  added 3276 changesets with 12301 changes to 1353 files
-  594 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  added 79 changesets with 1102 changes to 222 files
+  206 files updated, 0 files merged, 0 files removed, 0 files unresolved
 @end verbatim
 
-After the clone command completes, you should have a directory called 
-ns-3-dev under your @code{~/repos} directory, the contents of which should 
-look something like the following:
+This is the download script fetching the reference trace files for you.
+The download script is smart enough to know that on some platforms various
+pieces of ns-3 are not supported.  On your platform you may not see some
+of these pieces come down.  However, on most platforms, the process should
+continue with something like,
+
+@verbatim
+      #
+      # Get PyBindGen
+      #
+  
+  Required pybindgen version:  0.10.0.630
+  Trying to fetch pybindgen; this will fail if no network connection is available.  Hit Ctrl-C to skip.
+   =>  bzr checkout -rrevno:630 https://launchpad.net/pybindgen pybindgen
+  Fetch was successful.
+@end verbatim
+
+This was the download script getting the Python bindings generator for you.
+Next you should see (modulo platform variations) something along the lines of,
 
 @verbatim
-  AUTHORS  examples/  README         samples/  utils/   waf.bat*
-  build/   LICENSE    regression/    scratch/  VERSION  wscript
-  doc/     ns3/       RELEASE_NOTES  src/      waf*
+      #
+      # Get NSC
+      #
+  
+  Required NSC version:  nsc-0.5.0
+  Retrieving nsc from https://secure.wand.net.nz/mercurial/nsc
+   =>  hg clone https://secure.wand.net.nz/mercurial/nsc nsc
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 270 changesets with 17375 changes to 14991 files
+  10614 files updated, 0 files merged, 0 files removed, 0 files unresolved 
+@end verbatim
+
+This part of the process is the script downloading the Network Simulation
+Cradle for you.
+
+After the clone command completes, you should have several new directories
+under @code{~/repos/ns-3-allinone}:
+
+@verbatim
+  build.py*     constants.pyc  download.py*  ns-3-dev-ref-traces/  pybindgen/  util.py
+  constants.py  dist.py*       ns-3-dev/     nsc/                  README      util.pyc
 @end verbatim
 
-Similarly, if working from a released version instead, you can simply
+Go ahead and change into @code{ns-3-dev} under your @code{~/repos/ns-3-allinone} 
+directory.  You should see something like the following there:
+
+@verbatim
+  AUTHORS       examples/  regression/    scratch/  waf*
+  bindings/     LICENSE    regression.py  src/      waf.bat*
+  CHANGES.html  ns3/       RELEASE_NOTES  utils/    wscript
+  doc/          README     samples/       VERSION   wutils.py
+@end verbatim
+
+You are now ready to build the @command{ns-3} distribution.
+
+@subsection Downloading ns-3 Using a Tarball
+The process for downloading @command{ns-3} via tarball is simpler than the
+Mercurial process since all of the pieces are pre-packaged for you.  You just
+have to pick a release, download it and decompress it.
+
+As mentioned above, one practice is to create a directory called @code{repos}
+in one's home directory under which one can keep local Mercurial repositories.
+One could also keep a @code{tarballs} directory.  @emph{Hint:  the tutorial
+will assume you downloaded into a @code{repos} directory, so remember the
+placekeeper.}  If you adopt the @code{tarballs} directory approach, you can 
+get a copy of a release by typing the following into your Linux shell 
+(substitute the appropriate version numbers, of course):
+
 @verbatim
   cd
-  mkdir repos
-  wget http://www.nsnam.org/releases/ns-3.2.tar.bz2
-  bunzip2 ns-3.2.tar.bz2
-  tar xvf ns-3.2.tar
+  mkdir tarballs
+  cd tarballs
+  wget http://www.nsnam.org/releases/ns-allinone-3.4.tar.bz2
+  tar xjf ns-3.4.tar.bz2
+@end verbatim 
+
+If you change into the directory @code{ns-allinone-3.4} you should see a
+number of files:
+
+@verbatim
+build.py*     ns-3.4-RC2/             nsc-0.5.0/             util.py
+constants.py  ns-3.4-RC2-ref-traces/  pybindgen-0.10.0.630/
 @end verbatim 
 
 You are now ready to build the @command{ns-3} distribution.
@@ -127,19 +277,61 @@
 @node Building ns-3
 @section Building ns-3
 
+@subsection Building with build.py
+@cindex building with build.py
+The first time you build the @command{ns-3} project you should build using the
+@command{allinone} environment.  This will get the project configured for you
+in the most commonly useful way.
+
+Change into the directory you created in the download section above.  If you
+downloaded using Mercurial you should have a directory called 
+@code{ns-3-allinone} under your @code{~/repos} directory.  If you downloaded
+using a tarball you should have a directory called something like 
+@code{ns-3-allinone-3.4} under your @code{~/tarballs} directory.  Take a deep
+breath and type the following:
+
+@verbatim
+  ./build.py
+@end verbatim
+
+You will see lots of typical compiler output messages displayed as the build
+script builds the various pieces you downloaded.  Eventually you should see the
+following magic words:
+
+@verbatim
+  Build finished successfully (00:02:37)
+  Leaving directory `./ns-3-dev'
+@end verbatim
+
+Once the project has built you can say goodbye to your old friends, the 
+@code{ns-3-allinone} scripts.  You got what you needed from them and will now 
+interact directly with Waf and we do it in the @code{ns-3-dev} directory and
+not in the @code{ns-3-allinone} directory.  Go ahead and change into the 
+@code{ns-3-dev} directory (or the directory for the appropriate release you
+downloaded.
+
+@verbatim
+  cd ns-3-dev
+@end verbatim
+
+@subsection Building with Waf
 @cindex building with Waf
 @cindex configuring Waf
 @cindex building debug version with Waf
 @cindex compiling with Waf
 @cindex unit tests with Waf
 @cindex regression tests with Waf
-We use Waf to build the @command{ns-3} project.  The first thing you will need
-to do is to configure the build.  For reasons that will become clear later, 
-we are going to work with debug builds in the tutorial.  To explain to Waf 
-that it should do debug builds you will need to execute the following command,
+We use Waf to configure and build the @command{ns-3} project.  It's not 
+strictly required at this point, but it will be valuable to take a slight
+detour and look at how to make changes to the configuration of the project.
+Probably the most useful configuration change you can make will be to 
+build the optimized version of the code.  By default you have configured
+your project to build the debug version.  Let's tell the project to do
+make an optimized build.  To explain to Waf that it should do optimized
+builds you will need to execute the following command,
 
 @verbatim
-  ./waf -d debug configure
+  ./waf -d optimized configure
 @end verbatim
 
 This runs Waf out of the local directory (which is provided as a convenience
@@ -147,57 +339,82 @@
 output that looks similar to the following,
 
 @verbatim
-Checking for program g++                 : ok /usr/bin/g++ 
-Checking for compiler version            : ok Version 4.0.1 
-Checking for program cpp                 : ok /usr/bin/cpp 
-Checking for program ar                  : ok /usr/bin/ar 
-Checking for program ranlib              : ok /usr/bin/ranlib 
-Checking for compiler could create programs : ok  
-Checking for compiler could create shared libs : ok  
-Checking for compiler could create static libs : ok  
-Checking for flags -O2 -DNDEBUG                : ok  
-Checking for flags -g -DDEBUG                  : ok  
-Checking for flags -g3 -O0 -DDEBUG             : ok  
-Checking for flags -Wall                       : ok  
-Checking for g++                               : ok  
-Checking for -Wno-error=deprecated-declarations compilation flag support : no 
-Checking for header stdlib.h                   : ok  
-Checking for header stdlib.h                   : ok  
-Checking for header signal.h                   : ok  
-Checking for library rt                        : not found 
-Checking for header pthread.h                  : ok  
-Checking for high precision time implementation: 128-bit integer 
-Checking for header stdint.h                   : ok  
-Checking for header inttypes.h                 : ok  
-Checking for header sys/inttypes.h             : not found 
-Checking for package gtk+-2.0 >= 2.12          : not found 
-Checking for library sqlite3                   : ok  
-Checking for package goocanvas gthread-2.0     : not found 
-Checking for program python                    : ok /usr/local/bin/python 
-Checking for Python version >= 2.3             : ok 2.4.3 
-Checking for library python2.4                 : not found 
-Checking for library python2.4                 : not found 
-Checking for library python24                  : not found 
-Checking for program python2.4-config          : not found 
-Checking for header Python.h                   : not found 
-Checking for program diff                      : ok /usr/bin/diff 
-Checking for program hg                        : ok /opt/local/bin/hg 
+Checking for program g++                 : ok /usr/bin/g++
+Checking for program cpp                 : ok /usr/bin/cpp
+Checking for program ar                  : ok /usr/bin/ar
+Checking for program ranlib              : ok /usr/bin/ranlib
+Checking for g++                         : ok
+Checking for program pkg-config          : ok /usr/bin/pkg-config
+Checking for regression reference traces  : ok ../ns-3-dev-ref-traces (guessed)
+Checking for -Wno-error=deprecated-declarations support : yes
+Checking for header stdlib.h                            : ok
+Checking for header signal.h                            : ok
+Checking for header pthread.h                           : ok
+Checking for high precision time implementation         : 128-bit integer
+Checking for header stdint.h                            : ok
+Checking for header inttypes.h                          : ok
+Checking for header sys/inttypes.h                      : not found
+Checking for library rt                                 : ok
+Checking for header netpacket/packet.h                  : ok
+Checking for header linux/if_tun.h                      : ok
+Checking for pkg-config flags for GTK_CONFIG_STORE      : ok
+Package libxml-2.0 was not found in the pkg-config search path.
+Perhaps you should add the directory containing `libxml-2.0.pc'
+to the PKG_CONFIG_PATH environment variable
+No package 'libxml-2.0' found
+Checking for pkg-config flags for LIBXML2               : not found
+Checking for library sqlite3                            : ok
+Checking for NSC location                               : ok ../nsc (guessed)
+Checking for library dl                                 : ok
+Checking for NSC supported architecture x86_64          : ok
+Package goocanvas was not found in the pkg-config search path.
+Perhaps you should add the directory containing `goocanvas.pc'
+to the PKG_CONFIG_PATH environment variable
+No package 'goocanvas' found
+Checking for pkg-config flags for MOBILITY_VISUALIZER   : not found
+Checking for program python                             : ok /usr/bin/python
+Checking for Python version >= 2.3                      : ok 2.5.2
+Checking for library python2.5                          : ok
+Checking for program python2.5-config                   : ok /usr/bin/python2.5-config
+Checking for header Python.h                            : ok
+Checking for -fvisibility=hidden support                : yes
+Checking for pybindgen location                         : ok ../pybindgen (guessed)
+Checking for Python module pybindgen                    : ok
+Checking for pybindgen version                          : ok 0.10.0.630
+Checking for Python module pygccxml                     : ok
+Checking for pygccxml version                           : ok 0.9.5
+Checking for program gccxml                             : ok /usr/local/bin/gccxml
+Checking for gccxml version                             : ok 0.9.0
+Checking for program sudo                               : ok /usr/bin/sudo
+Checking for program hg                                 : ok /usr/bin/hg
+Checking for program valgrind                           : ok /usr/bin/valgrind
 ---- Summary of optional NS-3 features:
-Threading Primitives        : enabled
-Real Time Simulator         : enabled
-GtkConfigStore              : not enabled (library 'gtk+-2.0 >= 2.12' not found)
-SQlite stats data output    : enabled
-Network Simulation Cradle   : not enabled (--enable-nsc configure option not given)
-Python Bindings             : not enabled (Python development headers not found.)
-Configuration finished successfully; project is now ready to build. 
+Threading Primitives          : enabled
+Real Time Simulator           : enabled
+Emulated Net Device           : enabled
+Tap Bridge                    : enabled
+GtkConfigStore                : enabled
+XmlIo                         : not enabled (library 'libxml-2.0 >= 2.7' not found)
+SQlite stats data output      : enabled
+Network Simulation Cradle     : enabled
+Python Bindings               : enabled
+Python API Scanning Support   : enabled
+Use sudo to set suid bit      : not enabled (option --enable-sudo not selected)
+Configuration finished successfully (00:00:02); project is now ready to build.
 @end verbatim
 
-Note the trailing portion of the above output.  Some ns-3 options are
-not enabled by default or require support from the underlying system.
-For instance, to enable Python bindings, Python development headers must
-be installed on the host machine, and they were not found in the above
-example, so Python scripting will not be supported in the resulting build.
-For this tutorial, we will focus on the non-optional pieces of ns-3.
+Note the last part of the above output.  Some ns-3 options are not enabled by
+default or require support from the underlying system to work properly
+For instance, to enable XmlTo, the library libxml-2.0 must be found on the
+system.  in the example above, this library was not found and the corresponding
+feature was not enabled.  There is a feature to use sudo to set the suid bit of
+certain programs.  This was not enabled by default.
+
+Now go ahead and switch back to the debug build.
+
+@verbatim
+  ./waf -d debug configure
+@end verbatim
 
 The build system is now configured and you can build the debug versions of 
 the @command{ns-3} programs by simply typing,
@@ -206,15 +423,29 @@
   ./waf
 @end verbatim
 
-(Hint:  if you have a multicore machine, use the "-j JOBS" option to speed
-up your build, where JOBS is the number of cores)
-You will see many Waf status messages displayed as the system compiles.  The
-most important is the last one:
+Some waf commands are meaningful during the build phase and some commands are valid
+in the configuration phase.  For example, if you wanted to use the emulation 
+features of @command{ns-3} you might want to enable setting the suid bit using
+sudo.  This is a configuration command, and so you could have run the following
+command
 
 @verbatim
-  Compilation finished successfully
+  ./waf -d debug --enable-sudo configure
 @end verbatim
 
+If you had done this, waf would have run sudo to change the socket creator 
+programs to run as root.  There are many other configure- and build-time options
+available in waf.  To explore these options, type:
+
+@verbatim
+  ./waf -- help
+@end verbatim
+
+We'll use some of the testing-related commands in the next section.
+
+Okay, sorry, I made you build the @command{ns-3} part of the system twice,
+but now you know how to change the configuration and build optimized code.
+
 @c ========================================================================
 @c Testing ns-3
 @c ========================================================================
@@ -234,19 +465,22 @@
 test has passed.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf check
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
+  -- Running NS-3 C++ core unit tests...
   PASS AddressHelper
   PASS Wifi
   PASS DcfManager
-  
   ...
-
   PASS Object
   PASS Ptr
   PASS Callback
-  ~/repos/ns-3-dev >
+  -- Running NS-3 Python bindings unit tests...
+  ...........
+  ----------------------------------------------------------------------
+  Ran 11 tests in 0.003s
+
+  OK
 @end verbatim
 
 This command is typically run by @code{users} to quickly verify that an 
@@ -255,60 +489,66 @@
 @cindex regression tests
 You can also run our regression test suite to ensure that your distribution and
 tool chain have produced binaries that generate output that is identical to
-reference output files stored in a central location.  To run the regression 
-tests, you provide Waf with the regression flag.
+known-good reference output files.  You downloaded these reference traces to 
+your machine during the download process above.  (Warning:  The @code{ns-3.2} 
+and @code{ns-3.3} releases do not use the @code{ns-3-allinone} environment
+and require you to be online when you run regression tests because they
+dynamically synchronize the reference traces directory with an online
+repository immediately prior to the run).
+
+During regression testing Waf will run a number of tests that generate what we
+call trace files.  The content of these trace files are compared with the 
+reference traces.  If they are identical, the regression tests report a PASS 
+status.  If a regression test fails you will see a FAIL indication along with a
+pointer to the offending trace file and its associated reference trace file
+along with a suggestion on diff parameters and options in order to see what 
+has gone awry.  If the error was discovered in a pcap file, it will be useful
+to convert the pcap files to text using tcpdump prior to comparison.
+
+Some regression tests wmay be SKIPped if the required support
+is not present.
+
+To run the regression tests, you provide Waf with the regression flag.
 
 @verbatim
   ./waf --regression
 @end verbatim
 
-Waf will verify that the current files in the @command{ns-3} distribution are
-built and will then look for trace files in the aforementioned centralized 
-location.  If your tool chain includes Mercurial, the regression tests will 
-be downloaded from a repository at @code{code.nsnam.org}.  If you do not have 
-Mercurial installed, the reference traces will be downloaded from a tarball 
-located in the releases section of @code{www.nsnam.org}.  The particular name 
-of the reference trace location is built from the @command{ns-3} version 
-located in the VERSION file, so don't change that string yourself unless you 
-know what you are doing.  (Warning:  The ns-3.2 release requires you
-to be online when you run regression tests because it synchronizes the
-trace directory with an online repository).
-
-Once the reference traces are downloaded to your local machine, Waf will run
-a number of tests that generate what we call trace files.  The content of 
-these trace files are compared with the reference traces just downloaded.  If 
-they are identical, the regression tests report a PASS status.  If the 
-regression tests pass, you should see something like,
+You should see messages indicating that many tests are being run and are
+passing.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --regression
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully 
-  ========== Running Regression Tests ==========
-  Synchronizing reference traces using Mercurial.
-  Pulling http://code.nsnam.org/ns-3-dev-ref-traces from repo.
-  Skipping csma-bridge: Python bindings not available.
-  SKIP test-csma-bridge
-  PASS test-csma-broadcast
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  [647/669] regression-test (test-csma-bridge)
+  [648/669] regression-test (test-csma-broadcast)
+  [649/669] regression-test (test-csma-multicast)
+  [650/669] regression-test (test-csma-one-subnet)
   PASS test-csma-multicast
-  PASS test-csma-one-subnet
-  PASS test-csma-packet-socket
-  PASS test-realtime-udp-echo
-  PASS test-simple-error-model
-  PASS test-simple-global-routing
-  PASS test-simple-point-to-point-olsr
-  PASS test-tcp-large-transfer
-  PASS test-udp-echo
-  PASS test-wifi-wired-bridging
-
-  ~/repos/ns-3-dev >
+  [651/669] regression-test (test-csma-packet-socket)
+  PASS test-csma-bridge
+  ...
+  Regression testing summary:
+  PASS: 22 of 22 tests passed
+  Build finished successfully (00:00:23)
 @end verbatim
 
-If a regression tests fails you will see a FAIL indication along with a
-pointer to the offending trace file and its associated reference trace file
-along with a suggestion on diff parameters and options in order to see what 
-has gone awry.  Python regression tests will be SKIPped if Python bindings
-are not built.
+If you want to take a look at an example of what might be checked during
+a regression test, you can do the following:
+
+@verbatim
+  cd build/debug/regression/traces/second.ref
+  tcpdump -nn -tt -r second-2-0.pcap
+@end verbatim
+
+The output should be clear to anyone who is familiar with tcpdump or net
+sniffers.  We'll have much more to say on pcap files later in this tutorial.
+
+Remember to cd back into the top-level @command{ns-3} directory
+after you are done:
+
+@verbatim
+  cd ../../../../..
+@end verbatim
 
 @c ========================================================================
 @c Running a Script
--- a/doc/tutorial/in-process/introduction.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/in-process/introduction.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -487,7 +487,7 @@
   cd
   mkdir repos
   cd !$
-  hg clone http://code.nanam.org/ns-3-dev
+  hg clone http://code.nsnam.org/ns-3-dev
 @end verbatim
 
 As the hg command executes, you should see something like the following,
--- a/doc/tutorial/introduction.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/introduction.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -24,7 +24,7 @@
 The @command{ns-3} simulator is a discrete-event network simulator targeted 
 primarily for research and educational use.  The 
 @uref{http://www.nsnam.org,,ns-3 project}, 
-started in 2006, is an open-source project developing ns-3.
+started in 2006, is an open-source project developing @command{ns-3}.
 
 Primary documentation for the @command{ns-3} project is available in four
 forms:
@@ -43,7 +43,7 @@
 several example simulations, introducing and explaining key concepts and
 features as we go.
 
-As the tutorial unfolds, we will introduce the full ns-3 documentation 
+As the tutorial unfolds, we will introduce the full @command{ns-3} documentation 
 and provide pointers to source code for those interested in delving deeper
 into the workings of the system.
 
@@ -52,9 +52,9 @@
 @item Ns-3 is not an extension of @uref{http://www.isi.edu/nsnam/ns,,ns-2}; 
 it is a new simulator.  The two simulators are both written in C++ but 
 @command{ns-3} is a new simulator that does not support the ns-2 APIs.  Some 
-models from ns-2 have already been ported from ns-2 to ns-3. The project will
-continue to maintain ns-2 while ns-3 is being built, and will study transition
-and integration mechanisms.
+models from ns-2 have already been ported from ns-2 to @command{ns-3}. The 
+project will continue to maintain ns-2 while @command{ns-3} is being built,
+and will study transition and integration mechanisms.
 @item @command{Ns-3} is open-source, and the project strives to maintain an 
 open  environment for researchers to contribute and share their software.  
 @end itemize
@@ -63,36 +63,36 @@
 @section For ns-2 Users
 
 For those familiar with ns-2, the most visible outward change when moving to 
-ns-3 is the choice of scripting language.  Ns-2 is 
+@command{ns-3} is the choice of scripting language.  Ns-2 is 
 scripted in OTcl and results of simulations can be visualized using the 
 Network Animator @command{nam}.  It is not possible to run a simulation
 in ns-2 purely from C++ (i.e., as a main() program without any OTcl).
 Moreover, some components of ns-2 are written in C++ and others in OTcl.
-In ns-3, the simulator is written entirely in C++, with optional
+In @command{ns-3}, the simulator is written entirely in C++, with optional
 Python bindings.  Simulation scripts can therefore be written in C++
 or in Python.  The results of some simulations can be visualized by
-@command{nam}, but new animators are under development.  Since ns-3
+@command{nam}, but new animators are under development.  Since @command{ns-3}
 generates pcap packet trace files, other utilities can be used to
 analyze traces as well.
 In this tutorial, we will first concentrate on scripting 
 directly in C++ and interpreting results via ascii trace files.  
 
 But there are similarities as well (both, for example, are based on C++ 
-objects, and some code from ns-2 has already been ported to ns-3).
-We will try to highlight differences between ns-2 and ns-3
+objects, and some code from ns-2 has already been ported to @command{ns-3}).
+We will try to highlight differences between ns-2 and @command{ns-3}
 as we proceed in this tutorial.
 
 A question that we often hear is "Should I still use ns-2 or move to
-ns-3?"  The answer is that it depends.  ns-3 does not have all of the
-models that ns-2 currently has, but on the other hand, ns-3 does have
-new capabilities (such as handling multiple interfaces on nodes 
+@command{ns-3}?"  The answer is that it depends.  @command{ns-3} does not have
+all of the models that ns-2 currently has, but on the other hand, @command{ns-3}
+does have new capabilities (such as handling multiple interfaces on nodes 
 correctly, use of IP addressing and more alignment with Internet
 protocols and designs, more detailed 802.11 models, etc.).  ns-2
-models can usually be ported to ns-3 (a porting guide is under
-development).  There is active development on multiple fronts for ns-3.
-The ns-3 developers believe (and certain early users have proven) that
-ns-3 is ready for active use, and should be an attractive alternative
-for users looking to start new simulation projects.  
+models can usually be ported to @command{ns-3} (a porting guide is under
+development).  There is active development on multiple fronts for 
+@command{ns-3}.  The @command{ns-3} developers believe (and certain early users
+have proven) that @command{ns-3} is ready for active use, and should be an 
+attractive alternative for users looking to start new simulation projects.  
 
 @node Contributing
 @section Contributing
@@ -119,7 +119,7 @@
 the project is probably not your foremost concern at this point, but
 we want you to be aware that contributing is in the spirit of the project and
 that even the act of dropping us a note about your early experience 
-with ns-3 (e.g. "this tutorial section was not clear..."), 
+with @command{ns-3} (e.g. "this tutorial section was not clear..."), 
 reports of stale documentation, etc. are much appreciated. 
 
 @node Tutorial Organization
@@ -160,14 +160,14 @@
 @cindex architecture
 There are several important resources of which any @command{ns-3} user must be
 aware.  The main web site is located at @uref{http://www.nsnam.org} and 
-provides access to basic information about the ns-3 system.  Detailed 
+provides access to basic information about the @command{ns-3} system.  Detailed 
 documentation is available through the main web site at
 @uref{http://www.nsnam.org/documents.html}.  You can also find documents 
 relating to the system architecture from this page.
 
-There is a Wiki that complements the main ns-3 web site which you will find at 
-@uref{http://www.nsnam.org/wiki/}.  You will find user and developer FAQs 
-there, as well as troubleshooting guides, third-party contributed code, 
+There is a Wiki that complements the main @command{ns-3} web site which you will
+find at @uref{http://www.nsnam.org/wiki/}.  You will find user and developer 
+FAQs there, as well as troubleshooting guides, third-party contributed code, 
 papers, etc. 
 
 @cindex mercurial repository
@@ -221,7 +221,7 @@
 
 The build system @code{Waf} is used on the @command{ns-3} project.  It is one 
 of the new generation of Python-based build systems.  You will not need to 
-understand any Python to build the existing ns-3 system, and will 
+understand any Python to build the existing @command{ns-3} system, and will 
 only have to understand a tiny and intuitively obvious subset of Python in 
 order to extend the system in most cases.
 
@@ -233,9 +233,9 @@
 
 @cindex C++
 @cindex Python
-As mentioned above, scripting in ns-3 is done in C++ or Python.
-As of ns-3.2, most of the ns-3 API is available in Python, but the models
-are written in C++ in either case.  A working 
+As mentioned above, scripting in @command{ns-3} is done in C++ or Python.
+As of ns-3.2, most of the @command{ns-3} API is available in Python, but the 
+models are written in C++ in either case.  A working 
 knowledge of C++ and object-oriented concepts is assumed in this document.
 We will take some time to review some of the more advanced concepts or 
 possibly unfamiliar language features, idioms and design patterns as they 
@@ -255,7 +255,7 @@
 for development.  A 
 software toolchain is the set of programming tools available in the given 
 environment. For a quick review of what is included in the GNU toolchain see,
-@uref{http://en.wikipedia.org/wiki/GNU_toolchain}.  ns-3 uses gcc, 
+@uref{http://en.wikipedia.org/wiki/GNU_toolchain}.  @command{ns-3} uses gcc, 
 GNU binutils, and gdb.  However, we do not use the GNU build system,
 either make or autotools, using Waf instead.
 
--- a/doc/tutorial/tweaking.texi	Mon Mar 23 13:16:09 2009 +0100
+++ b/doc/tutorial/tweaking.texi	Fri Apr 17 17:45:16 2009 +0200
@@ -82,8 +82,8 @@
 documentation if you have not done so.
 
 Now that you have read the documentation in great detail, let's use some of
-that knowledge to get some interesting information out of the @code{first.cc}
-example script you have already built.
+that knowledge to get some interesting information out of the 
+@code{scratch/myfirst.cc} example script you have already built.
 
 @node Enabling Logging
 @subsection Enabling Logging
@@ -92,17 +92,22 @@
 to get our bearings, go ahead and run the script just as you did previously,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
+  ./waf --run scratch/myfirst
+@end verbatim
+
+You should see the now familiar output of the first @command{ns-3} example
+program
+
+@verbatim
+  Entering directory `repos/ns-3-dev/build'
   Compilation finished successfully
   Sent 1024 bytes to 10.1.1.2
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.1.2
-  ~/repos/ns-3-dev >
 @end verbatim
 
-It turns out that the ``Sent'' and ``Received'' messages are actually logging
-messages from the @code{UdpEchoClientApplication} and 
+It turns out that the ``Sent'' and ``Received'' messages you see above are
+actually logging messages from the @code{UdpEchoClientApplication} and 
 @code{UdpEchoServerApplication}.  We can ask the client application, for 
 example, to print more information by setting its logging level via the 
 NS_LOG environment variable.  
@@ -113,7 +118,7 @@
 required by those shells.
 
 Right now, the UDP echo client application is responding to the following line
-of code in @code{first.cc},
+of code in @code{scratch/myfirst.cc},
 
 @verbatim
   LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
@@ -127,7 +132,7 @@
 script and recompiling by setting the NS_LOG environment variable like this:
 
 @verbatim
-  ~/repos/ns-3-dev > export NS_LOG=UdpEchoClientApplication=level_all
+  export NS_LOG=UdpEchoClientApplication=level_all
 @end verbatim
 
 This sets the shell environment variable @code{NS_LOG} to the string,
@@ -143,21 +148,19 @@
 system will pick up the change and you should see the following output:
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   UdpEchoClientApplication:UdpEchoClient()
   UdpEchoClientApplication:StartApplication()
   UdpEchoClientApplication:ScheduleTransmit()
   UdpEchoClientApplication:Send()
   Sent 1024 bytes to 10.1.1.2
   Received 1024 bytes from 10.1.1.1
-  UdpEchoClientApplication:HandleRead(0x62c640, 0x62cd70)
+  UdpEchoClientApplication:HandleRead(0x638180, 0x6389b0)
   Received 1024 bytes from 10.1.1.2
   UdpEchoClientApplication:StopApplication()
   UdpEchoClientApplication:DoDispose()
   UdpEchoClientApplication:~UdpEchoClient()
-  ~/repos/ns-3-dev >
 @end verbatim
 
 The additional debug information provided by the application is from
@@ -198,21 +201,19 @@
 name.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   UdpEchoClientApplication:UdpEchoClient()
   UdpEchoClientApplication:StartApplication()
   UdpEchoClientApplication:ScheduleTransmit()
   UdpEchoClientApplication:Send()
   UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
   Received 1024 bytes from 10.1.1.1
-  UdpEchoClientApplication:HandleRead(0x62c710, 0x62ce40)
+  UdpEchoClientApplication:HandleRead(0x638180, 0x6389b0)
   UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
   UdpEchoClientApplication:StopApplication()
   UdpEchoClientApplication:DoDispose()
   UdpEchoClientApplication:~UdpEchoClient()
-  ~/repos/ns-3-dev >
 @end verbatim
 
 You can now see all of the messages coming from the UDP echo client application
@@ -227,17 +228,16 @@
                  UdpEchoServerApplication=level_all|prefix_func'
 @end verbatim
 
-Note that you will need to remove the newline after the @code{:} in the
-example text above.
+Warning:  You will need to remove the newline after the @code{:} in the
+example text above which is only there for document formatting purposes.
 
 Now, if you run the script you will see all of the log messages from both the
 echo client and server applications.  You may see that this can be very useful
 in debugging problems.
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   UdpEchoServerApplication:UdpEchoServer()
   UdpEchoClientApplication:UdpEchoClient()
   UdpEchoServerApplication:StartApplication()
@@ -247,7 +247,7 @@
   UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
   UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
   UdpEchoServerApplication:HandleRead(): Echoing packet
-  UdpEchoClientApplication:HandleRead(0x62c760, 0x62ce90)
+  UdpEchoClientApplication:HandleRead(0x638320, 0x638b50)
   UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
   UdpEchoServerApplication:StopApplication()
   UdpEchoClientApplication:StopApplication()
@@ -255,7 +255,6 @@
   UdpEchoServerApplication:DoDispose()
   UdpEchoClientApplication:~UdpEchoClient()
   UdpEchoServerApplication:~UdpEchoServer()
-  ~/repos/ns-3-dev >
 @end verbatim
 
 It is also sometimes useful to be able to see the simulation time at which a
@@ -266,12 +265,12 @@
                  UdpEchoServerApplication=level_all|prefix_func|prefix_time'
 @end verbatim
 
-If you run the script now, you should see the following output:
+Again, you will have to remove the newline above.  If you run the script now,
+you should see the following output:
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   0s UdpEchoServerApplication:UdpEchoServer()
   0s UdpEchoClientApplication:UdpEchoClient()
   1s UdpEchoServerApplication:StartApplication()
@@ -281,7 +280,7 @@
   2s UdpEchoClientApplication:Send(): Sent 1024 bytes to 10.1.1.2
   2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
   2.00369s UdpEchoServerApplication:HandleRead(): Echoing packet
-  2.00737s UdpEchoClientApplication:HandleRead(0x62c8c0, 0x62d020)
+  2.00737s UdpEchoClientApplication:HandleRead(0x638490, 0x638cc0)
   2.00737s UdpEchoClientApplication:HandleRead(): Received 1024 bytes from 10.1.1.2
   10s UdpEchoServerApplication:StopApplication()
   10s UdpEchoClientApplication:StopApplication()
@@ -289,15 +288,14 @@
   UdpEchoServerApplication:DoDispose()
   UdpEchoClientApplication:~UdpEchoClient()
   UdpEchoServerApplication:~UdpEchoServer()
-  ~/repos/ns-3-dev >
 @end verbatim
 
 You can see that the constructor for the UdpEchoServer was called at a 
 simulation time of 0 seconds.  This is actually happening before the 
 simulation starts.  The same for the UdpEchoClient constructor.
 
-Recall that the @code{first.cc} script started the echo server application at
-one second into the simulation.  You can now see that the 
+Recall that the @code{scratch/first.cc} script started the echo server 
+application at one second into the simulation.  You can now see that the 
 @code{StartApplication} method of the server is, in fact, called at one second
 (or one billion nanoseconds).  You can also see that the echo client 
 application is started at a simulation time of two seconds as we requested in
@@ -322,29 +320,29 @@
 
 The asterisk above is the logging component wildcard.  This will turn on all 
 of the logging in all of the components used in the simulation.  I won't 
-reproduce the output here (as of this writing it produces 772 lines of output
+reproduce the output here (as of this writing it produces 974 lines of output
 for the single packet echo) but you can redirect this information into a file 
 and look through it with your favorite editor if you like,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first >& log.out
+  ./waf --run scratch/myfirst > log.out 2>&1
 @end verbatim
 
-I personally use this quite a bit when I am presented with a problem and I
-have no idea where things are going wrong.  I can follow the progress of the
-code quite easily without having to set breakpoints and step through code
-in a debugger.  When I have a general idea about what is going wrong, I 
-transition into a debugger for fine-grained examination of the problem.  This
-kind of output can be especially useful when your script does something 
-completely unexpected.  If you are stepping using a debugger you may miss an
-unexpected excursion completely.  Logging the excursion makes it quickly
-visible.
+I personally use this volume of logging quite a bit when I am presented with 
+a problem and I have no idea where things are going wrong.  I can follow the 
+progress of the code quite easily without having to set breakpoints and step 
+through code in a debugger.  When I have a general idea about what is going 
+wrong, I transition into a debugger for fine-grained examination of the 
+problem.  This kind of output can be especially useful when your script does 
+something completely unexpected.  If you are stepping using a debugger you
+may miss an unexpected excursion completely.  Logging the excursion makes it
+quickly visible.
 
 @node Adding Logging to your Code
 @subsection Adding Logging to your Code
 @cindex NS_LOG
 You can add new logging to your simulations by making calls to the log 
-component via several macros.  Let's do so in the @code{first.cc} script we
+component via several macros.  Let's do so in the @code{myfirst.cc} script we
 have in the @code{scratch} directory.
 
 Recall that we have defined a logging component in that script:
@@ -357,43 +355,56 @@
 setting the @code{NS_LOG} environment variable to the various levels.  Let's
 go ahead add some logging to the script.  The macro used to add an 
 informational level log message is @code{NS_LOG_INFO}.  Go ahead and add one 
-just before we start creating the nodes that tells you that the script is 
+(just before we start creating the nodes) that tells you that the script is 
 ``Creating Topology.''  This is done as in this code snippet,
 
+Open @code{scratch/myfirst.cc} in your favorite editor and add the line,
+
 @verbatim
   NS_LOG_INFO ("Creating Topology");
 @end verbatim
 
+right before the lines,
+
+@verbatim
+  NodeContainer nodes;
+  nodes.Create (2);
+@end verbatim
+
 Now build the script using waf and clear the @code{NS_LOG} variable to turn 
 off the torrent of logging we previously enabled:
 
 @verbatim
-  ~/repos/ns-3-dev > export NS_LOG=
+  ./waf
+  export NS_LOG=
 @end verbatim
 
-Now, if you run the script, you will not see your new message since its 
-associated logging component (@code{FirstScriptExample}) has not been enabled.
-In order to see your message you will have to enable the 
-@code{FirstScriptExample} logging component with a level greater than or equal
-to @code{NS_LOG_INFO}.  If you just want to see this particular level of 
-logging, you can enable it by,
+Now, if you run the script, 
 
 @verbatim
-  ~/repos/ns-3-dev > export NS_LOG=FirstScriptExample=info
+  ./waf --run scratch/myfirst
+@end verbatim
+
+you will @emph{not} see your new message since its associated logging 
+component (@code{FirstScriptExample}) has not been enabled.  In order to see your
+message you will have to enable the @code{FirstScriptExample} logging component
+with a level greater than or equal to @code{NS_LOG_INFO}.  If you just want to 
+see this particular level of logging, you can enable it by,
+
+@verbatim
+  export NS_LOG=FirstScriptExample=info
 @end verbatim
 
 If you now run the script you will see your new ``Creating Topology'' log
 message,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   Creating Topology
   Sent 1024 bytes to 10.1.1.2
   Received 1024 bytes from 10.1.1.1
   Received 1024 bytes from 10.1.1.2
-  ~/repos/ns-3-dev >
 @end verbatim
 
 @c ========================================================================
@@ -427,35 +438,33 @@
 @end verbatim
 
 This simple two line snippet is actually very useful by itself.  It opens the
-door to the @command{ns-3} global variable and attribute systems.  Go ahead 
-and add that two lines of code to the @code{first.cc} script at the start of 
-@code{main}.  Go ahead and build the script and run it, but ask the script 
-for help in the following way,
+door to the @command{ns-3} global variable and @code{Attribute} systems.  Go 
+ahead and add that two lines of code to the @code{scratch/first.cc} script at
+the start of @code{main}.  Go ahead and build the script and run it, but ask 
+the script for help in the following way,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run "scratch/first --PrintHelp"
+  ./waf --run "scratch/myfirst --PrintHelp"
 @end verbatim
 
-This will ask Waf to run the @code{scratch/first} script and pass the command
+This will ask Waf to run the @code{scratch/myfirst} script and pass the command
 line argument @code{--PrintHelp} to the script.  The quotes are required to 
 sort out which program gets which argument.  The command line parser will
 now see the @code{--PrintHelp} argument and respond with,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run ``scratch/first --PrintHelp''
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   --PrintHelp: Print this help message.
   --PrintGroups: Print the list of groups.
   --PrintTypeIds: Print all TypeIds.
   --PrintGroup=[group]: Print all TypeIds of group.
   --PrintAttributes=[typeid]: Print all attributes of typeid.
   --PrintGlobals: Print the list of globals.
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Let's focus on the @code{--PrintAttributes} option.  We have already hinted
-at the @command{ns-3} attribute system while walking through the 
+at the @command{ns-3} @code{Attribute} system while walking through the 
 @code{first.cc} script.  We looked at the following lines of code,
 
 @verbatim
@@ -466,17 +475,17 @@
 
 and mentioned that @code{DataRate} was actually an @code{Attribute} of the 
 @code{PointToPointNetDevice}.  Let's use the command line argument parser
-to take a look at the attributes of the PointToPointNetDevice.  The help
+to take a look at the @code{Attributes} of the PointToPointNetDevice.  The help
 listing says that we should provide a @code{TypeId}.  This corresponds to the
-class name of the class to which the attributes belong.  In this case it will
-be @code{ns3::PointToPointNetDevice}.  Let's go ahead and type in,
+class name of the class to which the @code{Attributes} belong.  In this case it
+will be @code{ns3::PointToPointNetDevice}.  Let's go ahead and type in,
 
 @verbatim
-  ./waf --run "scratch/first --PrintAttributes=ns3::PointToPointNetDevice"
+  ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice"
 @end verbatim
 
-The system will print out all of the attributes of this kind of net device.
-Among the attributes you will see listed is,
+The system will print out all of the @code{Attributes} of this kind of net device.
+Among the @code{Attributes} you will see listed is,
 
 @verbatim
   --ns3::PointToPointNetDevice::DataRate=[32768bps]:
@@ -484,7 +493,7 @@
 @end verbatim
 
 This is the default value that will be used when a @code{PointToPointNetDevice}
-is created in the system.  We overrode this default with the attribute
+is created in the system.  We overrode this default with the @code{Attribute}
 setting in the @code{PointToPointHelper} above.  Let's use the default values 
 for the point-to-point devices and channels by deleting the 
 @code{SetDeviceAttribute} call and the @code{SetChannelAttribute} call from 
@@ -518,24 +527,26 @@
 If you run the script, you should now see the following output,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run scratch/first
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
-  0ns UdpEchoServerApplication:UdpEchoServer()
-  1000000000ns UdpEchoServerApplication:StartApplication()
+  Build finished successfully (00:00:00)
+  0s UdpEchoServerApplication:UdpEchoServer()
+  1s UdpEchoServerApplication:StartApplication()
   Sent 1024 bytes to 10.1.1.2
-  2257324218ns Received 1024 bytes from 10.1.1.1
-  2257324218ns Echoing packet
+  2.25732s Received 1024 bytes from 10.1.1.1
+  2.25732s Echoing packet
   Received 1024 bytes from 10.1.1.2
-  10000000000ns UdpEchoServerApplication:StopApplication()
+  10s UdpEchoServerApplication:StopApplication()
   UdpEchoServerApplication:DoDispose()
   UdpEchoServerApplication:~UdpEchoServer()
-  ~/repos/ns-3-dev >
 @end verbatim
 
 Recall that the last time we looked at the simulation time at which the packet
-was received by the echo server, it was at 2.0036864 seconds.  Now it is
-receiving the packet at about 2.257 seconds.  This is because we just dropped
+was received by the echo server, it was at 2.00369 seconds.
+
+@verbatim
+  2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1
+@end verbatim
+
+Now it is receiving the packet at 2.25732 seconds.  This is because we just dropped
 the data rate of the @code{PointToPointNetDevice} down to its default of 
 32768 bits per second from five megabits per second.
 
@@ -544,20 +555,21 @@
 the formula implied by the help item:
 
 @verbatim
-  ./waf --run "scratch/first --ns3::PointToPointNetDevice::DataRate=5Mbps"
+  ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps"
 @end verbatim
 
-This will set the default value of the @code{DataRate} attribute back to 
-five megabits per second.  To get the original behavior of the script back, 
-we will have to set the speed-of-light delay of the channel.  We can ask the 
-command line system to print out the @code{Attributes} of the channel just 
-like we did the net device:
+This will set the default value of the @code{DataRate} @code{Attribute} back to 
+five megabits per second.  Are you surprised by the result?  It turns out that
+in order to get the original behavior of the script back, we will have to set 
+the speed-of-light delay of the channel as well.  We can ask the command line 
+system to print out the @code{Attributes} of the channel just like we did for
+the net device:
 
 @verbatim
-  ./waf --run "scratch/first --PrintAttributes=ns3::PointToPointChannel"
+  ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel"
 @end verbatim
 
-We discover the @code{Delay} attribute of the channel is set in the following
+We discover the @code{Delay} @code{Attribute} of the channel is set in the following
 way:
 
 @verbatim
@@ -568,7 +580,7 @@
 We can then set both of these default values through the command line system,
 
 @verbatim
-  ./waf --run "scratch/first
+  ./waf --run "scratch/myfirst
     --ns3::PointToPointNetDevice::DataRate=5Mbps
     --ns3::PointToPointChannel::Delay=2ms"
 @end verbatim
@@ -577,25 +589,26 @@
 @code{DataRate} and @code{Delay} in the script:
 
 @verbatim
-  Compilation finished successfully
-  0ns UdpEchoServerApplication:UdpEchoServer()
-  1000000000ns UdpEchoServerApplication:StartApplication()
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
+  0s UdpEchoServerApplication:UdpEchoServer()
+  1s UdpEchoServerApplication:StartApplication()
   Sent 1024 bytes to 10.1.1.2
-  2003686400ns Received 1024 bytes from 10.1.1.1
-  2003686400ns Echoing packet
+  2.00369s Received 1024 bytes from 10.1.1.1
+  2.00369s Echoing packet
   Received 1024 bytes from 10.1.1.2
-  10000000000ns UdpEchoServerApplication:StopApplication()
+  10s UdpEchoServerApplication:StopApplication()
   UdpEchoServerApplication:DoDispose()
   UdpEchoServerApplication:~UdpEchoServer()
 @end verbatim
 
-Note that the packet is again received by the server at 2.0036864 seconds.  We 
-could actually set any of the attributes used in the script in this way.  In
-particular we could set the @code{UdpEchoClient} attribute @code{MaxPackets} 
+Note that the packet is again received by the server at 2.00369 seconds.  We 
+could actually set any of the @code{Attributes} used in the script in this way.
+In particular we could set the @code{UdpEchoClient Attribute MaxPackets} 
 to some other value than one.
 
 How would you go about that?  Give it a try.  Remember you have to comment 
-out the place we override the default attribute in the script.  Then you 
+out the place we override the default @code{Attribute} in the script.  Then you 
 have to rebuild the script using the default.  You will also have to find the
 syntax for actually setting the new default atribute value using the command
 line help facility.  Once you have this figured out you should be able to
@@ -604,7 +617,7 @@
 like,
 
 @verbatim
-  ./waf --run "scratch/first 
+  ./waf --run "scratch/myfirst 
     --ns3::PointToPointNetDevice::DataRate=5Mbps 
     --ns3::PointToPointChannel::Delay=2ms 
     --ns3::UdpEchoClient::MaxPackets=2"
@@ -619,7 +632,7 @@
 to the @code{main} function.  We'll initialize it to one to match our previous 
 default behavior.  To allow the command line parser to change this value, we
 need to hook the value into the parser.  We do this by adding a call to 
-@code{AddValue}.  Go ahead and change the @code{scratch/first.cc} script to
+@code{AddValue}.  Go ahead and change the @code{scratch/myfirst.cc} script to
 start with the following code,
 
 @verbatim
@@ -636,20 +649,25 @@
 @end verbatim
 
 Scroll down to the point in the script where we set the @code{MaxPackets}
-attribute and change it so that it is set to the variable @code{nPackets}
+@code{Attribute} and change it so that it is set to the variable @code{nPackets}
 instead of the constant @code{1} as is shown below.
 
 @verbatim
-  echoClient.SetAppAttribute ("MaxPackets", UintegerValue (nPackets));
+  echoClient.SetAttribute ("MaxPackets", UintegerValue (nPackets));
 @end verbatim
 
 Now if you run the script and provide the @code{--PrintHelp} argument, you 
 should see your new @code{User Argument} listed in the help display.
 
+Try,
+
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run "scratch/first --PrintHelp"
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  ./waf --run "scratch/myfirst --PrintHelp"
+@end verbatim
+
+@verbatim
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
   --PrintHelp: Print this help message.
   --PrintGroups: Print the list of groups.
   --PrintTypeIds: Print all TypeIds.
@@ -658,33 +676,43 @@
   --PrintGlobals: Print the list of globals.
   User Arguments:
       --nPackets: Number of packets to echo
-  ~/repos/ns-3-dev >
 @end verbatim
 
 If you want to specify the number of packets to echo, you can now do so by
 setting the @code{--nPackets} argument in the command line,
 
 @verbatim
-  ~/repos/ns-3-dev > ./waf --run "scratch/first --nPackets=2"
-  Entering directory `/home/craigdo/repos/ns-3-dev/build'
-  Compilation finished successfully
+  ./waf --run "scratch/myfirst --nPackets=2"
+@end verbatim
+
+You should now see
+
+@verbatim
+  Entering directory `repos/ns-3-allinone/ns-3-dev/build'
+  Build finished successfully (00:00:00)
+  0s UdpEchoServerApplication:UdpEchoServer()
+  1s UdpEchoServerApplication:StartApplication()
   Sent 1024 bytes to 10.1.1.2
-  Received 1024 bytes from 10.1.1.1
+  2.25732s Received 1024 bytes from 10.1.1.1
+  2.25732s Echoing packet
   Received 1024 bytes from 10.1.1.2
   Sent 1024 bytes to 10.1.1.2
-  Received 1024 bytes from 10.1.1.1
+  3.25732s Received 1024 bytes from 10.1.1.1
+  3.25732s Echoing packet
   Received 1024 bytes from 10.1.1.2
-  ~/repos/ns-3-dev >
+  10s UdpEchoServerApplication:StopApplication()
+  UdpEchoServerApplication:DoDispose()
+  UdpEchoServerApplication:~UdpEchoServer()
 @end verbatim
 
 You have now echoed two packets.
 
 You can see that if you are an @command{ns-3} user, you can use the command 
-line argument system to control global values and attributes.  If you are a 
-model author, you can add new attributes to your Objects and they will 
-automatically be available for setting by your users through the command line
-system.  If you are a script author, you can add new variables to your scripts
-and hook them into the command line system quite painlessly.
+line argument system to control global values and @code{Attributes}.  If you are
+a model author, you can add new @code{Attributes} to your @code{Objects} and 
+they will automatically be available for setting by your users through the
+command line system.  If you are a script author, you can add new variables to 
+your scripts and hook them into the command line system quite painlessly.
 
 @c ========================================================================
 @c Using the Tracing System
@@ -764,17 +792,26 @@
 
 @cindex tracing packets
 Let's just jump right in and add some ASCII tracing output to our 
-@code{first.cc} script.  The first thing you need to do is to add the 
-following code to the script just before the call to @code{Simulator::Run ()}.
+@code{scratch/myfirst.cc} script.  
+
+The first thing you need to do is to add the following include to the top of
+the script just after the GNU GPL comment:
+
+@verbatim
+  #include <fstream>
+@end verbatim
+
+Then, right before the before the call to @code{Simulator::Run ()}, add the
+following lines of code.
 
 @verbatim
   std::ofstream ascii;
-  ascii.open ("first.tr");
+  ascii.open ("myfirst.tr");
   PointToPointHelper::EnableAsciiAll (ascii);
 @end verbatim
 
 The first two lines are just vanilla C++ code to open a stream that will be
-written to a file named ``first.tr.''  See your favorite C++ tutorial if you
+written to a file named ``myfirst.tr.''  See your favorite C++ tutorial if you
 are unfamiliar with this code.  The last line of code in the snippet above
 tells @command{ns-3} that you want to enable ASCII tracing on all 
 point-to-point devices in your simulation; and you want the (provided) trace
@@ -782,32 +819,24 @@
 stream provided. For those familiar with @command{ns-2}, the traced events are
 equivalent to the popular trace points that log "+", "-", "d", and "r" events.
 
-Since we have used a @code{std::ofstream} object, we also need to include the
-appropriate header.  Add the following line to the script (I typically add it
-above the ns-3 includes):
-
-@verbatim
-  #include <fstream>
-@end verbatim
-
 You can now build the script and run it from the command line:
 
 @verbatim
-  ./waf --run scratch/first
+  ./waf --run scratch/myfirst
 @end verbatim
 
-@cindex first.tr
-Just as you have seen previously, you may see some messages from Waf and then
-the ``Compilation finished successfully'' with some number of messages from 
+@cindex myfirst.tr
+Just as you have seen many times before, you will see some messages from Waf and then
+the ``Build finished successfully'' with some number of messages from 
 the running program.  
 
-When it ran, the program will have created a file named @code{first.tr}.  
+When it ran, the program will have created a file named @code{myfirst.tr}.  
 Because of the way that Waf works, the file is not created in the local 
 directory, it is created at the top-level directory of the repository by 
 default.  If you want to control where the traces are saved you can use the 
 @code{--cwd} option of Waf to specify this.  We have not done so, thus we 
 need to change into the top level directory of our repo and take a look at 
-the ASCII trace file @code{first.tr} in your favorite editor.
+the ASCII trace file @code{myfirst.tr} in your favorite editor.
 
 @subsubsection Parsing Ascii Traces
 @cindex parsing ascii traces
@@ -844,7 +873,7 @@
   03 ns3::PppHeader (
   04   Point-to-Point Protocol: IP (0x0021)) 
   05   ns3::Ipv4Header (
-  06     tos 0x0 ttl 64 id 0 offset 0 flags [none] 
+  06     tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none] 
   07     length: 1052 10.1.1.1 > 10.1.1.2)
   08     ns3::UdpHeader (
   09       length: 1032 49153 > 9) 
@@ -898,7 +927,7 @@
 @verbatim
   00 r 
   01 2.25732 
-  02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/Rx 
+  02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx 
   03 ns3::PppHeader (
   04   Point-to-Point Protocol: IP (0x0021)) 
   05   ns3::Ipv4Header (
@@ -917,7 +946,7 @@
 
 The trace source namespace entry (reference 02) has changed to reflect that
 this event is coming from node 1 (@code{/NodeList/1}) and the packet reception
-trace source (@code{/Rx}).  It should be quite easy for you to follow the 
+trace source (@code{/MacRx}).  It should be quite easy for you to follow the 
 progress of the packet through the topology by looking at the rest of the 
 traces in the file.
 
@@ -937,54 +966,54 @@
 The code used to enable pcap tracing is a one-liner.  
 
 @verbatim
-  PointToPointHelper::EnablePcapAll ("first");
+  PointToPointHelper::EnablePcapAll ("myfirst");
 @end verbatim
 
 Go ahead and insert this line of code after the ASCII tracing code we just 
-added to @code{scratch/first.cc}.  Notice that we only passed the string
-``first,'' and not ``first.pcap'' or something similar.  This is because the 
+added to @code{scratch/myfirst.cc}.  Notice that we only passed the string
+``myfirst,'' and not ``myfirst.pcap'' or something similar.  This is because the 
 parameter is a prefix, not a complete file name.  The helper will actually 
 create a trace file for every point-to-point device in the simulation.  The 
 file names will be built using the prefix, the node number, the device number
  and a ``.pcap'' suffix.
 
-In our example script, we will eventually see files named ``first-0-0.pcap'' 
-and ``first.1-0.pcap'' which are the pcap traces for node 0-device 0 and 
+In our example script, we will eventually see files named ``myfirst-0-0.pcap'' 
+and ``myfirst.1-0.pcap'' which are the pcap traces for node 0-device 0 and 
 node 1-device 0, respectively.
 
 Once you have added the line of code to enable pcap tracing, you can run the
 script in the usual way:
 
 @verbatim
-  ./waf --run scratch/first
+  ./waf --run scratch/myfirst
 @end verbatim
 
 If you look at the top level directory of your distribution, you should now
-see three log files:  @code{first.tr} is the ASCII trace file we have 
-previously examined.  @code{first-0-0.pcap} and @code{first-1-0.pcap}
+see three log files:  @code{myfirst.tr} is the ASCII trace file we have 
+previously examined.  @code{myfirst-0-0.pcap} and @code{myfirst-1-0.pcap}
 are the new pcap files we just generated.  
 
 @subsubsection Reading output with tcpdump
 @cindex tcpdump
 The easiest thing to do at this point will be to use @code{tcpdump} to look
-at the @code{pcap} files.  Output from dumping both files is shown below:
+at the @code{pcap} files.  
 
 @verbatim
-  ~/repos/ns-3-dev > /usr/sbin/tcpdump -r first-0-0.pcap -nn -tt
-  reading from file first-0-0.pcap, link-type PPP (PPP)
+  tcpdump -nn -tt -r myfirst-0-0.pcap
+  reading from file myfirst-0-0.pcap, link-type PPP (PPP)
   2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
   2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev > /usr/sbin/tcpdump -r first-1-0.pcap -nn -tt
-  reading from file first-1-0.pcap, link-type PPP (PPP)
+
+  tcpdump -nn -tt -r myfirst-1-0.pcap
+  reading from file myfirst-1-0.pcap, link-type PPP (PPP)
   2.257324 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024
   2.257324 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024
-  ~/repos/ns-3-dev >
 @end verbatim
 
-You can see in the dump of ``first-0.0.pcap'' (the client device) that the 
+You can see in the dump of @code{myfirst-0.0.pcap} (the client device) that the 
 echo packet is sent at 2 seconds into the simulation.  If you look at the
-second dump (of ``first-1-0.pcap'') you can see that packet being received
-at 2.257324 seconds.  You see the packet being echoed at 2.257324 seconds
+second dump (@code{first-1-0.pcap}) you can see that packet being received
+at 2.257324 seconds.  You see the packet being echoed back at 2.257324 seconds
 in the second dump, and finally, you see the packet being received back at 
 the client in the first dump at 2.514648 seconds.
 
--- a/examples/second.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/second.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -37,8 +37,8 @@
 main (int argc, char *argv[])
 {
   bool verbose = true;
+  uint32_t nCsma = 3;
 
-  uint32_t nCsma = 3;
   CommandLine cmd;
   cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
   cmd.AddValue ("verbose", "Tell echo applications to log if true", verbose);
@@ -51,6 +51,8 @@
       LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
     }
 
+  nCsma = nCsma == 0 ? 1 : nCsma;
+
   NodeContainer p2pNodes;
   p2pNodes.Create (2);
 
@@ -102,8 +104,8 @@
 
   GlobalRouteManager::PopulateRoutingTables ();
 
-  PointToPointHelper::EnablePcap ("second", p2pDevices.Get (1));
-  CsmaHelper::EnablePcap ("second", csmaDevices.Get (0), true);
+  PointToPointHelper::EnablePcapAll ("second");
+  CsmaHelper::EnablePcap ("second", csmaDevices.Get (1), true);
 
   Simulator::Run ();
   Simulator::Destroy ();
--- a/examples/tap-wifi-dumbbell.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/tap-wifi-dumbbell.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -20,7 +20,8 @@
 //  | external |                                                                  
 //  |  Linux   |                                                                  
 //  |   Host   |                                                                  
-//  |  "left"  |                                                                  
+//  |          |
+//  | "mytap"  |                                                                  
 //  +----------+                                                                  
 //       |           n0                n3                n4
 //       |       +--------+     +------------+     +------------+
@@ -61,7 +62,7 @@
 //    item).
 //
 //    ./waf --run tap-wifi-dumbbell&
-//    sudo route add -net 10.1.3.0 netmask 255.255.255.0 dev left gw 10.1.1.2
+//    sudo route add -net 10.1.3.0 netmask 255.255.255.0 dev thetap gw 10.1.1.2
 //    ping 10.1.3.4
 //
 //    Take a look at the pcap traces and note that the timing reflects the 
@@ -77,9 +78,33 @@
 //    traffic data rate and watch the ping timing change dramatically.
 //
 //    ./waf --run "tap-wifi-dumbbell --ns3::OnOffApplication::DataRate=100kb/s"&
-//    sudo route add -net 10.1.3.0 netmask 255.255.255.0 dev left gw 10.1.1.2
+//    sudo route add -net 10.1.3.0 netmask 255.255.255.0 dev thetap gw 10.1.1.2
 //    ping 10.1.3.4
 //
+// 4) Try to run this in UseLocal mode.  This allows you to provide an existing
+//    pre-configured tap device to the simulation.  The IP address and MAC 
+//    address in this mode do not have to match those of the ns-3 device.
+//
+//    sudo tunctl -t mytap
+//    sudo ifconfig mytap hw ether 08:00:2e:00:00:01
+//    sudo ifconfig mytap 10.1.1.1 netmask 255.255.255.0 up
+//    ./waf --run "tap-wifi-dumbbell --mode=UseLocal --tapName=mytap"&
+//    ping 10.1.1.3
+//
+// 5) Try to run this in UseBridge mode.  This allows you to bridge an ns-3
+//    simulation to an existing pre-configured bridge.  This uses tap devices
+//    just for illustration, you can create your own bridge if you want.
+//
+//    sudo tunctl -t mytap1
+//    sudo ifconfig mytap1 0.0.0.0 promisc up
+//    sudo tunctl -t mytap2
+//    sudo ifconfig mytap2 0.0.0.0 promisc up
+//    sudo brctl addbr mybridge
+//    sudo brctl addif mybridge mytap1
+//    sudo brctl addif mybridge mytap2
+//    sudo ifconfig mybridge 10.1.1.5 netmask 255.255.255.0 up
+//    ./waf --run "tap-wifi-dumbbell --mode=UseBridge --tapName=mytap2"&
+//    ping 10.1.1.3
 
 #include <iostream>
 #include <fstream>
@@ -98,7 +123,12 @@
 int 
 main (int argc, char *argv[])
 {
+  std::string mode = "ConfigureLocal";
+  std::string tapName = "thetap";
+
   CommandLine cmd;
+  cmd.AddValue("mode", "Mode setting of TapBridge", mode);
+  cmd.AddValue("tapName", "Name of the OS tap device", tapName);
   cmd.Parse (argc, argv);
 
   GlobalValue::Bind ("SimulatorImplementationType", StringValue ("ns3::RealtimeSimulatorImpl"));
@@ -145,9 +175,10 @@
   ipv4Left.SetBase ("10.1.1.0", "255.255.255.0");
   Ipv4InterfaceContainer interfacesLeft = ipv4Left.Assign (devicesLeft);
 
-  TapBridgeHelper bridgeLeft (interfacesLeft.GetAddress (1));
-  bridgeLeft.SetAttribute ("DeviceName", StringValue ("left"));
-  bridgeLeft.Install (nodesLeft.Get (0), devicesLeft.Get (0));
+  TapBridgeHelper tapBridge (interfacesLeft.GetAddress (1));
+  tapBridge.SetAttribute ("Mode", StringValue (mode));
+  tapBridge.SetAttribute ("DeviceName", StringValue (tapName));
+  tapBridge.Install (nodesLeft.Get (0), devicesLeft.Get (0));
 
   //
   // Now, create the right side.
--- a/examples/tcp-large-transfer.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/tcp-large-transfer.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -57,9 +57,14 @@
 void StartFlow(Ptr<Socket>, Ipv4Address, uint16_t);
 void WriteUntilBufferFull (Ptr<Socket>, uint32_t);
 
+static void 
+CwndTracer (uint32_t oldval, uint32_t newval)
+{
+  NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
+}
+
 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
   //  LogComponentEnable("TcpL4Protocol", LOG_LEVEL_ALL);
@@ -67,9 +72,6 @@
   //  LogComponentEnable("PacketSink", LOG_LEVEL_ALL);
   //  LogComponentEnable("TcpLargeTransfer", LOG_LEVEL_ALL);
 
-
-  // Allow the user to override any of the defaults and the above
-  // Bind()s at run-time, via command-line arguments
   CommandLine cmd;
   cmd.Parse (argc, argv);
 
@@ -140,6 +142,9 @@
       Socket::CreateSocket (n0n1.Get (0), TcpSocketFactory::GetTypeId ());
   localSocket->Bind ();
 
+  // Trace changes to the congestion window
+  Config::ConnectWithoutContext ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", MakeCallback (&CwndTracer));
+
   // ...and schedule the sending "Application"; This is similar to what an 
   // ns3::Application subclass would do internally.
   Simulator::ScheduleNow (&StartFlow, localSocket,
--- a/examples/tcp-nsc-lfn.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/tcp-nsc-lfn.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -43,6 +43,11 @@
 
 NS_LOG_COMPONENT_DEFINE ("TcpNscLfn");
 
+static void 
+CwndTracer (uint32_t oldval, uint32_t newval)
+{
+  NS_LOG_INFO ("Moving cwnd from " << oldval << " to " << newval);
+}
 
 int main (int argc, char *argv[])
 {
@@ -133,6 +138,10 @@
       clientApp.Stop (Seconds (runtime + 1.0 + i));
     }
 
+  // Trace changes to the congestion window
+  Config::ConnectWithoutContext ("/NodeList/1/$ns3::NscTcpL4Protocol/SocketList/0/CongestionWindow", 
+                                 MakeCallback (&CwndTracer));
+
   // This tells ns-3 to generate pcap traces.
   PointToPointHelper::EnablePcapAll ("tcp-nsc-lfn");
 
--- a/examples/third.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/third.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -40,11 +40,10 @@
 int 
 main (int argc, char *argv[])
 {
-
   bool verbose = true;
-
   uint32_t nCsma = 3;
   uint32_t nWifi = 3;
+
   CommandLine cmd;
   cmd.AddValue ("nCsma", "Number of \"extra\" CSMA nodes/devices", nCsma);
   cmd.AddValue ("nWifi", "Number of wifi STA devices", nWifi);
@@ -162,7 +161,7 @@
 
   Simulator::Stop (Seconds (10.0));
 
-  PointToPointHelper::EnablePcap ("third", p2pDevices.Get (0));
+  PointToPointHelper::EnablePcapAll ("third");
   YansWifiPhyHelper::EnablePcap ("third", apDevices.Get (0));
   CsmaHelper::EnablePcap ("third", csmaDevices.Get (0), true);
 
--- a/examples/wifi-adhoc.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/wifi-adhoc.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -251,6 +251,24 @@
   dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
   gnuplot.AddDataset (dataset);
 
+  NS_LOG_DEBUG ("aarf-cd");
+  experiment = Experiment ("aarf-cd");
+  wifi.SetRemoteStationManager ("ns3::AarfcdWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
+  NS_LOG_DEBUG ("cara");
+  experiment = Experiment ("cara");
+  wifi.SetRemoteStationManager ("ns3::CaraWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
+  NS_LOG_DEBUG ("rraa");
+  experiment = Experiment ("rraa");
+  wifi.SetRemoteStationManager ("ns3::RraaWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
   NS_LOG_DEBUG ("ideal");
   experiment = Experiment ("ideal");
   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
--- a/examples/wifi-ap.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/wifi-ap.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -32,14 +32,14 @@
 using namespace ns3;
 
 void
-DevTxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+DevTxTrace (std::string context, Ptr<const Packet> p)
 {
-  std::cout << " TX to=" << address << " p: " << *p << std::endl;
+  std::cout << " TX p: " << *p << std::endl;
 }
 void
-DevRxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+DevRxTrace (std::string context, Ptr<const Packet> p)
 {
-  std::cout << " RX from=" << address << " p: " << *p << std::endl;
+  std::cout << " RX p: " << *p << std::endl;
 }
 void
 PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
@@ -168,8 +168,8 @@
 
   Simulator::Stop (Seconds (44.0));
 
-  Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
-  Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
+  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacTx", MakeCallback (&DevTxTrace));
+  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacRx", MakeCallback (&DevRxTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxOk", MakeCallback (&PhyRxOkTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxError", MakeCallback (&PhyRxErrorTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/Tx", MakeCallback (&PhyTxTrace));
--- a/examples/wifi-wired-bridging.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/examples/wifi-wired-bridging.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -157,8 +157,6 @@
       wifiX += 20.0;
     }
 
-  GlobalRouteManager::PopulateRoutingTables ();
-
   Address dest;
   std::string protocol;
   if (sendIp)
--- a/regression.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/regression.py	Fri Apr 17 17:45:16 2009 +0200
@@ -3,10 +3,9 @@
 import sys
 import shutil
 import pproc as subprocess
-import urllib
+import errno
 
 # WAF modules
-import Build
 import Options
 import Utils
 import Task
@@ -66,9 +65,11 @@
     after = 'cc cxx cc_link cxx_link'
     color = 'BLUE'
 
-    def __init__(self, env, test_name, test_scripts_dir, build_traces_dir, reference_traces):
-        super(regression_test_task, self).__init__()
+    def __init__(self, bld, env, test_name, test_scripts_dir, build_traces_dir, reference_traces):
+        self.bld = bld
+        self.generator = self
         self.env = env
+        super(regression_test_task, self).__init__(generator=self, env=env)
         self.test_name = test_name
         self.test_scripts_dir = test_scripts_dir
         self.build_traces_dir = build_traces_dir
@@ -77,6 +78,9 @@
     def __str__(self):
         return 'regression-test (%s)\n' % self.test_name
 
+    def runnable_status(self):
+        return Task.RUN_ME
+
     def run(self):
         """Run a single test"""
         sys.path.insert(0, self.test_scripts_dir)
@@ -118,7 +122,11 @@
 
         if Options.options.regression_generate:
             # clean the target dir
-            shutil.rmtree(reference_traces_path, ignore_errors=True)
+            try:
+                shutil.rmtree(reference_traces_path)
+            except OSError, ex:
+                if ex.errno not in [errno.ENOENT]:
+                    raise
             os.makedirs(reference_traces_path)
             result = self.run_reference_generate(reference_traces_path, program, arguments, is_pyscript)
             if result == 0:
@@ -127,7 +135,11 @@
                 print "GENERATE FAIL " + self.test_name
         else:
             # clean the target dir
-            shutil.rmtree(trace_output_path, ignore_errors=True)
+            try:
+                shutil.rmtree(trace_output_path)
+            except OSError, ex:
+                if ex.errno not in [errno.ENOENT]:
+                    raise
             os.makedirs(trace_output_path)
             # run it
             result = self.run_reference_test(reference_traces_path, trace_output_path, program, arguments, is_pyscript)
@@ -147,13 +159,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                wutils.run_argv(argv, cwd=trace_output_path)
+                wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                wutils.run_program(program,
+                wutils.run_program(program, self.env,
                                    command_template=wutils.get_command_template(self.env, arguments),
                                    cwd=trace_output_path)
             except Utils.WafError, ex:
@@ -179,13 +191,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                retval = wutils.run_argv(argv, cwd=trace_output_path)
+                retval = wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                retval = wutils.run_program(program,
+                retval = wutils.run_program(program, self.env,
                                             command_template=wutils.get_command_template(self.env, arguments),
                                             cwd=trace_output_path)
             except Utils.WafError, ex:
@@ -198,13 +210,17 @@
     after = 'regression_test_task'
     color = 'BLUE'
 
-    def __init__(self, test_tasks):
-        super(regression_test_collector_task, self).__init__()
+    def __init__(self, bld, test_tasks):
+        self.bld = bld
+        super(regression_test_collector_task, self).__init__(generator=self)
         self.test_tasks = test_tasks
 
     def __str__(self):
         return 'regression-test-collector\n'
 
+    def runnable_status(self):
+        return Task.RUN_ME
+
     def run(self):
         failed_tests = [test for test in self.test_tasks if test.result is not None and test.result != 0]
         skipped_tests = [test for test in self.test_tasks if test.result is None]
@@ -248,5 +264,7 @@
     build_traces_dir = bld.path.find_or_declare('regression/traces').abspath(bld.env)
     tasks = []
     for test in tests:
-        tasks.append(regression_test_task(bld.env, test, test_scripts_dir, build_traces_dir, reference_traces))
-    regression_test_collector_task(tasks)
+        task = regression_test_task(bld, bld.env, test, test_scripts_dir, build_traces_dir, reference_traces)
+        #bld.task_manager.add_task(task)
+        tasks.append(task)
+    regression_test_collector_task(bld, tasks)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-random-variable.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -0,0 +1,377 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Timo Bingmann
+ *
+ * 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: Timo Bingmann <timo.bingmann@student.kit.edu>
+ */
+#include "ns3/random-variable.h"
+#include "ns3/gnuplot.h"
+#include <map>
+#include <cmath>
+
+using namespace ns3;
+
+/// Round a double number to the given precision. e.g. dround(0.234, 0.1) = 0.2
+/// and dround(0.257, 0.1) = 0.3
+double dround(double number, double precision)
+{
+  number /= precision;
+  if (number >= 0)
+    number = std::floor(number + 0.5);
+  else
+    number = std::ceil(number - 0.5);
+  number *= precision;
+  return number;
+}
+
+static GnuplotDataset
+Histogramm (RandomVariable rndvar, unsigned int probes, double precision, const std::string& title, bool notcontinous = false)
+{
+  typedef std::map<double, unsigned int> histogramm_maptype;
+  histogramm_maptype histogramm;
+
+  for(unsigned int i = 0; i < probes; ++i)
+    {
+      double val = dround( rndvar.GetValue(), precision );
+
+      ++histogramm[val];
+    }
+
+  Gnuplot2dDataset data;
+  data.SetTitle(title);
+
+  if (notcontinous)
+    {
+      data.SetStyle(Gnuplot2dDataset::IMPULSES);
+    }
+
+  for(histogramm_maptype::const_iterator hi = histogramm.begin();
+      hi != histogramm.end(); ++hi)
+    {
+      data.Add(hi->first, (double)hi->second / (double)probes / precision);
+    }
+
+  return data;
+}
+
+int main (int argc, char *argv[])
+{
+  unsigned int probes = 1000000;
+  double precision = 0.01;
+
+  GnuplotCollection gnuplots("main-random-variables.pdf");
+  gnuplots.SetTerminal("pdf enhanced");
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("UniformVariable");
+    plot.AppendExtra("set yrange [0:]");
+
+    plot.AddDataset( Histogramm(UniformVariable(0.0, 1.0), probes, precision,
+                                "UniformVariable [0.0 .. 1.0)") );
+
+    plot.AddDataset( Gnuplot2dFunction("0.1",
+                                       "0 <= x && x <= 1 ? 1.0 : 0") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ExponentialVariable");
+    plot.AppendExtra("set xrange [0:8]");
+    plot.AppendExtra("ExpDist(x,l) = 1/l * exp(-1/l * x)");
+
+    plot.AddDataset( Histogramm(ExponentialVariable(0.5), probes, precision,
+                                "ExponentialVariable m=0.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 0.5",
+                                       "ExpDist(x, 0.5)") );
+
+    plot.AddDataset( Histogramm(ExponentialVariable(1.0), probes, precision,
+                                "ExponentialVariable m=1") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 1.0",
+                                       "ExpDist(x, 1.0)") );
+
+    plot.AddDataset( Histogramm(ExponentialVariable(1.5), probes, precision,
+                                "ExponentialVariable m=1.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 1.5",
+                                       "ExpDist(x, 1.5)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ParetoVariable");
+    plot.AppendExtra("set xrange [0:2]");
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 1.5), probes, precision,
+                                "ParetoVariable m=1.0 s=1.5") );
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 2.0), probes, precision,
+                                "ParetoVariable m=1.0 s=2.0") );
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 2.5), probes, precision,
+                                "ParetoVariable m=1.0 s=2.5") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("WeibullVariable");
+    plot.AppendExtra("set xrange [0:3]");
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 1.0), probes, precision,
+                                "WeibullVariable m=1.0 s=1.0") );
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 2.0), probes, precision,
+                                "WeibullVariable m=1.0 s=2.0") );
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 3.0), probes, precision,
+                                "WeibullVariable m=1.0 s=3.0") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("NormalVariable");
+    plot.AppendExtra("set xrange [-3:3]");
+    plot.AppendExtra("NormalDist(x,m,s) = 1 / (s * sqrt(2*pi)) * exp(-1.0 / 2.0 * ((x-m) / s)**2)");
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 1.0), probes, precision,
+                                "NormalVariable m=0.0 v=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=1.0",
+                                       "NormalDist(x,0.0,1.0)") );
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 2.0), probes, precision,
+                                "NormalVariable m=0.0 v=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(2.0)",
+                                       "NormalDist(x,0.0,sqrt(2.0))") );
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 3.0), probes, precision,
+                                "NormalVariable m=0.0 v=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(3.0)",
+                                       "NormalDist(x,0.0,sqrt(3.0))") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("EmpiricalVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    EmpiricalVariable emp1;
+    emp1.CDF(0.0,  0.0 / 15.0);
+    emp1.CDF(0.2,  1.0 / 15.0);
+    emp1.CDF(0.4,  3.0 / 15.0);
+    emp1.CDF(0.6,  6.0 / 15.0);
+    emp1.CDF(0.8, 10.0 / 15.0);
+    emp1.CDF(1.0, 15.0 / 15.0);
+
+    plot.AddDataset( Histogramm(emp1, probes, precision,
+                                "EmpiricalVariable (Stairs)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("DeterministicVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    double values[] = { 0.0, 0.2, 0.2, 0.4, 0.2, 0.6, 0.8, 0.8, 1.0 };
+    DeterministicVariable det1 (values, sizeof(values) / sizeof(values[0]));
+
+    plot.AddDataset( Histogramm(det1, probes, precision,
+                                "DeterministicVariable", true) );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("LogNormalVariable");
+    plot.AppendExtra("set xrange [0:3]");
+
+    plot.AppendExtra("LogNormalDist(x,m,s) = 1.0/x * NormalDist(log(x), m, s)");
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 1.0), probes, precision,
+                                "LogNormalVariable m=0.0 s=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 1.0)",
+                                       "LogNormalDist(x, 0.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.5), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.5") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.25), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.25") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 0.25)",
+                                       "LogNormalDist(x, 0.0, 0.25)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.125), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.125") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 2.0), probes, precision,
+                                "LogNormalVariable m=0.0 s=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 2.0)",
+                                       "LogNormalDist(x, 0.0, 2.0)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 2.5), probes, precision,
+                                "LogNormalVariable m=0.0 s=2.5") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("TriangularVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.5), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.5") );
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.4), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.4") );
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.65), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.65") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("GammaVariable");
+    plot.AppendExtra("set xrange [0:10]");
+    plot.AppendExtra("set yrange [0:1]");
+    plot.AppendExtra("GammaDist(x,a,b) = x**(a-1) * 1/b**a * exp(-x/b) / gamma(a)");
+
+    plot.AppendExtra("set label 1 '{/Symbol g}(x,{/Symbol a},{/Symbol b}) = x^{/Symbol a-1} e^{-x {/Symbol b}^{-1}} ( {/Symbol b}^{/Symbol a} {/Symbol G}({/Symbol a}) )^{-1}' at 0.7, 0.9");
+
+    plot.AddDataset( Histogramm(GammaVariable(1.0, 1.0), probes, precision,
+                                "GammaVariable a=1.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 1.0, 1.0)",
+                                       "GammaDist(x, 1.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(1.5, 1.0), probes, precision,
+                                "GammaVariable a=1.5 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 1.5, 1.0)",
+                                       "GammaDist(x, 1.5, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.0, 1.0), probes, precision,
+                                "GammaVariable a=2.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.0, 1.0)",
+                                       "GammaDist(x, 2.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(4.0, 1.0), probes, precision,
+                                "GammaVariable a=4.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 4.0, 1.0)",
+                                       "GammaDist(x, 4.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.0, 2.0), probes, precision,
+                                "GammaVariable a=2.0 b=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.0, 2.0)",
+                                       "GammaDist(x, 2.0, 2.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.5, 3.0), probes, precision,
+                                "GammaVariable a=2.5 b=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.5, 3.0)",
+                                       "GammaDist(x, 2.5, 3.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.5, 4.5), probes, precision,
+                                "GammaVariable a=2.5 b=4.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.5, 4.5)",
+                                       "GammaDist(x, 2.5, 4.5)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ErlangVariable");
+    plot.AppendExtra("set xrange [0:10]");
+    plot.AppendExtra("ErlangDist(x,k,l) = x**(k-1) * 1/l**k * exp(-x/l) / (k-1)!");
+
+    plot.AppendExtra("set label 1 'Erlang(x,k,{/Symbol l}) = x^{k-1} e^{-x {/Symbol l}^{-1}} ( {/Symbol l}^k (k-1)! )^{-1}' at 0.7, 0.9");
+
+    plot.AddDataset( Histogramm(ErlangVariable(1, 1.0), probes, precision,
+                                "ErlangVariable k=1 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 1, 1.0)",
+                                       "ErlangDist(x, 1, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 1.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 1.0)",
+                                       "ErlangDist(x, 2, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(3, 1.0), probes, precision,
+                                "ErlangVariable k=3 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 3, 1.0)",
+                                       "ErlangDist(x, 3, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(5, 1.0), probes, precision,
+                                "ErlangVariable k=5 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 5, 1.0)",
+                                       "ErlangDist(x, 5, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 2.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 2.0)",
+                                       "ErlangDist(x, 2, 2.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 3.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 3.0)",
+                                       "ErlangDist(x, 2, 3.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 5.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=5.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 5.0)",
+                                       "ErlangDist(x, 2, 5.0)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  gnuplots.GenerateOutput(std::cout);
+
+  return 0;
+}
--- a/samples/main-simulator.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/samples/main-simulator.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,6 +1,7 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
+#include "ns3/command-line.h"
 #include <iostream>
 
 using namespace ns3;
@@ -37,6 +38,9 @@
 
 int main (int argc, char *argv[])
 {
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
   MyModel model;
 
   Simulator::Schedule (Seconds (10.0), &random_function, &model);
--- a/samples/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/samples/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -10,6 +10,9 @@
     obj = bld.create_ns3_program('main-simulator')
     obj.source = 'main-simulator.cc'
 
+    obj = bld.create_ns3_program('main-random-variable')
+    obj.source = 'main-random-variable.cc'
+
     obj = bld.create_ns3_program('main-packet-header', ['common', 'simulator'])
     obj.source = 'main-packet-header.cc'
 
--- a/src/core/log.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/log.h	Fri Apr 17 17:45:16 2009 +0200
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <iostream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/core/names.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/names.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -623,40 +623,47 @@
   NamesPriv::Delete ();
 }
 
-bool
+void
 Names::Add (std::string name, Ptr<Object> object)
 {
-  return NamesPriv::Get ()->Add (name, object);
+  bool result = NamesPriv::Get ()->Add (name, object);
+  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name);
 }
 
-bool
+void
 Names::Rename (std::string oldpath, std::string newname)
 {
-  return NamesPriv::Get ()->Rename (oldpath, newname);
+  bool result = NamesPriv::Get ()->Rename (oldpath, newname);
+  NS_ABORT_MSG_UNLESS (result, "Names::Rename(): Error renaming " << oldpath << " to " << newname);
 }
 
-bool
+void
 Names::Add (std::string path, std::string name, Ptr<Object> object)
 {
-  return NamesPriv::Get ()->Add (path, name, object);
+  bool result = NamesPriv::Get ()->Add (path, name, object);
+  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding " << path << " " << name);
 }
 
-bool
+void
 Names::Rename (std::string path, std::string oldname, std::string newname)
 {
-  return NamesPriv::Get ()->Rename (path, oldname, newname);
+  bool result = NamesPriv::Get ()->Rename (path, oldname, newname);
+  NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << path << " " << oldname << " to " << newname);
 }
 
-bool
+void
 Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object)
 {
-  return NamesPriv::Get ()->Add (context, name, object);
+  bool result = NamesPriv::Get ()->Add (context, name, object);
+  NS_ABORT_MSG_UNLESS (result, "Names::Add(): Error adding name " << name << " under context " << &context);
 }
 
-bool
+void
 Names::Rename (Ptr<Object> context, std::string oldname, std::string newname)
 {
-  return NamesPriv::Get ()->Rename (context, oldname, newname);
+  bool result = NamesPriv::Get ()->Rename (context, oldname, newname);
+  NS_ABORT_MSG_UNLESS (result, "Names::Rename (): Error renaming " << oldname << " to " << newname << " under context " <<
+                       &context);
 }
 
 std::string
@@ -730,50 +737,53 @@
 {
   bool result = true;
 
+  //
+  // Names::Add and Names::Rename return void to align with the Config API.
+  // The private versions of these functions do return error codes so we
+  // can test to make sure errors are detected.  Names::Add and 
+  // Names::Rename check for these error codes and abort if an error was
+  // detected.  So when we expect that an error should be detected, we 
+  // have to call the private routine to avoid a fatal error popping.
   // 
   // Name a couple of objects at the root level
   //
   Ptr<TestObject> client = CreateObject<TestObject> ();
-  result = Names::Add ("Client", client);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("Client", client);
 
   Ptr<TestObject> server = CreateObject<TestObject> ();
-  result = Names::Add ("Server", server);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("Server", server);
 
   //
   // We shouldn't be able to add another name to a previously named object
   //
-  result = Names::Add ("Not Client", client);
+  result = NamesPriv::Get ()->Add ("Not Client", client);
   NS_TEST_ASSERT_EQUAL (result, false);
 
   //
   // We shouldn't be able to duplicate a name at the root level.
   //
   Ptr<TestObject> secondClient = CreateObject<TestObject> ();
-  result = Names::Add ("Client", secondClient);
+  result = NamesPriv::Get ()->Add ("Client", secondClient);
   NS_TEST_ASSERT_EQUAL (result, false);
 
   //
   // We should be able to add a new name in the first object's context
   //
   Ptr<TestObject> clientEth0 = CreateObject<TestObject> ();
-  result = Names::Add (client, "eth0", clientEth0);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add (client, "eth0", clientEth0);
 
   //
   // We shouldn't be able to duplicate a name in that context.
   //
   Ptr<TestObject> secondClientEth0 = CreateObject<TestObject> ();
-  result = Names::Add (client, "eth0", secondClientEth0);
+  result = NamesPriv::Get ()->Add (client, "eth0", secondClientEth0);
   NS_TEST_ASSERT_EQUAL (result, false);
 
   //
   // We should be able to add the same name in the second object's context
   //
   Ptr<TestObject> serverEth0 = CreateObject<TestObject> ();
-  result = Names::Add (server, "eth0", serverEth0);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add (server, "eth0", serverEth0);
 
   //
   // We should be able to find the short names for the objects we created
@@ -879,32 +889,28 @@
   // in the name.
   //
   Ptr<TestObject> router1 = CreateObject<TestObject> ();
-  result = Names::Add ("/Names/Router1", router1);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("/Names/Router1", router1);
 
   //
   // We should be able to add objects while not including the root of the namespace
   // in the name.
   //
   Ptr<TestObject> router2 = CreateObject<TestObject> ();
-  result = Names::Add ("Router2", router2);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("Router2", router2);
 
   //
   // We should be able to add sub-objects while including the root of the namespace
   // in the name.
   //
   Ptr<TestObject> router1Eth0 = CreateObject<TestObject> ();
-  result = Names::Add ("/Names/Router1/eth0", router1Eth0);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("/Names/Router1/eth0", router1Eth0);
 
   //
   // We should be able to add sub-objects while not including the root of the namespace
   // in the name.
   //
   Ptr<TestObject> router2Eth0 = CreateObject<TestObject> ();
-  result = Names::Add ("Router2/eth0", router2Eth0);
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Add ("Router2/eth0", router2Eth0);
 
   //
   // We should be able to find these objects in the same two ways
@@ -937,20 +943,17 @@
   // We have a pile of names defined.  We should be able to rename them in the
   // usual ways.
   //
-  result = Names::Rename ("/Names/Router1", "RouterX");
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Rename ("/Names/Router1", "RouterX");
 
   foundObject = Names::Find<TestObject> ("/Names/RouterX");
   NS_TEST_ASSERT_EQUAL (foundObject, router1);
 
-  result = Names::Rename ("Router2", "RouterY");
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Rename ("Router2", "RouterY");
 
   foundObject = Names::Find<TestObject> ("RouterY");
   NS_TEST_ASSERT_EQUAL (foundObject, router2);
 
-  result = Names::Rename ("/Names/RouterX/eth0", "ath0");
-  NS_TEST_ASSERT_EQUAL (result, true);
+  Names::Rename ("/Names/RouterX/eth0", "ath0");
 
   foundObject = Names::Find<TestObject> ("/Names/RouterX/ath0");
   NS_TEST_ASSERT_EQUAL (foundObject, router1Eth0);
@@ -963,7 +966,7 @@
   // object.
   //
 
-  result = Names::Rename ("/Names/RouterX", "RouterY");
+  result = NamesPriv::Get ()->Rename ("/Names/RouterX", "RouterY");
   NS_TEST_ASSERT_EQUAL (result, false);
 
   Names::Delete ();
--- a/src/core/names.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/names.h	Fri Apr 17 17:45:16 2009 +0200
@@ -65,7 +65,7 @@
    *             prepended with a path to that object.
    * \param obj A smart pointer to the object itself.
    */
-  static bool Add (std::string name, Ptr<Object> obj);
+  static void Add (std::string name, Ptr<Object> obj);
 
   /**
    * \brief An intermediate form of Names::Add allowing you to provide a path to
@@ -96,11 +96,9 @@
    * \param name The name of the object you want to associate.
    * \param obj A smart pointer to the object itself.
    *
-   * \returns true if the association was successfully completed, false otherwise
-   *
    * \see Names::Add (Ptr<Object> context, std::string name, Ptr<Object> object);
    */
-  static bool Add (std::string path, std::string name, Ptr<Object> object);
+  static void Add (std::string path, std::string name, Ptr<Object> object);
 
   /**
    * \brief A low-level form of Names::Add allowing you to specify the path to
@@ -148,10 +146,8 @@
    *                under which you want this new name to be defined.
    * \param name The name of the object you want to associate.
    * \param obj A smart pointer to the object itself.
-   *
-   * \returns true if the association was successfully completed, false otherwise
    */
-  static bool Add (Ptr<Object> context, std::string name, Ptr<Object> object);
+  static void Add (Ptr<Object> context, std::string name, Ptr<Object> object);
 
   /**
    * \brief Rename a previously associated name.
@@ -178,11 +174,9 @@
    * \param oldpath The current path name to the object you want to change.
    * \param newname The new name of the object you want to change.
    *
-   * \returns true if the name change was successfully completed, false otherwise
-   *
    * \see Names::Add (std::string name, Ptr<Object> obj)
    */
-  static bool Rename (std::string oldpath, std::string newname);
+  static void Rename (std::string oldpath, std::string newname);
 
   /**
    * \brief An intermediate form of Names::Rename allowing you to provide a path to
@@ -203,10 +197,8 @@
    *             you want this name change to occur (cf. directory).
    * \param oldname The currently defined name of the object.
    * \param newname The new name you want the object to have.
-   *
-   * \returns true if the name change was successfully completed, false otherwise
    */
-  static bool Rename (std::string path, std::string oldname, std::string newname);
+  static void Rename (std::string path, std::string oldname, std::string newname);
 
   /**
    * \brief A low-level form of Names::Rename allowing you to specify the path to
@@ -244,10 +236,8 @@
    *                under which you want this new name to be defined.
    * \param oldname The current shortname of the object you want to change.
    * \param newname The new shortname of the object you want to change.
-   *
-   * \returns true if the name change was successfully completed, false otherwise
    */
-  static bool Rename (Ptr<Object> context, std::string oldname, std::string newname);
+  static void Rename (Ptr<Object> context, std::string oldname, std::string newname);
 
   /**
    * Given a pointer to an object, look to see if that object has a name
--- a/src/core/ptr.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/ptr.h	Fri Apr 17 17:45:16 2009 +0200
@@ -106,7 +106,7 @@
   T *operator -> () const;
   T *operator -> ();
   const T &operator * () const;
-  const T &operator * ();
+  T &operator * ();
   // allow if (!sp)
   bool operator! ();
   // allow if (sp)
@@ -472,7 +472,7 @@
 }
 
 template <typename T>
-const T &
+T &
 Ptr<T>::operator * ()
 {
   return *m_ptr;
--- a/src/core/random-variable.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/random-variable.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1220,6 +1220,230 @@
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
+// GammaVariableImpl
+class GammaVariableImpl : public RandomVariableBase
+{
+public:
+  /**
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   */
+  GammaVariableImpl (double alpha, double beta);
+
+  /**
+   * \return A random value from this distribution
+   */
+  virtual double GetValue ();
+
+  /**
+   * \return A random value from the gamma distribution with parameters alpha
+   * and beta
+   */
+  double GetValue(double alpha, double beta);
+
+  virtual RandomVariableBase* Copy(void) const;
+
+private:
+  double m_alpha;
+  double m_beta;
+  NormalVariable m_normal;
+};
+
+
+RandomVariableBase* GammaVariableImpl::Copy () const
+{
+  return new GammaVariableImpl (m_alpha, m_beta);
+}
+
+GammaVariableImpl::GammaVariableImpl (double alpha, double beta)
+  : m_alpha(alpha), m_beta(beta) 
+{
+}
+
+double
+GammaVariableImpl::GetValue ()
+{
+  return GetValue(m_alpha, m_beta);
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  Originally the algorithm was devised by Marsaglia in 2000:
+  G. Marsaglia, W. W. Tsang: A simple method for gereating Gamma variables
+  ACM Transactions on mathematical software, Vol. 26, No. 3, Sept. 2000
+
+  The Gamma distribution density function has the form 
+
+	                     x^(alpha-1) * exp(-x/beta)
+	p(x; alpha, beta) = ----------------------------
+                             beta^alpha * Gamma(alpha)
+
+  for x > 0.
+*/
+double
+GammaVariableImpl::GetValue (double alpha, double beta)
+{
+  if(!m_generator)
+    {
+      m_generator = new RngStream();
+    }
+
+  if (alpha < 1)
+    {
+      double u = m_generator->RandU01 ();
+      return GetValue(1.0 + alpha, beta) * pow (u, 1.0 / alpha);
+    }
+	
+  double x, v, u;
+  double d = alpha - 1.0 / 3.0;
+  double c = (1.0 / 3.0) / sqrt (d);
+
+  while (1)
+    {
+      do
+        {
+          x = m_normal.GetValue ();
+          v = 1.0 + c * x;
+        } while (v <= 0);
+
+      v = v * v * v;
+      u = m_generator->RandU01 ();
+      if (u < 1 - 0.0331 * x * x * x * x)
+        {
+          break;
+        }
+      if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
+        {
+          break;
+        }
+    }
+
+  return beta * d * v;
+}
+
+GammaVariable::GammaVariable ()
+  : RandomVariable (GammaVariableImpl (1.0, 1.0))
+{
+}
+
+GammaVariable::GammaVariable (double alpha, double beta)
+  : RandomVariable (GammaVariableImpl (alpha, beta))
+{
+}
+
+double GammaVariable::GetValue(void) const
+{
+  return this->RandomVariable::GetValue ();
+}
+
+double GammaVariable::GetValue(double alpha, double beta) const
+{
+  return ((GammaVariableImpl*)Peek())->GetValue(alpha, beta);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ErlangVariableImpl
+
+class ErlangVariableImpl : public RandomVariableBase
+{
+public:
+  /**
+   * \param k k parameter of the Erlang distribution
+   * \param lambda lambda parameter of the Erlang distribution
+   */
+  ErlangVariableImpl (unsigned int k, double lambda);
+
+  /**
+   * \return A random value from this distribution
+   */
+  virtual double GetValue ();
+
+  /**
+   * \return A random value from the Erlang distribution with parameters k and
+   * lambda.
+   */
+  double GetValue(unsigned int k, double lambda);
+
+  virtual RandomVariableBase* Copy(void) const;
+
+private:
+  unsigned int m_k;
+  double m_lambda;
+};
+
+
+RandomVariableBase* ErlangVariableImpl::Copy () const
+{
+  return new ErlangVariableImpl (m_k, m_lambda);
+}
+
+ErlangVariableImpl::ErlangVariableImpl (unsigned int k, double lambda)
+  : m_k(k), m_lambda(lambda)
+{
+}
+
+double
+ErlangVariableImpl::GetValue ()
+{
+  return GetValue(m_k, m_lambda);
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  The Erlang distribution density function has the form 
+
+	                   x^(k-1) * exp(-x/lambda)
+	p(x; k, lambda) = ---------------------------
+                             lambda^k * (k-1)!
+
+  for x > 0.
+*/
+double
+ErlangVariableImpl::GetValue (unsigned int k, double lambda)
+{
+  if(!m_generator)
+    {
+      m_generator = new RngStream();
+    }
+
+  ExponentialVariable exponential(lambda);
+
+  double result = 0;
+  for (unsigned int i = 0; i < k; ++i)
+    {
+      result += exponential.GetValue();
+    }
+
+  return result;
+}
+
+ErlangVariable::ErlangVariable ()
+  : RandomVariable (ErlangVariableImpl (1, 1.0))
+{
+}
+
+ErlangVariable::ErlangVariable (unsigned int k, double lambda)
+  : RandomVariable (ErlangVariableImpl (k, lambda))
+{
+}
+
+double ErlangVariable::GetValue(void) const
+{
+  return this->RandomVariable::GetValue ();
+}
+
+double ErlangVariable::GetValue(unsigned int k, double lambda) const
+{
+  return ((ErlangVariableImpl*)Peek())->GetValue(k, lambda);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // TriangularVariableImpl methods
 class TriangularVariableImpl : public RandomVariableBase {
 public:
--- a/src/core/random-variable.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/random-variable.h	Fri Apr 17 17:45:16 2009 +0200
@@ -36,7 +36,7 @@
  *
  */
 
-namespace ns3{
+namespace ns3 {
 
 class RandomVariableBase;
 
@@ -422,7 +422,7 @@
    * value and a shape (alpha) parameter of 1.5.
    * \param m mean value of the distribution
    */
-   WeibullVariable(double m) ;
+  WeibullVariable(double m) ;
 
   /**
    * Constructs a weibull random variable with the specified mean
@@ -560,7 +560,6 @@
   explicit DeterministicVariable(double* d, uint32_t c);
 };
 
-
 /**
  * \brief Log-normal Distributed random var
  * \ingroup randomvariable
@@ -594,6 +593,108 @@
 };
 
 /**
+ * \brief Gamma Distributed Random Variable
+ * \ingroup randomvariable
+ *
+ * GammaVariable defines a random variable with gamma distribution. 
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed gamma distribution. It also supports the generation of 
+ * single random numbers from various gamma distributions.
+ *
+ * The probability density function is defined over the interval [0,+inf) as:
+ * \f$ x^{\alpha-1} \frac{e^{-\frac{x}{\beta}}}{\beta^\alpha \Gamma(\alpha)}\f$
+ * where \f$ mean = \alpha\beta \f$ and 
+ * \f$ variance = \alpha \beta^2\f$
+ */
+class GammaVariable : public RandomVariable 
+{
+public:
+  /**
+   * Constructs a gamma random variable with alpha = 1.0 and beta = 1.0
+   */
+  GammaVariable ();
+
+  /**
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   */
+  GammaVariable (double alpha, double beta);
+
+  /**
+   * \brief call RandomVariable::GetValue
+   * \return A floating point random value 
+   *
+   * Note: we have to re-implement this method here because the method is
+   * overloaded below for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  double GetValue (void) const;
+  
+  /**
+   * \brief Returns a gamma random distributed double with parameters alpha and beta.
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   * \return A floating point random value
+   */
+  double GetValue(double alpha, double beta) const;
+};
+
+/**
+ * \brief Erlang Distributed Random Variable
+ * \ingroup randomvariable
+ *
+ * ErlangVariable defines a random variable with Erlang distribution.
+ *
+ * The Erlang distribution is a special case of the Gamma distribution where k
+ * (= alpha) is a non-negative integer. Erlang distributed variables can be
+ * generated using a much faster algorithm than gamma variables.
+ *
+ * This class supports the creation of objects that return random numbers from
+ * a fixed Erlang distribution. It also supports the generation of single
+ * random numbers from various Erlang distributions.
+ *
+ * The probability density function is defined over the interval [0,+inf) as:
+ * \f$ \frac{x^{k-1} e^{-\frac{x}{\lambda}}}{\lambda^k (k-1)!}\f$
+ * where \f$ mean = k \lambda \f$ and 
+ * \f$ variance = k \lambda^2\f$
+ */
+class ErlangVariable : public RandomVariable 
+{
+public:
+  /**
+   * Constructs an Erlang random variable with k = 1 and lambda = 1.0
+   */
+  ErlangVariable ();
+
+  /**
+   * \param k k parameter of the Erlang distribution. Must be a non-negative integer.
+   * \param lambda lambda parameter of the Erlang distribution
+   */
+  ErlangVariable (unsigned int k, double lambda);
+
+  /**
+   * \brief call RandomVariable::GetValue
+   * \return A floating point random value 
+   *
+   * Note: we have to re-implement this method here because the method is
+   * overloaded below for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  double GetValue (void) const;
+  
+  /**
+   * \brief Returns an Erlang random distributed double with parameters k and lambda.
+   * \param k k parameter of the Erlang distribution. Must be a non-negative integer.
+   * \param lambda lambda parameter of the Erlang distribution
+   * \return A floating point random value
+   */
+  double GetValue(unsigned int k, double lambda) const;
+};
+
+/**
  * \brief Triangularly Distributed random var
  * \ingroup randomvariable
  * 
--- a/src/core/type-id.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/type-id.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -71,6 +71,9 @@
   bool MustHideFromDocumentation (uint16_t uid) const;
 
 private:
+  bool HasTraceSource (uint16_t uid, std::string name);
+  bool HasAttribute (uint16_t uid, std::string name);
+
   struct AttributeInformation {
     std::string name;
     std::string help;
@@ -231,6 +234,33 @@
   return i + 1;
 }
 
+bool
+IidManager::HasAttribute (uint16_t uid,
+                          std::string name)
+{
+  struct IidInformation *information  = LookupInformation (uid);
+  while (true)
+    {
+      for (std::vector<struct AttributeInformation>::const_iterator i = information->attributes.begin ();
+           i != information->attributes.end (); ++i)
+        {
+          if (i->name == name)
+            {
+              return true;
+            }
+        }
+      struct IidInformation *parent = LookupInformation (information->parent);
+      if (parent == information)
+        {
+          // top of inheritance tree
+          return false;
+        }
+      // check parent
+      information = parent;
+    }
+  return false;
+}
+
 void 
 IidManager::AddAttribute (uint16_t uid, 
                           std::string name,
@@ -241,14 +271,10 @@
                           ns3::Ptr<const ns3::AttributeChecker> checker)
 {
   struct IidInformation *information = LookupInformation (uid);
-  for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
-       j != information->attributes.end (); j++)
+  if (HasAttribute (uid, name))
     {
-      if (j->name == name)
-        {
-          NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
-          return;
-        }
+      NS_FATAL_ERROR ("Attribute \"" << name << "\" already registered on tid=\"" << 
+                      information->name << "\"");
     }
   struct AttributeInformation param;
   param.name = name;
@@ -310,6 +336,33 @@
   return information->attributes[i].checker;
 }
 
+bool
+IidManager::HasTraceSource (uint16_t uid,
+                            std::string name)
+{
+  struct IidInformation *information  = LookupInformation (uid);
+  while (true)
+    {
+      for (std::vector<struct TraceSourceInformation>::const_iterator i = information->traceSources.begin ();
+           i != information->traceSources.end (); ++i)
+        {
+          if (i->name == name)
+            {
+              return true;
+            }
+        }
+      struct IidInformation *parent = LookupInformation (information->parent);
+      if (parent == information)
+        {
+          // top of inheritance tree
+          return false;
+        }
+      // check parent
+      information = parent;
+    }
+  return false;
+}
+
 void 
 IidManager::AddTraceSource (uint16_t uid,
                             std::string name, 
@@ -317,6 +370,11 @@
                             ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
 {
   struct IidInformation *information  = LookupInformation (uid);
+  if (HasTraceSource (uid, name))
+    {
+      NS_FATAL_ERROR ("Trace source \"" << name << "\" already registered on tid=\"" << 
+                      information->name << "\"");
+    }
   struct TraceSourceInformation source;
   source.name = name;
   source.help = help;
--- a/src/core/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/core/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -11,7 +11,7 @@
 
     # Check for POSIX threads
     test_env = conf.env.copy()
-    if Options.platform != 'darwin':
+    if Options.platform != 'darwin' and Options.platform != 'cygwin':
         test_env.append_value('LINKFLAGS', '-pthread')
         test_env.append_value('CXXFLAGS', '-pthread')
         test_env.append_value('CCFLAGS', '-pthread')
@@ -30,7 +30,7 @@
                               mandatory=False)
     if have_pthread:
         # darwin accepts -pthread but prints a warning saying it is ignored
-        if Options.platform != 'darwin':
+        if Options.platform != 'darwin' and Options.platform != 'cygwin':
             conf.env['CXXFLAGS_PTHREAD'] = '-pthread'
             conf.env['CCFLAGS_PTHREAD'] = '-pthread'
             conf.env['LINKFLAGS_PTHREAD'] = '-pthread'
--- a/src/devices/bridge/bridge-channel.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/bridge/bridge-channel.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -34,7 +34,7 @@
 }
 
 BridgeChannel::BridgeChannel ()
-  : Channel ("BridgeChannel")
+  : Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
--- a/src/devices/bridge/bridge-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/bridge/bridge-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -53,7 +53,6 @@
 
 BridgeNetDevice::BridgeNetDevice ()
   : m_node (0),
-    m_name (""),
     m_ifIndex (0),
     m_mtu (0xffff)
 {
@@ -111,7 +110,14 @@
       break;
 
     case PACKET_OTHERHOST:
-      ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
+      if (dst48 == m_address)
+        {
+          m_rxCallback (this, packet, protocol, src);
+        }
+      else
+        {
+          ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
+        }
       break;
     }
 }
@@ -121,7 +127,7 @@
                                  uint16_t protocol, Mac48Address src, Mac48Address dst)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
+  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
                 << ", packet=" << packet << ", protocol="<<protocol
                 << ", src=" << src << ", dst=" << dst << ")");
 
@@ -129,7 +135,7 @@
   Ptr<NetDevice> outPort = GetLearnedState (dst);
   if (outPort != NULL && outPort != incomingPort)
     {
-      NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetName () << "'");
+      NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetInstanceTypeId ().GetName () << "'");
       outPort->SendFrom (packet->Copy (), src, dst, protocol);
     }
   else
@@ -141,8 +147,9 @@
           Ptr<NetDevice> port = *iter;
           if (port != incomingPort)
             {
-              NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
-                            << " --> " << port->GetName ()
+              NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " 
+                            << incomingPort->GetInstanceTypeId ().GetName ()
+                            << " --> " << port->GetInstanceTypeId ().GetName ()
                             << " (UID " << packet->GetUid () << ").");
               port->SendFrom (packet->Copy (), src, dst, protocol);
             }
@@ -155,7 +162,7 @@
                                         uint16_t protocol, Mac48Address src, Mac48Address dst)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
+  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
                 << ", packet=" << packet << ", protocol="<<protocol
                 << ", src=" << src << ", dst=" << dst << ")");
   Learn (src, incomingPort);
@@ -166,8 +173,9 @@
       Ptr<NetDevice> port = *iter;
       if (port != incomingPort)
         {
-          NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
-                        << " --> " << port->GetName ()
+          NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " 
+                        << incomingPort->GetInstanceTypeId ().GetName ()
+                        << " --> " << port->GetInstanceTypeId ().GetName ()
                         << " (UID " << packet->GetUid () << ").");
           port->SendFrom (packet->Copy (), src, dst, protocol);
         }
@@ -242,7 +250,7 @@
       m_address = Mac48Address::ConvertFrom (bridgePort->GetAddress ());
     }
 
-  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetName ());
+  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetInstanceTypeId ().GetName ());
   m_node->RegisterProtocolHandler (MakeCallback (&BridgeNetDevice::ReceiveFromDevice, this),
                                    0, bridgePort, true);
   m_ports.push_back (bridgePort);
@@ -250,20 +258,6 @@
 }
 
 void 
-BridgeNetDevice::SetName(const std::string name)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_name = name;
-}
-
-std::string 
-BridgeNetDevice::GetName(void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-void 
 BridgeNetDevice::SetIfIndex(const uint32_t index)
 {
   NS_LOG_FUNCTION_NOARGS ();
--- a/src/devices/bridge/bridge-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/bridge/bridge-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -88,8 +88,6 @@
   Ptr<NetDevice> GetBridgePort (uint32_t n) const;
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -140,7 +138,6 @@
   std::map<Mac48Address, LearnedState> m_learnState;
   Ptr<Node> m_node;
   Ptr<BridgeChannel> m_channel;
-  std::string m_name;
   std::vector< Ptr<NetDevice> > m_ports;
   uint32_t m_ifIndex;
   uint16_t m_mtu;
--- a/src/devices/csma/csma-channel.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/csma/csma-channel.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -51,7 +51,7 @@
 
 CsmaChannel::CsmaChannel ()
 : 
-  Channel ("Csma Channel")
+  Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_state = IDLE;
--- a/src/devices/csma/csma-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/csma/csma-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -154,8 +154,7 @@
 }
 
 CsmaNetDevice::CsmaNetDevice ()
-  : m_name (""),
-    m_linkUp (false)
+ : m_linkUp (false)
 {
   NS_LOG_FUNCTION (this);
   m_txMachineState = READY;
@@ -874,20 +873,6 @@
 }
 
   void 
-CsmaNetDevice::SetName (const std::string name)
-{
-  NS_LOG_FUNCTION (name);
-  m_name = name;
-}
-
-  std::string 
-CsmaNetDevice::GetName (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-  void 
 CsmaNetDevice::SetIfIndex (const uint32_t index)
 {
   NS_LOG_FUNCTION (index);
@@ -1054,25 +1039,6 @@
   NS_LOG_FUNCTION (node);
 
   m_node = node;
-  int count = -1;
-  if (m_name.size () == 0)
-    {
-      for (uint32_t i = 0; i < node->GetNDevices (); i++)
-        {
-          Ptr<NetDevice> dev = node->GetDevice (i);
-          if (dynamic_cast<CsmaNetDevice*> (PeekPointer (dev)))
-            {
-              count++;
-              if (dev == this)
-                {
-                  break;
-                }
-            }
-        }
-      std::ostringstream s;
-      s << "eth" << count;
-      m_name = s.str ();
-    }
 }
 
   bool 
--- a/src/devices/csma/csma-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/csma/csma-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -61,7 +61,6 @@
 
   /**
    * Enumeration of the types of packets supported in the class.
-   *
    */
   enum EncapsulationMode {
     ILLEGAL,     /**< Encapsulation mode not set */
@@ -306,8 +305,6 @@
   //
   // The following methods are inherited from NetDevice base class.
   //
-  virtual void SetName (const std::string name);
-  virtual std::string GetName (void) const;
   virtual void SetIfIndex (const uint32_t index);
   virtual uint32_t GetIfIndex (void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -809,11 +806,6 @@
   uint32_t m_ifIndex;
 
   /**
-   * The human readable name of this device.
-   */
-  std::string m_name;
-
-  /**
    * Flag indicating whether or not the link is up.  In this case,
    * whether or not the device is connected to a channel.
    */
--- a/src/devices/emu/emu-encode-decode.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/emu/emu-encode-decode.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -20,6 +20,7 @@
 #include <iostream>
 #include <iomanip>
 #include <sstream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/devices/emu/emu-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/emu/emu-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -68,11 +68,6 @@
                    Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
                    MakeMac48AddressAccessor (&EmuNetDevice::m_address),
                    MakeMac48AddressChecker ())
-    .AddAttribute ("DeviceName", 
-                   "The name of the underlying real device (e.g. eth1).",
-                   StringValue ("eth1"),
-                   MakeStringAccessor (&EmuNetDevice::m_deviceName),
-                   MakeStringChecker ())
     .AddAttribute ("Start", 
                    "The simulation time at which to spin up the device thread.",
                    TimeValue (Seconds (0.)),
@@ -173,8 +168,7 @@
   m_sock (-1),
   m_readThread (0),
   m_ifIndex (std::numeric_limits<uint32_t>::max ()),  // absurdly large value
-  m_sll_ifindex (-1),
-  m_name ("Emu NetDevice")
+  m_sll_ifindex (-1)
 {
   NS_LOG_FUNCTION (this);
   Start (m_tStart);
@@ -844,18 +838,6 @@
 }
 
 void 
-EmuNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-
-std::string 
-EmuNetDevice::GetName(void) const
-{
-  return m_name;
-}
-
-void 
 EmuNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/emu/emu-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/emu/emu-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -105,9 +105,6 @@
 //
 // Pure virtual methods inherited from NetDevice we must implement.
 //
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
-
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
 
@@ -450,11 +447,6 @@
   int32_t m_sll_ifindex;
 
   /**
-   * The human readable name of this device.
-   */
-  std::string m_name;
-
-  /**
    * Flag indicating whether or not the link is up.  In this case,
    * whether or not the device is connected to a channel.
    */
--- a/src/devices/point-to-point/point-to-point-channel.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/point-to-point/point-to-point-channel.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -43,11 +43,11 @@
 }
 
 //
-// By default, you get a channel with the name "PointToPoint Channel" that 
+// By default, you get a channel that 
 // has an "infitely" fast transmission speed and zero delay.
 PointToPointChannel::PointToPointChannel()
 : 
-  Channel ("PointToPoint Channel"), 
+  Channel (), 
   m_delay (Seconds (0.)),
   m_nDevices (0)
 {
--- a/src/devices/point-to-point/point-to-point-channel.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/point-to-point/point-to-point-channel.h	Fri Apr 17 17:45:16 2009 +0200
@@ -50,7 +50,7 @@
   /**
    * \brief Create a PointToPointChannel
    *
-   * By default, you get a channel with the name "PointToPoint Channel" that
+   * By default, you get a channel that
    * has zero transmission delay.
    */
   PointToPointChannel ();
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -148,7 +148,6 @@
 : 
   m_txMachineState (READY),
   m_channel (0), 
-  m_name (""),
   m_linkUp (false),
   m_currentPkt (0)
 {
@@ -167,6 +166,7 @@
 
 PointToPointNetDevice::~PointToPointNetDevice ()
 {
+  NS_LOG_FUNCTION_NOARGS ();
 }
 
   void 
@@ -226,8 +226,8 @@
   //
   NS_ASSERT_MSG(m_txMachineState == READY, "Must be READY to transmit");
   m_txMachineState = BUSY;
+  m_currentPkt = p;
   m_phyTxBeginTrace (m_currentPkt);
-  m_currentPkt = p;
 
   Time txTime = Seconds (m_bps.CalculateTxTime(p->GetSize()));
   Time txCompleteTime = txTime + m_tInterframeGap;
@@ -373,18 +373,6 @@
 }
 
   void 
-PointToPointNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-
-  std::string 
-PointToPointNetDevice::GetName(void) const
-{
-  return m_name;
-}
-
-  void 
 PointToPointNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/point-to-point/point-to-point-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -226,12 +226,6 @@
    */
   uint16_t GetFrameSize (void) const;
 
-//
-// Pure virtual methods inherited from NetDevice we must implement.
-//
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
-
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
 
@@ -531,7 +525,6 @@
   NetDevice::ReceiveCallback m_rxCallback;
   NetDevice::PromiscReceiveCallback m_promiscCallback;
   uint32_t m_ifIndex;
-  std::string m_name;
   bool m_linkUp;
   Callback<void> m_linkChangeCallback;
 
--- a/src/devices/tap-bridge/tap-bridge.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/tap-bridge.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -28,6 +28,7 @@
 #include "ns3/abort.h"
 #include "ns3/boolean.h"
 #include "ns3/string.h"
+#include "ns3/enum.h"
 #include "ns3/ipv4.h"
 #include "ns3/simulator.h"
 #include "ns3/realtime-simulator-impl.h"
@@ -48,10 +49,7 @@
 // if you are running in an environment where you have got to run as root,
 // such as ORBIT or CORE.
 //
-//   sudo tunctl -t tap0
-//   sudo ifconfig tap0 hw ether 00:00:00:00:00:01
-//   sudo ifconfig tap0 10.1.1.1 netmask 255.255.255.0 up
-//
+
 
 // #define NO_CREATOR
 
@@ -82,22 +80,25 @@
                    MakeStringAccessor (&TapBridge::m_tapDeviceName),
                    MakeStringChecker ())
     .AddAttribute ("Gateway", 
-                   "The IP address of the default gateway to assign to the tap device.",
+                   "The IP address of the default gateway to assign to the host machine, when in ConfigureLocal mode.",
                    Ipv4AddressValue ("255.255.255.255"),
                    MakeIpv4AddressAccessor (&TapBridge::m_tapGateway),
                    MakeIpv4AddressChecker ())
     .AddAttribute ("IpAddress", 
-                   "The IP address to assign to the tap device.",
+                   "The IP address to assign to the tap device, when in ConfigureLocal mode.  "
+                   "This address will override the discovered IP address of the simulated device.",
                    Ipv4AddressValue ("255.255.255.255"),
                    MakeIpv4AddressAccessor (&TapBridge::m_tapIp),
                    MakeIpv4AddressChecker ())
     .AddAttribute ("MacAddress", 
-                   "The MAC address to assign to the tap device.",
+                   "The MAC address to assign to the tap device, when in ConfigureLocal mode.  "
+                   "This address will override the discovered MAC address of the simulated device.",
                    Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
                    MakeMac48AddressAccessor (&TapBridge::m_tapMac),
                    MakeMac48AddressChecker ())
     .AddAttribute ("Netmask", 
-                   "The network mask to assign to the tap device.",
+                   "The network mask to assign to the tap device, when in ConfigureLocal mode.  "
+                   "This address will override the discovered MAC address of the simulated device.",
                    Ipv4MaskValue ("255.255.255.255"),
                    MakeIpv4MaskAccessor (&TapBridge::m_tapNetmask),
                    MakeIpv4MaskChecker ())
@@ -111,6 +112,13 @@
                    TimeValue (Seconds (0.)),
                    MakeTimeAccessor (&TapBridge::m_tStop),
                    MakeTimeChecker ())
+    .AddAttribute ("Mode", 
+                   "The operating and configuration mode to use.",
+                   EnumValue (USE_LOCAL),
+                   MakeEnumAccessor (&TapBridge::SetMode),
+                   MakeEnumChecker (CONFIGURE_LOCAL, "ConfigureLocal",
+                                    USE_LOCAL, "UseLocal",
+                                    USE_BRIDGE, "UseBridge"))
     ;
   return tid;
 }
@@ -122,7 +130,8 @@
   m_sock (-1),
   m_startEvent (),
   m_stopEvent (),
-  m_readThread (0)
+  m_readThread (0),
+  m_learnedMac (Mac48Address ("ff:ff:ff:ff:ff:ff"))
 {
   NS_LOG_FUNCTION_NOARGS ();
   Start (m_tStart);
@@ -215,38 +224,53 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-#ifdef NO_CREATOR
+  // 
+  // The TapBridge has three distinct operating modes.  At this point, the
+  // differences revolve around who is responsible for creating and configuring
+  // the underlying network tap that we use.  In ConfigureLocal mode, the 
+  // TapBridge has the responsibility for creating and configuring the TAP.
   //
-  // In come cases, can you say FreeBSD, the tap-creator just gets in the way.
-  // in this case, just define NO_CREATOR, manually set up your tap device and
-  // just open and use it.
+  // In UseBridge or UseLocal modes, the user will provide us a configuration
+  // and we have to adapt to it.  For example, in UseLocal mode, the user will
+  // be configuring a tap device outside the scope of the ns-3 simulation and
+  // will be expecting us to work with it.  The user will do something like:
   //
-  //
-  // Creation and management of Tap devices is done via the tun device
+  //   sudo tunctl -t tap0
+  //   sudo ifconfig tap0 hw ether 00:00:00:00:00:01
+  //   sudo ifconfig tap0 10.1.1.1 netmask 255.255.255.0 up
   //
-  m_sock = open ("/dev/net/tun", O_RDWR);
-  NS_ABORT_MSG_IF (m_sock == -1, "TapBridge::CreateTap(): could not open /dev/net/tun: " << strerror (errno));
-
+  // The user will then set the "Mode" Attribute of the TapBridge to "UseLocal"
+  // and the "DeviceName" Attribute to "tap0" in this case.  
+  //
+  // In ConfigureLocal mode, the user is asking the TapBridge to do the 
+  // configuration and create a TAP with the provided "DeviceName" with which 
+  // the user can later do what she wants.  We need to extract values for the
+  // MAC address, IP address, net mask, etc, from the simualtion itself and 
+  // use them to initialize corresponding values on the created tap device.
   //
-  // Allocate a tap device, making sure that it will not send the tun_pi header.
-  // If we provide a null name to the ifr.ifr_name, we tell the kernel to pick
-  // a name for us (i.e., tapn where n = 0..255
+  // In UseBridge mode, the user is asking us to use an existing tap device
+  // has been included in an OS bridge.  She is asking us to take the simulated
+  // net device and logically add it to the existing bridge.  We expect that
+  // the user has done something like:
   //
-  struct ifreq ifr;
-  ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
-  strcpy (ifr.ifr_name, m_tapDeviceName.c_str ());
-  int status = ioctl (m_sock, TUNSETIFF, (void *) &ifr);
-  NS_ABORT_MSG_IF (status == -1, "TapBridge::CreateTap(): could not open device " << m_tapDeviceName << 
-                   ": " << strerror (errno));
-
-#else // use the tap-creator
-
+  //   sudo brctl addbr mybridge
+  //   sudo tunctl -t mytap
+  //   sudo ifconfig mytap hw ether 00:00:00:00:00:01
+  //   sudo ifconfig mytap 0.0.0.0 up
+  //   sudo brctl addif mybridge mytap
+  //   sudo brctl addif mybridge ...
+  //   sudo ifconfig mybridge 10.1.1.1 netmask 255.255.255.0 up
   //
-  // We want to create a tap device on the host.  Unfortunately for us
-  // you have to have root privileges to do that.  Instead of running the 
-  // entire simulation as root, we decided to make a small program who's whole
-  // reason for being is to run as suid root and do what it takes to create the
-  // tap.  We're going to fork and exec that program soon, but we need to have 
+  // The bottom line at this point is that we want to either create or use a 
+  // tap device on the host based on the verb part "Use" or "Configure" of the 
+  // operating mode.  Unfortunately for us you have to have root privileges to
+  // do either.  Instead of running the entire simulation as root, we decided 
+  // to make a small program who's whole reason for being is to run as suid 
+  // root and do what it takes to create the tap.  We're just going to pass 
+  // off the configuration information to that program and let it deal with
+  // the situation.
+  //
+  // We're going to fork and exec that program soon, but first we need to have 
   // a socket to talk to it with.  So we create a local interprocess (Unix) 
   // socket for that purpose.
   //
@@ -282,7 +306,8 @@
   NS_LOG_INFO ("Encoded Unix socket as \"" << path << "\"");
   //
   // Fork and exec the process to create our socket.  If we're us (the parent)
-  // we wait for the child (the creator) to complete and read the  socket it created using the ancillary data mechanism.
+  // we wait for the child (the creator) to complete and read the socket it 
+  // created and passed back using the ancillary data mechanism.
   //
   pid_t pid = ::fork ();
   if (pid == 0)
@@ -300,9 +325,10 @@
       // -i<IP-address> The IP address to assign to the new tap device;
       // -m<MAC-address> The MAC-48 address to assign to the new tap device;
       // -n<network-mask> The network mask to assign to the new tap device;
+      // -o<operating mode> The operating mode of the bridge (1=ConfigureLocal, 2=UseLocal, 3=UseBridge)
       // -p<path> the path to the unix socket described above.
       //
-      // Example tap-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -pblah
+      // Example tap-creator -dnewdev -g1.2.3.2 -i1.2.3.1 -m08:00:2e:00:01:23 -n255.255.255.0 -o1 -pblah
       //
       // We want to get as much of this stuff automagically as possible.
       //
@@ -382,6 +408,21 @@
           ossNetmask << "-n" << m_tapNetmask;
         }
 
+      std::ostringstream ossMode;
+      ossMode << "-o";
+      if (m_mode == CONFIGURE_LOCAL)
+        {
+          ossMode << "1";
+        }
+      else if (m_mode == USE_LOCAL)
+        {
+          ossMode << "2";
+        }
+      else
+        {
+          ossMode << "3";
+        }
+
       std::ostringstream ossPath;
       ossPath << "-p" << path;
       //
@@ -394,7 +435,8 @@
                         ossIp.str ().c_str (),                // argv[3] (-i<IP address>)
                         ossMac.str ().c_str (),               // argv[4] (-m<MAC address>)
                         ossNetmask.str ().c_str (),           // argv[5] (-n<net mask>)
-                        ossPath.str ().c_str (),              // argv[6] (-p<path>)
+                        ossMode.str ().c_str (),              // argv[6] (-o<operating mode>)
+                        ossPath.str ().c_str (),              // argv[7] (-p<path>)
                         (char *)NULL);
 
       //
@@ -484,14 +526,14 @@
 
       //
       // Now we can actually receive the interesting bits from the tap
-      // creator process.
+      // creator process.  Lots of pain to get four bytes.
       //
       ssize_t bytesRead = recvmsg (sock, &msg, 0);
       NS_ABORT_MSG_IF (bytesRead != sizeof(int), "TapBridge::CreateTap(): Wrong byte count from socket creator");
 
       //
       // There may be a number of message headers/ancillary data arrays coming in.
-      // Let's look for the one with a type SCM_RIGHTS which indicates it' the
+      // Let's look for the one with a type SCM_RIGHTS which indicates it's the
       // one we're interested in.
       //
       struct cmsghdr *cmsg;
@@ -521,7 +563,6 @@
 	}
       NS_FATAL_ERROR ("Did not get the raw socket from the socket creator");
     }
-#endif // use the tap-creator
 }
 
 std::string
@@ -531,19 +572,19 @@
 
   std::list<std::string> locations;
 
-  // in repo
+  // The path to the bits if we're sitting in the root of the repo
   locations.push_back ("./build/optimized/src/devices/tap-bridge/");
   locations.push_back ("./build/debug/src/devices/tap-bridge/");
 
-  // in src
+  // if in src
   locations.push_back ("../build/optimized/src/devices/tap-bridge/");
   locations.push_back ("../build/debug/src/devices/tap-bridge/");
 
-  // in src/devices
+  // if in src/devices
   locations.push_back ("../../build/optimized/src/devices/tap-bridge/");
   locations.push_back ("../../build/debug/src/devices/tap-bridge/");
 
-  // in src/devices/tap-bridge
+  // if in src/devices/tap-bridge
   locations.push_back ("../../../build/optimized/src/devices/tap-bridge/");
   locations.push_back ("../../../build/debug/src/devices/tap-bridge/");
 
@@ -568,12 +609,15 @@
   NS_LOG_FUNCTION_NOARGS ();
 
   //
-  // It's important to remember that we're in a completely different thread than the simulator is running in.  We
-  // need to synchronize with that other thread to get the packet up into ns-3.  What we will need to do is to schedule 
-  // a method to deal with the packet using the multithreaded simulator we are most certainly running.  However, I just 
-  // said it -- we are talking about two threads here, so it is very, very dangerous to do any kind of reference couning
-  // on a shared object.  Just don't do it.  So what we're going to do is to allocate a buffer on the heap and pass that
-  // buffer into the ns-3 context thread where it will create the packet.
+  // It's important to remember that we're in a completely different thread 
+  // than the simulator is running in.  We need to synchronize with that 
+  // other thread to get the packet up into ns-3.  What we will need to do 
+  // is to schedule a method to deal with the packet using the multithreaded
+  // simulator we are most certainly running.  However, I just said it -- we
+  // are talking about two threads here, so it is very, very dangerous to do
+  // any kind of reference counting on a shared object.  Just don't do it.
+  // So what we're going to do is to allocate a buffer on the heap and pass
+  // that buffer into the ns-3 context thread where it will create the packet.
   //
   int32_t len = -1;
 
@@ -582,11 +626,12 @@
       uint32_t bufferSize = 65536;
       uint8_t *buf = (uint8_t *)malloc (bufferSize);
       NS_ABORT_MSG_IF (buf == 0, "TapBridge::ReadThread(): malloc packet buffer failed");
-      NS_LOG_LOGIC ("Calling read on tap device socket fd");
+      NS_LOG_LOGIC ("Calling read on tap device socket fd " << m_sock);
       len = read (m_sock, buf, bufferSize);
 
       if (len == -1)
         {
+          NS_LOG_INFO ("TapBridge::ReadThread(): Returning");
           free (buf);
           buf = 0;
           return;
@@ -606,7 +651,31 @@
   NS_LOG_FUNCTION (buf << len);
 
   //
-  // Create a packet out of the buffer we received and free that buffer.
+  // There are three operating modes for the TapBridge
+  //
+  // CONFIGURE_LOCAL means that ns-3 will create and configure a tap device
+  // and we are expected to use it.  The tap device and the ns-3 net device
+  // will have the same MAC address by definition.  Thus Send and SendFrom
+  // are equivalent in this case.  We use Send to allow all ns-3 devices to
+  // participate in this mode.
+  //
+  // USE_LOCAL mode tells us that we have got to USE a pre-created tap device
+  // that will have a different MAC address from the ns-3 net device.  We 
+  // also enforce the requirement that there will only be one MAC address
+  // bridged on the Linux side so we can use Send (instead of SendFrom) in
+  // the linux to ns-3 direction.  Again, all ns-3 devices can participate
+  // in this mode.
+  //
+  // USE_BRIDGE mode tells us that we are logically extending a Linux bridge
+  // on which lies our tap device.  In this case there may be many linux
+  // net devices on the other side of the bridge and so we must use SendFrom
+  // to preserve the possibly many source addresses.  Thus, ns-3 devices 
+  // must support SendFrom in order to be considered for USE_BRIDGE mode.
+  //
+
+  //
+  // First, create a packet out of the byte buffer we received and free that
+  // buffer.
   //
   Ptr<Packet> packet = Create<Packet> (reinterpret_cast<const uint8_t *> (buf), len);
   free (buf);
@@ -633,9 +702,74 @@
   NS_LOG_LOGIC ("Pkt source is " << src);
   NS_LOG_LOGIC ("Pkt destination is " << dst);
   NS_LOG_LOGIC ("Pkt LengthType is " << type);
+  if (m_mode == USE_LOCAL)
+    {
+      //
+      // Packets we are going to forward should not be from a broadcast src
+      //
+      NS_ASSERT_MSG (Mac48Address::ConvertFrom (src) != Mac48Address ("ff:ff:ff:ff:ff:ff"), 
+                     "TapBridge::ForwardToBridgedDevice:  Source addr is broadcast");
+      //
+      // Remember the Mac address since we are going to spoof it when we go
+      // the other way.
+      //
+      m_learnedMac = Mac48Address::ConvertFrom (src);
+      NS_LOG_LOGIC ("Learned MacAddr is " << m_learnedMac);
 
+      // 
+      // If we are operating in USE_LOCAL mode, we may be attached to an ns-3
+      // device that does not support bridging (SupportsSendFrom returns false).
+      // The whole point of this mode is really to support this case.  We allow
+      // only packets from one source MAC to flow across the TapBridge in this 
+      // mode and will spoof that address when packets flow the other way.  
+      // Since we will be doing this spoofing, we can relax the normal bridged
+      // device requirement to support SendFrom and use Send.
+      //
+      NS_LOG_LOGIC ("Forwarding packet to ns-3 device via Send()");
+      m_bridgedDevice->Send (packet, dst, type);
+      return;
+    }
+
+  //
+  // If we are operating in USE_BRIDGE mode, we have the 
+  // situation described below:
+  //
+  //  Other Device  <-bridge->  Tap Device  <-bridge-> ns3 device
+  //   Mac Addr A               Mac Addr B             Mac Addr C
+  //
+  // In Linux, "Other Device" and "Tap Device" are bridged together.  By this
+  // we mean that a user has sone something in Linux like:
+  //
+  //   brctl addbr mybridge
+  //   brctl addif other-device
+  //   brctl addif tap-device
+  //
+  // In USE_BRIDGE mode, we want to logically extend this Linux behavior to the 
+  // simulated ns3 device and make it appear as if it is connected to the Linux
+  // subnet.  As you may expect, this means that we need to act like a real
+  // Linux bridge and take all packets that come from "Tap Device" and ask 
+  // "ns3 Device" to send them down its directly connected network.  Just like 
+  // in a normal everyday bridge we need to call SendFrom in order to preserve 
+  //the original packet's from address.
+  //
+  // If we are operating in CONFIGURE_LOCAL mode, we simply simply take all packets
+  // that come from "Tap Device" and ask "ns3 Device" to send them down its 
+  // directly connected network.  A normal bridge would need to call SendFrom
+  // in order to preserve the original from address, but in CONFIGURE_LOCAL mode
+  // the tap device and the ns-3 device have the same MAC address by definition so 
+  // we can call Send.
+  //
   NS_LOG_LOGIC ("Forwarding packet");
-  m_bridgedDevice->Send (packet, dst, type);
+
+  if (m_mode == USE_BRIDGE)
+    {
+      m_bridgedDevice->SendFrom (packet, src, dst, type);
+    }
+  else
+    {
+      NS_ASSERT_MSG (m_mode == CONFIGURE_LOCAL, "TapBridge::ForwardToBridgedDevice(): Internal error");
+      m_bridgedDevice->Send (packet, dst, type);
+    }
 }
 
 Ptr<Packet>
@@ -646,7 +780,7 @@
 
   //
   // We have a candidate packet for injection into ns-3.  We expect that since
-  // it came over a socket that provides Ethernet packets, it sould be big 
+  // it came over a socket that provides Ethernet packets, it should be big 
   // enough to hold an EthernetHeader.  If it can't, we signify the packet 
   // should be filtered out by returning 0.
   //
@@ -720,7 +854,7 @@
       NS_FATAL_ERROR ("TapBridge::SetBridgedDevice: Device does not support eui 48 addresses: cannot be added to bridge.");
     }
   
-  if (!bridgedDevice->SupportsSendFrom ())
+  if (m_mode == USE_BRIDGE && !bridgedDevice->SupportsSendFrom ())
     {
       NS_FATAL_ERROR ("TapBridge::SetBridgedDevice: Device does not support SendFrom: cannot be added to bridge.");
     }
@@ -744,38 +878,72 @@
 {
   NS_LOG_FUNCTION (device << packet << protocol << src << dst << packetType);
   NS_ASSERT_MSG (device == m_bridgedDevice, "TapBridge::SetBridgedDevice:  Received packet from unexpected device");
-  
   NS_LOG_DEBUG ("Packet UID is " << packet->GetUid ());
 
-  Mac48Address from = Mac48Address::ConvertFrom (src);
-  Mac48Address to = Mac48Address::ConvertFrom (dst);
-
   //
-  // We hooked the promiscuous mode protocol handler so we could get the 
-  // destination address of the actual packet.  This means we will be getting
-  // PACKET_OTHERHOST packets (not broadcast, not multicast, not unicast to 
-  // this device, but to some other address).  We don't want to forward those
-  // PACKET_OTHERHOST packets so just ignore them
+  // There are three operating modes for the TapBridge
+  //
+  // CONFIGURE_LOCAL means that ns-3 will create and configure a tap device
+  // and we are expected to use it.  The tap device and the ns-3 net device
+  // will have the same MAC address by definition.
+  //
+  // USE_LOCAL mode tells us that we have got to USE a pre-created tap device
+  // that will have a different MAC address from the ns-3 net device.  In this
+  // case we will be spoofing the MAC address of a received packet to match
+  // the single allowed address on the Linux side.
+  //
+  // USE_BRIDGE mode tells us that we are logically extending a Linux bridge
+  // on which lies our tap device.
   //
-  if (packetType == PACKET_OTHERHOST)
+
+  if (m_mode == CONFIGURE_LOCAL && packetType == PACKET_OTHERHOST)
     {
+      //
+      // We hooked the promiscuous mode protocol handler so we could get the 
+      // destination address of the actual packet.  This means we will be 
+      // getting PACKET_OTHERHOST packets (not broadcast, not multicast, not 
+      // unicast to the ns-3 net device, but to some other address).  In 
+      // CONFIGURE_LOCAL mode we are not interested in these packets since they 
+      // don't refer to the single MAC address shared by the ns-3 device and 
+      // the TAP device.  If, however, we are in USE_LOCAL or USE_BRIDGE mode, 
+      // we want to act like a bridge and forward these PACKET_OTHERHOST 
+      // packets.
+      //
       return;
     }
 
   //
   // We have received a packet from the ns-3 net device that has been associated
-  // with this bridge.  We want to take these bits and send them off to the 
-  // Tap device on the Linux host.  Once we do this, the bits in the packet will
-  // percolate up through the stack on the Linux host.
+  // with this bridge.  We want to take these bits and send them off to the tap
+  // device on the Linux host.  The only question we have to answer is, what 
+  // should the destination address be?
+  //
+  // If we are in CONFIGURE_LOCAL mode, then the destination address is just
+  // left alone since it can only be the shared single MAC address, broadcast
+  // or multicast.
+  //
+  // If we are in USE_LOCAL mode, then we need to spoof the destination 
+  // address with the one we saved.
   //
-  // The ns-3 net device that is the source of these bits has removed the MAC 
-  // header, so we have to put one back on.  This is a callback and by convention
-  // uses Ptr<const Packet>, so we have to muck with a copy.
+  // If we are in USE_BRIDGE mode, then we need to do the equvalent of a 
+  // SendFrom and leave the source and destination alone.
   //
+  Mac48Address from = Mac48Address::ConvertFrom (src);
+  Mac48Address to;
+  if (m_mode == USE_LOCAL)
+    {
+      to = Mac48Address::ConvertFrom (m_learnedMac);
+    }
+  else 
+    {
+      to = Mac48Address::ConvertFrom (dst);
+    }
+
   Ptr<Packet> p = packet->Copy ();
   EthernetHeader header = EthernetHeader (false);
   header.SetSource (from);
   header.SetDestination (to);
+
   header.SetLengthType (protocol);
   p->AddHeader (header);
 
@@ -790,20 +958,6 @@
 }
 
 void 
-TapBridge::SetName(const std::string name)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_name = name;
-}
-
-std::string 
-TapBridge::GetName(void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-void 
 TapBridge::SetIfIndex(const uint32_t index)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -831,6 +985,20 @@
   return m_address;
 }
 
+  void 
+TapBridge::SetMode (enum Mode mode)
+{
+  NS_LOG_FUNCTION (mode);
+  m_mode = mode;
+}
+
+  TapBridge::Mode
+TapBridge::GetMode (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_mode;
+}
+  
 bool 
 TapBridge::SetMtu (const uint16_t mtu)
 {
--- a/src/devices/tap-bridge/tap-bridge.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/tap-bridge.h	Fri Apr 17 17:45:16 2009 +0200
@@ -38,57 +38,78 @@
 class Node;
 
 /**
- * \ingroup devices
- * \defgroup tap-bridge TapBridge
+ * \ingroup tap-bridge
  * 
- * \brief A bridge to make it appear that a host is connected to an ns-3 net device.
- *
- * The Tap Bridge lives in a kind of a gray world somewhere between a Linux host and
- * an ns-3 bridge device.  From the Linux perspective, this code appears as the user
- * mode handler for a Tap net device.  That is, when the Linux host writes to the
- * /dev/tap device that we create for it, the write is redirected into the TapBridge
- * and from that perspective, becomes a read.  The TapBridge then redirects the data
- * written (by the Linux host) to the tap device on out the ns-3 net device to which
- * we are bridged.  When a packet comes in from the ns-3 world to the ns-3 net device
- * we are bridging, it appears via a callback from that net device.  Our job is to
- * take those bits and write them back to the host using the user mode handler for
- * /dev/tapx.  This write to the device will then appear to the Linux host as if a 
- * packet has arrived on its device.
+ * \brief A bridge to make it appear that a real host process is connected to 
+ * an ns-3 net device.
  *
- * The upshot is that the Tap Bridge appears to bridge a tap device on a Linux host 
- * in the "real world" to an ns-3 net device in the simulation.  In order to do this
- * we need a "ghost node" in the simulation to hold the bridged ns-3 net device and 
- * this Tap Bridge.  This node will not be able to actually do anything else in the 
- * simulation with respect to the Tap Bridge and its bridged net device.  This is 
- * because:
- *
- * - Bits sent to the Tap Bridge using its Send() method are completely ignored.  
- *   The Tap Bridge is not, itself, connected to any network.
- * - The bridged ns-3 net device is has had its receive callback disconnected from
- *   the ns-3 node and reconnected to the Tap Bridge.  All data received by a 
- *   bridged device will be sent to the Linux host and will not be received by the
- *   node.  You can send but you cannot ever receive.
+ * The Tap Bridge lives in a kind of a gray world somewhere between a
+ * Linux host and an ns-3 bridge device.  From the Linux perspective,
+ * this code appears as the user mode handler for a Tap net device.  That
+ * is, when the Linux host writes to a /dev/tap device (that is either
+ * manually or automatically created depending on basic operating mode 
+ * -- more on this later), the write is redirected into the TapBridge that
+ * lives in the ns-3 world; and from this perspective, becomes a read.
+ * In other words, a Linux process writes a packet to a tap device and
+ * this packet is redirected to an ns-3 process where it is received by
+ * the TapBridge as a result of a read operation there.  The TapBridge
+ * then sends the packet to the ns-3 net device to which it is bridged.
+ * In the other direction, a packet received by an ns-3 net device is
+ * bridged to the TapBridge (it appears via a callback from that net
+ * device.  The TapBridge then takes that packet and writes it back to
+ * the host using the Linux TAP mechanism.  This write to the device will
+ * then appear to the Linux host as if a packet has arrived on its
+ * device.
  * 
- * You will be able to perform typical ns-3 operations on the ghost node if you so
- * desire.  The internet stack, for example, must be there and functional on that
- * node in order to participate in IP address assignment and global routing.
- * However, interfaces talking any Tap Bridge or associated bridged net devices 
- * will not work completely.  If you understand exactly what you are doing, you 
- * can set up other interfaces and devices on the ghost node and use them; but we 
- * generally recommend that you treat this node as a ghost of the Linux host and 
- * leave it alone.
+ * The upshot is that the Tap Bridge appears to bridge a tap device on a
+ * Linux host in the "real world" to an ns-3 net device in the simulation
+ * and make is appear that a ns-3 net device is actually installed in the
+ * Linux host.  In order to do this on the ns-3 side, we need a "ghost
+ * node" in the simulation to hold the bridged ns-3 net device and the
+ * TapBridge.  This node should not actually do anything else in the
+ * simulation since its job is simply to make the net device appear in
+ * Linux.  This is not just arbitrary policy, it is because:
+ *
+ * - Bits sent to the Tap Bridge from higher layers in the ghost node (using
+ *   the TapBridge Send() method) are completely ignored.  The Tap Bridge is 
+ *   not, itself, connected to any network, neither in Linux nor in ns-3;
+ * - The bridged ns-3 net device is has had its receive callback disconnected
+ *   from the ns-3 node and reconnected to the Tap Bridge.  All data received 
+ *   by a bridged device will be sent to the Linux host and will not be 
+ *   received by the node.  From the perspective of the ghost node, you can 
+ *   send over this device but you cannot ever receive.
+ *
+ * Of course, if you understand all of the issues you can take control of
+ * your own destiny and do whatever you want -- we do not actively
+ * prevent you from using the ghost node for anything you decide.  You
+ * will be able to perform typical ns-3 operations on the ghost node if
+ * you so desire.  The internet stack, for example, must be there and
+ * functional on that node in order to participate in IP address
+ * assignment and global routing.  However, as mentioned above,
+ * interfaces talking any Tap Bridge or associated bridged net devices
+ * will not work completely.  If you understand exactly what you are
+ * doing, you can set up other interfaces and devices on the ghost node
+ * and use them; or take advantage of the operational send side of the
+ * bridged devices to create traffic generators.  We generally recommend
+ * that you treat this node as a ghost of the Linux host and leave it to
+ * itself, though.
  */
-
-/**
- * \ingroup tap-bridge
- * \brief A bridge to make it appear that a host is connected to an ns-3 net device.
- */
-
 class TapBridge : public NetDevice
 {
 public:
   static TypeId GetTypeId (void);
 
+  /**
+   * Enumeration of the operating modes supported in the class.
+   *
+   */
+  enum Mode {
+    ILLEGAL,         /**< mode not set */
+    CONFIGURE_LOCAL, /**< ns-3 creates and configures tap device */
+    USE_LOCAL,       /**< ns-3 uses a pre-created tap, without configuring it */
+    USE_BRIDGE, /**< ns-3 uses a pre-created tap, and bridges to a bridging net device */
+  };
+
   TapBridge ();
   virtual ~TapBridge ();
 
@@ -134,12 +155,24 @@
    */
   void Stop (Time tStop);
 
+  /**
+   * Set the operating mode of this device.
+   *
+   * \param mode The operating mode of this device.
+   */
+  void SetMode (TapBridge::Mode mode);
+
+  /**
+   * Get the operating mode of this device.
+   *
+   * \returns The operating mode of this device.
+   */
+  TapBridge::Mode  GetMode (void);
+
   //
   // The following methods are inherited from NetDevice base class and are
   // documented there.
   //
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -283,12 +316,6 @@
    */
   Ptr<Node> m_node;
 
-  /**
-   * \internal
-   *
-   * A possible name for the (ghost) Node to which we are connected.
-   */
-  std::string m_name;
 
   /**
    * \internal
@@ -338,13 +365,19 @@
 
   /**
    * \internal
+   *     
+   * The operating mode of the bridge.  Tells basically who creates and
+   * configures the underlying network tap.
+   */
+  Mode m_mode;
+
+  /**
+   * \internal
    *
    * The (unused) MAC address of the TapBridge net device.  Since the TapBridge
    * is implemented as a ns-3 net device, it is required to implement certain
    * functionality.  In this case, the TapBridge is automatically assigned a
-   * MAC address, but it is not used.  The MAC address assigned to the internet
-   * host actually comes from the bridged (N.B. the "ed") device and not from 
-   * the bridge device.
+   * MAC address, but it is not used.
    */
   Mac48Address m_address;
 
@@ -386,7 +419,11 @@
   /**
    * \internal
    *
-   * The MAC address to use as the hardware address on the host.
+   * The MAC address to use as the hardware address on the host; only used
+   * in UseLocal mode.  This value comes from the MAC  
+   * address assigned to the bridged ns-3 net device and matches the MAC 
+   * address of the underlying network TAP which we configured to have the 
+   * same value.
    */
   Mac48Address m_tapMac;
 
@@ -403,6 +440,17 @@
    * The ns-3 net device to which we are bridging.
    */
   Ptr<NetDevice> m_bridgedDevice;
+  /**
+   * \internal
+   *
+   * The MAC address of the local tap device is stored in this variable.
+   * When in UseLocal mode, this address is added back to the destination 
+   * Mac address for frames destined to the tap device.  It is learned from
+   * the first frame sent from the host to the TapBridge device.  In the
+   * other modes of this device, this value is unused.  
+   */
+  Mac48Address m_learnedMac;
+
 };
 
 } // namespace ns3
--- a/src/devices/tap-bridge/tap-creator.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/tap-creator.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -29,17 +29,10 @@
 #include <sys/ioctl.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-#if 0
-#include <linux/un.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <linux/route.h>
-#else
 #include <sys/un.h>
 #include <net/if.h>
 #include <linux/if_tun.h>
 #include <net/route.h>
-#endif
 #include <netinet/in.h>
 
 #include "tap-encode-decode.h"
@@ -145,13 +138,17 @@
     }
 }
 
-static void
-SetInetAddress (sockaddr *ad, uint32_t networkOrder)
+static sockaddr
+CreateInetAddress (uint32_t networkOrder)
 {
-  struct sockaddr_in *sin = (struct sockaddr_in*)ad;
-  sin->sin_family = AF_INET;
-  sin->sin_port = 0; // unused
-  sin->sin_addr.s_addr = htonl (networkOrder);
+  union {
+    struct sockaddr any_socket;
+    struct sockaddr_in si;
+  } s;
+  s.si.sin_family = AF_INET;
+  s.si.sin_port = 0; // unused
+  s.si.sin_addr.s_addr = htonl (networkOrder);
+  return s.any_socket;
 }
 
   static void
@@ -277,7 +274,7 @@
 }
 
   static int
-CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, const char *netmask)
+CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, const char *mode, const char *netmask)
 {
   //
   // Creation and management of Tap devices is done via the tun device
@@ -288,7 +285,9 @@
   //
   // Allocate a tap device, making sure that it will not send the tun_pi header.
   // If we provide a null name to the ifr.ifr_name, we tell the kernel to pick
-  // a name for us (i.e., tapn where n = 0..255
+  // a name for us (i.e., tapn where n = 0..255.
+  //
+  // If the device does not already exist, the system will create one.
   //
   struct ifreq ifr;
   ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
@@ -300,6 +299,18 @@
   LOG ("Allocated TAP device " << tapDeviceName);
 
   //
+  // Operating mode "2" corresponds to USE_LOCAL and "3" to USE_BRIDGE mode.  
+  // This means that we expect that the user will have named, created and 
+  // configured a network tap that we are just going to use.  So don't mess 
+  // up his hard work by changing anything, just return the tap fd.
+  //
+  if (strcmp (mode, "2") == 0 || strcmp (mode, "3") == 0)
+    {
+      LOG ("Returning precreated tap ");
+      return tap;
+    }
+
+  //
   // Set the hardware (MAC) address of the new device
   //
   ifr.ifr_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
@@ -323,7 +334,7 @@
   //
   // Set the IP address of the new interface/device.
   //
-  SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
+  ifr.ifr_addr = CreateInetAddress (AsciiToIpv4 (ip));
   status = ioctl (fd, SIOCSIFADDR, &ifr);
   ABORT_IF (status == -1, "Could not set IP address", true);
   LOG ("Set device IP address to " << ip);
@@ -331,7 +342,7 @@
   //
   // Set the net mask of the new interface/device
   //
-  SetInetAddress (&ifr.ifr_netmask, AsciiToIpv4 (netmask));
+  ifr.ifr_netmask = CreateInetAddress (AsciiToIpv4 (netmask));
   status = ioctl (fd, SIOCSIFNETMASK, &ifr);
   ABORT_IF (status == -1, "Could not set net mask", true);
   LOG ("Set device Net Mask to " << netmask);
@@ -348,31 +359,35 @@
   char *ip = NULL;
   char *mac = NULL;
   char *netmask = NULL;
+  char *operatingMode = NULL;
   char *path = NULL;
 
   opterr = 0;
 
-  while ((c = getopt (argc, argv, "vd:g:i:m:n:p:")) != -1)
+  while ((c = getopt (argc, argv, "vd:g:i:m:n:o:p:")) != -1)
     {
       switch (c)
         {
         case 'd':
-          dev = optarg;     // name of the new tap device
+          dev = optarg;           // name of the new tap device
           break;
         case 'g':
-          gw = optarg;      // gateway address for the new device
+          gw = optarg;            // gateway address for the new device
           break;
         case 'i':
-          ip = optarg;      // ip address of the new device
+          ip = optarg;            // ip address of the new device
           break;
         case 'm':
-          mac = optarg;     // mac address of the new device
+          mac = optarg;           // mac address of the new device
           break;
         case 'n':
-          netmask = optarg; // net mask for the new device
+          netmask = optarg;       // net mask for the new device
+          break;
+        case 'o':
+          operatingMode = optarg; // operating mode of tap bridge
           break;
         case 'p':
-          path = optarg;    // path back to the tap bridge
+          path = optarg;          // path back to the tap bridge
           break;
         case 'v':
           gVerbose = true;
@@ -422,6 +437,12 @@
   LOG ("Provided Net Mask is \"" << netmask << "\"");
 
   //
+  // We have got to know whether or not to create the TAP.
+  //
+  ABORT_IF (operatingMode == NULL, "Operating Mode is a required argument", 0);
+  LOG ("Provided Operating Mode is \"" << operatingMode << "\"");
+
+  //
   // This program is spawned by a tap bridge running in a simulation.  It
   // wants to create a socket as described below.  We are going to do the
   // work here since we're running suid root.  Once we create the socket,
@@ -444,7 +465,7 @@
   // us to exeucte the following code:
   //
   LOG ("Creating Tap");
-  int sock = CreateTap (dev, gw, ip, mac, netmask);
+  int sock = CreateTap (dev, gw, ip, mac, operatingMode, netmask);
   ABORT_IF (sock == -1, "main(): Unable to create tap socket", 1);
 
   //
--- a/src/devices/tap-bridge/tap-encode-decode.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/tap-encode-decode.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -20,6 +20,7 @@
 #include <iostream>
 #include <iomanip>
 #include <sstream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/devices/tap-bridge/tap.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/tap.h	Fri Apr 17 17:45:16 2009 +0200
@@ -6,46 +6,281 @@
  *
  * The Tap Bridge is designed to integrate "real" internet hosts (or more 
  * precisely, hosts that support Tun/Tap devices) into ns-3 simulations.  The 
- * goal is to make it appear to the host host node in question that it has an
- * ns-3 net device as a local device.  The concept of a "real host" is a bit
- * slippery the "real host" may actually be virtualized using readily avialable
+ * goal is to make it appear to a "real" host node in that it has an ns-3 net
+ * device as a local device.  The concept of a "real host" is a bit slippery
+ * since the "real host" may actually be virtualized using readily avialable
  * technologies such as VMware or OpenVZ.
  *
  * Since we are, in essence, connecting the inputs and outputs of an ns-3 net 
  * device to the inputs and outputs of a Linux Tap net device, we call this 
  * arrangement a Tap Bridge.
  *
- * The TapBridge appears to the Linux host computer as a network device just
- * like any arbitrary "eth0" or "ath0" might appear.  The creation and
- * configuration of the device is done by the ns-3 simulation, however.  You 
- * should not expect to be able to configure a net device via, for example,
- * wlanconfig.  The IP addresses, MAC addresses, gateway, etc., for the given
- * Tap device are also set up by the ns-3 simulation.  If you change the
- * or manipulate the configuration manually, you will almost certainly break
- * the simulation.
+ * There are two basic operating modes of this device available to users.  
+ * Basic functionality is essentially identical, but the two modes are 
+ * different in details regarding how the arrangement is configured.  In the
+ * first mode, the configuration is ns-3 configuration-centric.  Configuration
+ * information is taken from the ns-3 simulation and a tap device matching
+ * the ns-3 attributes is created for you.  In this mode, which we call 
+ * LocalDevice mode, an ns-3 net device is made to appear to be directly 
+ * connected to a real host.  
+ * 
+ * This is illustrated below
+ *
+ * \verbatim
+ *     +--------+
+ *     |  Linux |
+ *     |  host  |                    +----------+
+ *     | ------ |                    |   ghost  |
+ *     |  apps  |                    |   node   |
+ *     | ------ |                    | -------- |
+ *     |  stack |                    |    IP    |     +----------+
+ *     | ------ |                    |   stack  |     |   node   |
+ *     |  TAP   |                    |==========|     | -------- |
+ *     | device | <-- IPC Bridge --> |   tap    |     |    IP    |
+ *     +--------+                    |  bridge  |     |   stack  |
+ *                                   | -------- |     | -------- |
+ *                                   |   ns-3   |     |   ns-3   |
+ *                                   |   net    |     |   net    |
+ *                                   |  device  |     |  device  |
+ *                                   +----------+     +----------+
+ *                                        ||               ||
+ *                                   +---------------------------+
+ *                                   |        ns-3 channel       |
+ *                                   +---------------------------+
+ *\endverbatim
+ *
+ * In this case, the ns-3 net device in the ghost node appears as if it were 
+ * actually replacing the TAP device in the Linux host.  The ns-3 process 
+ * creates the TAP device configures the IP address and MAC address of the 
+ * TAP device to match the values assigned to the ns-3 net device.  The IPC 
+ * link is via the network tap mechanism in the underlying OS and acts as a 
+ * conventional bridge; but a bridge between devices that happen to have the 
+ * same shared MAC address.
+ *
+ * The LocalDevice mode is the default operating mode of the Tap Bridge.
+ *
+ * The second mode, BridgedDevice mode, is more oriented toward allowing existing
+ * host configurations.  This allows ns-3 net devices to appear as part of a host
+ * operating system bridge (in Linux, we make the ns-3 device part of a "brctl"
+ * bridge.  This mode is especially  useful in the case of virtualization where 
+ * the configuration of the virtual hosts may be dictated by another system and 
+ * not be changable to suit ns-3.  For example, a particular VM scheme may create
+ * virtual "vethx" or "vmnetx" devices that appear local to virtual hosts.  In 
+ * order to connect to such systems, one would need to manually create TAP devices
+ * on the host system and brigde these TAP devices to the existing (VM) virtual 
+ * devices.  The job of the Tap Bridge in this case is to extend the bridge to
+ * join the ns-3 net device.
+ *
+ * This is illustrated below:
+ *
+ * \verbatim
+ *     +---------+
+ *     |  Linux  |
+ *     |   VM    |                             +----------+
+ *     | ------- |                             |   ghost  |
+ *     |  apps   |                             |   node   |
+ *     | ------- |                             | -------- |
+ *     |  stack  |                             |    IP    |     +----------+
+ *     | ------- | +--------+                  |   stack  |     |   node   |
+ *     | Virtual | |  TAP   |                  |==========|     | -------- |
+ *     | Device  | | Device | <-- IPC Bridge-> |   tap    |     |    IP    |
+ *     +---------+ +--------+                  |  bridge  |     |   stack  |
+ *         ||          ||                      | -------- |     | -------- |
+ *     +--------------------+                  |   ns-3   |     |   ns-3   |
+ *     | OS (brctl) Bridge  |                  |   net    |     |   net    |
+ *     +--------------------+                  |  device  |     |  device  |
+ *                                             +----------+     +----------+
+ *                                                  ||               ||
+ *                                             +---------------------------+
+ *                                             |        ns-3 channel       |
+ *                                             +---------------------------+
+ *\endverbatim
+ *
+ * In this case, a collection of virtual machines with associated Virtual
+ * Devices is created in the virtualization environment (for exampe, OpenVZ
+ * or VMware).  A TAP device (with a specific name) is then manually created 
+ * for each Virtual Device that will be bridged into the ns-3 simulation.
+ * These created TAP devices are then bridged together with the Virtual Devices
+ * using a native OS bridge mechanism shown as "OS (brctl) Bridge" in the 
+ * illustration above.
+ *
+ * In the ns-3 simulation, a Tap Bridge is created to match each TAP Device.
+ * The name of the TAP Device is assigned to the Tap Bridge using the 
+ * "DeviceName" attribute.  The Tap Bridge then opens a network tap to the TAP 
+ * Device and logically extends the bridge to encompass the ns-3 net device.  
+ * This makes it appear as if an ns-3 simulated net device is a member of the 
+ * "OS (brctl) Bridge" and allows the Virtual Machines to communicate with the 
+ * ns-3 simulation..
+ *
+ * \subsection TapBridgeLocalDeviceMode TapBridge LocalDevice Mode
+ * 
+ * In LocalDevice mode, the TapBridge and therefore its associated ns-3 net
+ * device appears to the Linux host computer as a network device just like any
+ * arbitrary "eth0" or "ath0" might appear.  The creation and configuration 
+ * of the TAP device is done by the ns-3 simulation and no manual configuration
+ * is required by the user.  The IP addresses, MAC addresses, gateways, etc., 
+ * for created TAP devices are extracted from the simulation itself by querying
+ * the configuration of the ns-3 device and the TapBridge Attributes.
  *
  * The TapBridge appears to an ns-3 simulation as a channel-less net device.
- * This device, however, must _not_ have an IP address associated with it.  
- * Be aware that this is the inverse situation of an ns-3 BridgeNetDevice
- * which demands that its bridge ports not have IP addresses, but allows the
- * bridge to have an IP address.  
+ * This device must not have an IP address associated with it, but the bridged
+ * (ns-3) net device must have an IP adress.  Be aware that this is the inverse
+ * of an ns-3 BridgeNetDevice (or a conventional bridge in general) which 
+ * demands that its bridge ports not have IP addresses, but allows the bridge 
+ * device itself to have an IP address.  
  *
  * The host computer will appear in a simulation as a "ghost" node that contains
- * pairs of net devices and Tap bridges that represent the host devices.  From
- * the perspective of a simulation, the only difference between a ghost node and
- * another node will be the presence of the TapBridge devices that connect to
- * the hosts.  Configuration of address information and the ns-3 devices is
- * not changed in any way.  A TapBridge will pick up the addressing info from
- * the ns-3 net device to which it is connected (its "bridged" net device) and
- * use that information to configure the device on the real host.
+ * one TapBridge for each NetDevice that is being bridged.  From the perspective
+ * of a simulation, the only difference between a ghost node and any other node 
+ * will be the presence of the TapBridge devices.  Note however, that the 
+ * presence of the TapBridge does affect the connectivity of the net device to 
+ * the IP stack of the ghost node.
+ *
+ * Configuration of address information and the ns-3 devices is not changed in 
+ * any way if a TapBridge is present.  A TapBridge will pick up the addressing
+ * information from the ns-3 net device to which it is connected (its "bridged"
+ * net device) and use that information to create and configure the TAP device
+ * on the real host.
  *
  * The end result of this is a situation where one can, for example, use the
- * standard ping utility on a real host to ping a simulated ns-3 net device.  If
- * correct routes are added to the internet host, the routing systems in ns-3
- * will enable correct routing of the packets across simulated ns-3 networks.
- * For an example of this, see the example program, tap-dumbbell.cc in the 
- * ns-3 distribution.
+ * standard ping utility on a real host to ping a simulated ns-3 node.  If
+ * correct routes are added to the internet host (this is expected to be done
+ * automatically in future ns-3 releases), the routing systems in ns-3 will
+ * enable correct routing of the packets across simulated ns-3 networks.
+ * For an example of this, see the example program, tap-wifi-dumbbell.cc in 
+ * the ns-3 distribution.
+ *
+ * \subsection TapBridgeLocalDeviceModeOperation TapBridge LocalDevice Mode Operation
+ *
+ * The Tap Bridge lives in a kind of a gray world somewhere between a Linux host
+ * and an ns-3 bridge device.  From the Linux perspective, this code appears as
+ * the user mode handler for a TAP net device.  In LocalDevice mode, this TAP 
+ * device is automatically created by the ns-3 simulation.  When the Linux host 
+ * writes to one of these automatically created /dev/tap devices, the write is 
+ * redirected into the TapBridge that lives in the ns-3 world; and from this 
+ * perspective, the packet write on Linux becomes a packet read in the Tap Bridge.
+ * In other words, a Linux process writes a packet to a tap device and this packet
+ * is redirected by the network tap mechanism toan ns-3 process where it is 
+ * received by the TapBridge as a result of a read operation there.  The TapBridge
+ * then writes the packet to the ns-3 net device to which it is bridged; and 
+ * therefore it appears as if the Linux host sent a packet directly through an 
+ * ns-3 net device onto an ns-3 network.
+ *
+ * In the other direction, a packet received by the ns-3 net device connected to
+ * the Tap Bridge is sent via promiscuous callback to the TapBridge.  The 
+ * TapBridge then takes that packet and writes it back to the host using the 
+ * network tap mechanism.  This write to the device will appear to the Linux 
+ * host as if a packet has arrived on its device; and therefore as if a packet
+ * received by the ns-3 net device has appeared on a Linux net device.
+ * 
+ * The upshot is that the Tap Bridge appears to bridge a tap device on a
+ * Linux host in the "real world" to an ns-3 net device in the simulation.
+ * Because the TAP device and the bridged ns-3 net device have the same MAC
+ * address and the network tap IPC link is not exernalized, this particular
+ * kind of bridge makes ti appear that a ns-3 net device is actually installed
+ * in the Linux host.
+ *
+ * In order to implement this on the ns-3 side, we need a "ghost node" in the
+ * simulation to hold the bridged ns-3 net device and the TapBridge.  This node
+ * should not actually do anything else in the simulation since its job is 
+ * simply to make the net device appear in Linux.  This is not just arbitrary 
+ * policy, it is because:
+ *
+ * - Bits sent to the Tap Bridge from higher layers in the ghost node (using
+ *   the TapBridge Send method) are completely ignored.  The Tap Bridge is 
+ *   not, itself, connected to any network, neither in Linux nor in ns-3.  You
+ *   can never send nor receive data over a Tap Bridge from the ghost node.
+ *
+ * - The bridged ns-3 net device has its receive callback disconnected
+ *   from the ns-3 node and reconnected to the Tap Bridge.  All data received 
+ *   by a bridged device will then be sent to the Linux host and will not be 
+ *   received by the node.  From the perspective of the ghost node, you can 
+ *   send over this device but you cannot ever receive.
+ *
+ * Of course, if you understand all of the issues you can take control of
+ * your own destiny and do whatever you want -- we do not actively
+ * prevent you from using the ghost node for anything you decide.  You
+ * will be able to perform typical ns-3 operations on the ghost node if
+ * you so desire.  The internet stack, for example, must be there and
+ * functional on that node in order to participate in IP address
+ * assignment and global routing.  However, as mentioned above,
+ * interfaces talking any Tap Bridge or associated bridged net devices
+ * will not work completely.  If you understand exactly what you are
+ * doing, you can set up other interfaces and devices on the ghost node
+ * and use them; or take advantage of the operational send side of the
+ * bridged devices to create traffic generators.  We generally recommend
+ * that you treat this node as a ghost of the Linux host and leave it to
+ * itself, though.
  *
+ * \subsection TapBridgeBridgedDeviceMode TapBridge BridgedDevice Mode
+ * 
+ * In BridgedDevice mode, the TapBridge and its associated ns-3 net device are
+ * arranged in a fundamentally similar was as in LocalDevice mode.  The TAP
+ * device is bridged to the ns-3 net device in the same way.  The description
+ * of LocalDevice mode applies except as noted below.
+ *
+ * The most user-visible difference in modes is how the creation and 
+ * configuration of the underlying TAP device is done.  In LocalDevice mode,
+ * both creation and configuration of the underlying TAP device are handled 
+ * completely by ns-3.  In BridgedDevice mode, creation and configuration is
+ * delegated (due to requirements) to the user.  No configuration is done in
+ * ns-3 other than settting the operating mode of the TapBridge to 
+ * "BridgedDevice" and specifying the name of a pre-configured TAP device
+ * using ns-3 Attributes of the TapBridge.
+ *
+ * The primary conceptual difference between modes is due to the fact that in 
+ * BridgedDevice mode the MAC addresses of the user-created TAPs will be pre-
+ * configured and will therefore be different than those in the bridged device.
+ * As in LocalDevice mode, the Tap Bridge functions as IPC bridge between the
+ * TAP device and the ns-3 net device, but in BridgedDevice configurations the
+ * two devices will have different MAC addresses and the bridging functionality
+ * will be fundamentally the same as in any bridge.  Since this implies MAC
+ * address spoofing, the only ns-3 devices which may paritcipate in a bridge
+ * in BridgedDevice mode must support SendFrom (i.e., a call to the method
+ * SupportsSendFrom in the bridged net device must return true).
+ *
+ * \subsection TapBridgeBridgedDeviceModeOperation TapBridge BridgedDevice Mode Operation
+ *
+ * As described in the LocalDevice mode section, when the Linux host writes to 
+ * one of the /dev/tap devices, the write is redirected into the TapBridge
+ * that lives in the ns-3 world.  In the case of the BridgedDevice mode, these
+ * packets will need to be sent out on the ns-3 network as if they were sent on
+ * the Linux network.  This means calling the SendFrom method on the bridged
+ * device and providing the source and destination MAC addresses found in the
+ * packet.
+ *
+ * In the other direction, a packet received by an ns-3 net device is hooked
+ * via callback to the TapBridge.  This must be done in promiscuous mode since
+ * the goal is to bridge the ns-3 net device onto the OS (brctl) bridge of 
+ * which the TAP device is a part.
+ *
+ * There is no functional difference between modes at this level, even though
+ * the configuration and conceptual models regarding what is going on are quite
+ * different -- the Tap Bridge is just acting like a bridge.  In the LocalDevice
+ * mode, the bridge is between devices having the same MAC address and in the 
+ * BridgedDevice model the bridge is between devices having different MAC 
+ * addresses.
+ *
+ * \subsection TapBridgeSingleSourceModeOperation TapBridge SingleSource Mode Operation
+ *
+ * As described in above, the Tap Bridge acts like a bridge.  Just like every
+ * other bridge, there is a requirement that participating devices must have
+ * the ability to receive promiscuously and to spoof the source MAC addresses
+ * of packets.
+ *
+ * We do, however, have a specific requirement to be able to bridge Virtual 
+ * Machines onto wireless STA nodes.  Unfortunately, the 802.11 spec doesn't
+ * provide a good way to implement SendFrom.  So we have to work around this.
+ * 
+ * To this end, we provice the SingleSource mode of the Tap Bridge.  This
+ * mode allows you to create a bridge as described in BridgedDevice mode, but
+ * only allows one source of packets on the Linux side of the bridge.  The
+ * address on the Linux side is remembered in the Tap Bridge, and all packets
+ * coming from the Linux side are repeated out the ns-3 side using the ns-3 device
+ * MAC source address.  All packets coming in from the ns-3 side are repeated
+ * out the Linux side using the remembered MAC address.  This allows us to use
+ * SendFrom on the ns-3 device side which is available on all ns-3 net devices.
+ * 
  * \section TapBridgeChannelModel Tap Bridge Channel Model
  *
  * There is no channel model associated with the Tap Bridge.  In fact, the
--- a/src/devices/tap-bridge/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/tap-bridge/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -27,6 +27,7 @@
         module.source.extend([
                 'tap-bridge.cc',
                 'tap-encode-decode.cc',
+                'tap-creator.cc',
                 ])
         headers.source.extend([
                 'tap-bridge.h',
--- a/src/devices/wifi/aarf-wifi-manager.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/aarf-wifi-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -71,39 +71,34 @@
 WifiRemoteStation *
 AarfWifiManager::CreateStation (void)
 {
-  return new AarfWifiRemoteStation (this, m_minTimerThreshold,
-                                    m_minSuccessThreshold,
-                                    m_successK,
-                                    m_maxSuccessThreshold,
-                                    m_timerK);
+  return new AarfWifiRemoteStation (this);
 }
 
 
 
 
-AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
-                                              uint32_t minTimerThreshold,
-                                              uint32_t minSuccessThreshold,
-                                              double successK,
-                                              uint32_t maxSuccessThreshold,
-                                              double timerK)
-  : ArfWifiRemoteStation (stations, minTimerThreshold, minSuccessThreshold),
-    m_successK (successK),
-    m_maxSuccessThreshold (maxSuccessThreshold),
-    m_timerK (timerK)
+AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> manager)
+  : ArfWifiRemoteStation (manager),
+    m_manager (manager)
 {}
 
 
 AarfWifiRemoteStation::~AarfWifiRemoteStation ()
 {}
 
+Ptr<WifiRemoteStationManager> 
+AarfWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
 void 
 AarfWifiRemoteStation::ReportRecoveryFailure (void)
 {
-  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_successK,
-                                  m_maxSuccessThreshold)));
+  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_manager->m_successK,
+                                  m_manager->m_maxSuccessThreshold)));
   SetTimerTimeout ((int)(Max (GetMinTimerTimeout (),
-                              GetSuccessThreshold () * m_timerK)));
+                              GetSuccessThreshold () * m_manager->m_timerK)));
 }
 
 void 
--- a/src/devices/wifi/aarf-wifi-manager.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/aarf-wifi-manager.h	Fri Apr 17 17:45:16 2009 +0200
@@ -17,8 +17,8 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#ifndef AARF_MAC_STATIONS_H
-#define AARF_MAC_STATIONS_H
+#ifndef AARF_WIFI_MANAGER_H
+#define AARF_WIFI_MANAGER_H
 
 #include "arf-wifi-manager.h"
 
@@ -39,6 +39,7 @@
   AarfWifiManager ();
   virtual ~AarfWifiManager ();
 private:
+  friend class AarfWifiRemoteStation;
   virtual class WifiRemoteStation *CreateStation (void);
   uint32_t m_minTimerThreshold;
   uint32_t m_minSuccessThreshold;
@@ -50,24 +51,18 @@
 class AarfWifiRemoteStation : public ArfWifiRemoteStation
 {
 public:
-  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
-                         uint32_t minTimerThreshold,
-                         uint32_t minSuccessThreshold,
-                         double successK,
-                         uint32_t maxSuccessThreshold,
-                         double timerK);
+  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations);
   virtual ~AarfWifiRemoteStation ();
 
 private:
   virtual void ReportRecoveryFailure (void);
   virtual void ReportFailure (void);
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
 
-  double m_successK;
-  uint32_t m_maxSuccessThreshold;
-  double m_timerK;
+  Ptr<AarfWifiManager> m_manager;
 };
 
 } // namespace ns3
 
 
-#endif /* AARF_MAC_STATIONS_H */
+#endif /* AARF_WIFI_MANAGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarfcd-wifi-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -0,0 +1,410 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+
+#include "aarfcd-wifi-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/boolean.h"
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("Aarfcd");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(AarfcdWifiManager);
+
+AarfcdWifiRemoteStation::AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager)
+  : m_manager (manager)
+{
+  m_timerTimeout = m_manager->m_minTimerThreshold;
+  m_successThreshold = m_manager->m_minSuccessThreshold;
+  m_rate = GetMinRate ();
+
+  m_success = 0;
+  m_failed = 0;
+  m_recovery = false;
+  m_retry = 0;
+  m_timer = 0;
+  m_rtsOn = false;
+  m_rtsWnd = m_manager->m_minRtsWnd;
+  m_rtsCounter = 0;
+  m_justModifyRate = true;
+  m_haveASuccess = false;
+}
+AarfcdWifiRemoteStation::~AarfcdWifiRemoteStation ()
+{}
+
+uint32_t
+AarfcdWifiRemoteStation::GetMaxRate (void)
+{
+  return GetNSupportedModes () - 1;
+}
+uint32_t
+AarfcdWifiRemoteStation::GetMinRate (void)
+{
+  return 0;
+}
+
+void
+AarfcdWifiRemoteStation::ReportRecoveryFailure (void)
+{
+  m_successThreshold = (int)(std::min ((uint32_t)(m_successThreshold * m_manager->m_successK),
+                                       m_manager->m_maxSuccessThreshold));
+  m_timerTimeout = (int)(std::max (m_manager->m_minTimerThreshold,
+                                   (uint32_t)(m_successThreshold * m_manager->m_timerK)));
+}
+
+void
+AarfcdWifiRemoteStation::ReportFailure (void)
+{
+  m_timerTimeout = m_manager->m_minTimerThreshold;
+  m_successThreshold = m_manager->m_minSuccessThreshold;
+}
+
+bool 
+AarfcdWifiRemoteStation::NeedRecoveryFallback (void)
+{
+  if (m_retry >= 1) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+bool 
+AarfcdWifiRemoteStation::NeedNormalFallback (void)
+{
+  int retryMod = (m_retry - 1) % 2;
+  if (retryMod == 1) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+
+
+void 
+AarfcdWifiRemoteStation::DoReportRtsFailed (void)
+{
+  //printf ("%.9f %p RtsFail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  NS_LOG_INFO ("" << this << " RtsFail rate=" << m_rate);
+  if (m_manager->m_rtsFailsAsDataFails)
+    {
+      m_rtsCounter--;
+      ReportDataFailed ();
+    }
+}
+/**
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode transcends retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void 
+AarfcdWifiRemoteStation::DoReportDataFailed (void)
+{
+  NS_LOG_INFO ("" << this << " TxFail rate=" << m_rate);
+  m_timer++;
+  m_failed++;
+  m_retry++;
+  m_success = 0;
+  //printf ("%.9f %p Fail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  if (!m_rtsOn) 
+    {
+      TurnOnRts ();
+      if (!m_justModifyRate && !m_haveASuccess) 
+        {
+          //printf ("%p Increase RTS Windows\n",this);
+          IncreaseRtsWnd ();
+        }
+      else 
+        {
+          //printf ("%p Reset RTS Window\n",this);
+          ResetRtsWnd ();
+        }
+      m_rtsCounter = m_rtsWnd;
+      if (m_retry >= 2) 
+        {
+          m_timer = 0;
+        }
+      //printf ("%.9f %p AtcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
+    }
+  else if (m_recovery) 
+    {
+      NS_ASSERT (m_retry >= 1);
+      m_justModifyRate = false;
+      m_rtsCounter = m_rtsWnd;
+      if (NeedRecoveryFallback ()) 
+        {
+          if (m_manager->m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts ();
+            }
+          m_justModifyRate = true;
+          ReportRecoveryFailure ();
+          if (m_rate != GetMinRate ()) 
+            {
+              m_rate--;
+            }
+          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
+          //printf ("%.9f %p DecreaseRateRecovery %d\n", Simulator::Now ().GetSeconds (),this, m_rate);
+        }
+      m_timer = 0;
+    } 
+  else 
+    {
+      NS_ASSERT (m_retry >= 1);
+      m_justModifyRate = false;
+      m_rtsCounter = m_rtsWnd;
+      if (NeedNormalFallback ()) 
+        {
+          if (m_manager->m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts ();
+            }
+          m_justModifyRate = true;
+          ReportFailure ();
+          if (m_rate != GetMinRate ()) 
+            {
+              m_rate--;
+            }
+          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
+          //printf ("%.9f %p DecreaseRate %d\n", Simulator::Now ().GetSeconds (),this,m_rate);
+        }
+      if (m_retry >= 2) 
+        {
+          m_timer = 0;
+        }
+    }
+  CheckRts ();
+}
+void 
+AarfcdWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+AarfcdWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_INFO ("" << this << " RtsOk rate=" << m_rate);
+  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+  m_rtsCounter--;
+}
+void 
+AarfcdWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  NS_LOG_INFO ("" << this << " TxOk rate=" << m_rate);
+  m_timer++;
+  m_success++;
+  m_failed = 0;
+  m_recovery = false;
+  m_retry = 0;
+  m_justModifyRate = false;
+  m_haveASuccess = true;
+  //printf ("%.9f %p Ok %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  //printf ("%p OK (m_success=%d, th=%d, m_rate=%d, maxRate=%d)\n",this,m_success,GetSuccessThreshold (), m_rate, GetMaxRate ());
+  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
+  if ((m_success == m_successThreshold ||
+       m_timer >= m_timerTimeout) &&
+      (m_rate < GetMaxRate ())) 
+    {
+      NS_LOG_DEBUG ("self="<<this<<" inc rate");
+      m_rate++;
+      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
+      m_timer = 0;
+      m_success = 0;
+      m_recovery = true;
+      m_justModifyRate = true;
+      if (m_manager->m_turnOnRtsAfterRateIncrease) 
+        {
+          TurnOnRts ();
+          ResetRtsWnd ();
+          m_rtsCounter = m_rtsWnd;
+        }
+      //printf ("%.9f %p IncreaseRate %d %d\n", Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
+    }
+  else if (m_success == m_successThreshold ||
+           m_timer >= m_timerTimeout) 
+    {
+      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
+    }
+  CheckRts ();
+}
+void 
+AarfcdWifiRemoteStation::DoReportFinalRtsFailed (void)
+{}
+void 
+AarfcdWifiRemoteStation::DoReportFinalDataFailed (void)
+{}
+
+WifiMode
+AarfcdWifiRemoteStation::DoGetDataMode (uint32_t size)
+{
+  return GetSupportedMode (m_rate);
+}
+WifiMode
+AarfcdWifiRemoteStation::DoGetRtsMode (void)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupportedMode (0);
+}
+
+Ptr<WifiRemoteStationManager>
+AarfcdWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
+void
+AarfcdWifiRemoteStation::CheckRts (void)
+{
+  if (m_rtsCounter == 0 && m_rtsOn) 
+    {
+      //printf ("%p Turn off RTS\n",this);
+      TurnOffRts ();
+    }
+}
+
+void
+AarfcdWifiRemoteStation::TurnOffRts (void)
+{
+  //printf ("%.9f %p DeatcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
+  m_rtsOn = false;
+  m_haveASuccess = false;
+}
+
+void
+AarfcdWifiRemoteStation::TurnOnRts (void)
+{
+  m_rtsOn = true;
+}
+
+void
+AarfcdWifiRemoteStation::IncreaseRtsWnd (void)
+{
+  if (m_rtsWnd == m_manager->m_maxRtsWnd)
+    {
+      return;
+    }
+
+  m_rtsWnd *= 2;
+  if (m_rtsWnd > m_manager->m_maxRtsWnd)
+    {
+      m_rtsWnd = m_manager->m_maxRtsWnd;
+    }
+}
+
+void
+AarfcdWifiRemoteStation::ResetRtsWnd (void)
+{
+  m_rtsWnd = m_manager->m_minRtsWnd;
+}
+
+bool
+AarfcdWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
+{
+  //printf ("%.9f %p NeedRts %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
+  NS_LOG_INFO ("" << this << " rate=" << m_rate << " rts=" << (m_rtsOn?"RTS":"BASIC") << " rtsCounter=" << m_rtsCounter);
+  return m_rtsOn;
+}
+
+
+
+
+
+TypeId 
+AarfcdWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::AarfcdWifiManager")
+    .SetParent<WifiRemoteStationManager> ()
+    .AddConstructor<AarfcdWifiManager> ()
+    .AddAttribute ("SuccessK", "Multiplication factor for the success threshold in the AARF algorithm.",
+                   DoubleValue (2.0),
+                   MakeDoubleAccessor (&AarfcdWifiManager::m_successK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TimerK",
+                   "Multiplication factor for the timer threshold in the AARF algorithm.",
+                   DoubleValue (2.0),
+                   MakeDoubleAccessor (&AarfcdWifiManager::m_timerK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxSuccessThreshold",
+                   "Maximum value of the success threshold in the AARF algorithm.",
+                   UintegerValue (60),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_maxSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinTimerThreshold",
+                   "The minimum value for the 'timer' threshold in the AARF algorithm.",
+                   UintegerValue (15),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minTimerThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinSuccessThreshold",
+                   "The minimum value for the success threshold in the AARF algorithm.",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinRtsWnd", 
+                   "Minimum value for Rts window of Aarf-CD",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minRtsWnd),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxRtsWnd", 
+                   "Maximum value for Rts window of Aarf-CD",
+                   UintegerValue (40),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_maxRtsWnd),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RtsFailsAsDataFails",
+                   "If true the RTS failures will be treated by Aarf-CD as Data failures",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_rtsFailsAsDataFails),
+                   MakeBooleanChecker ())
+    .AddAttribute ("TurnOffRtsAfterRateDecrease",
+                   "If true the RTS mechanism will be turned off when the rate will be decreased",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_turnOffRtsAfterRateDecrease),
+                   MakeBooleanChecker ())
+    .AddAttribute ("TurnOnRtsAfterRateIncrease",
+                   "If true the RTS mechanism will be turned on when the rate will be increased",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_turnOnRtsAfterRateIncrease),
+                   MakeBooleanChecker ())
+    ;
+  return tid;
+}
+AarfcdWifiManager::AarfcdWifiManager ()
+  : WifiRemoteStationManager ()
+{}
+AarfcdWifiManager::~AarfcdWifiManager ()
+{}
+WifiRemoteStation *
+AarfcdWifiManager::CreateStation (void)
+{
+  return new AarfcdWifiRemoteStation (this);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarfcd-wifi-manager.h	Fri Apr 17 17:45:16 2009 +0200
@@ -0,0 +1,112 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+#ifndef AARFCD_WIFI_MANAGER_H
+#define AARFCD_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief an implementation of the AARF-CD algorithm
+ *
+ * This algorithm was first described in "Efficient Collision Detection for Auto Rate Fallback Algorithm".
+ * The implementation available here was done by Federico Maguolo for a very early development
+ * version of ns-3. Federico died before merging this work in ns-3 itself so his code was ported
+ * to ns-3 later without his supervision.
+ */
+class AarfcdWifiManager : public WifiRemoteStationManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  AarfcdWifiManager ();
+  virtual ~AarfcdWifiManager ();
+
+private:
+  friend class AarfcdWifiRemoteStation;
+  virtual WifiRemoteStation *CreateStation (void);
+  uint32_t m_minTimerThreshold;
+  uint32_t m_minSuccessThreshold;
+  double m_successK;
+  uint32_t m_maxSuccessThreshold;
+  double m_timerK;
+  uint32_t m_minRtsWnd;
+  uint32_t m_maxRtsWnd;
+  bool m_rtsFailsAsDataFails;
+  bool m_turnOffRtsAfterRateDecrease;
+  bool m_turnOnRtsAfterRateIncrease;
+};
+
+
+class AarfcdWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager);
+  virtual ~AarfcdWifiRemoteStation ();
+
+
+private:
+  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (void);
+  virtual void DoReportDataFailed (void);
+  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (void);
+  virtual void DoReportFinalDataFailed (void);
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
+  virtual WifiMode DoGetDataMode (uint32_t size);
+  virtual WifiMode DoGetRtsMode (void);
+  virtual bool NeedRts (Ptr<const Packet> packet);
+
+  void ReportRecoveryFailure (void);
+  void ReportFailure (void);
+  uint32_t GetMaxRate (void);
+  uint32_t GetMinRate (void);
+  void CheckRts (void);
+  void IncreaseRtsWnd (void);
+  void ResetRtsWnd (void);
+  void TurnOffRts (void);
+  void TurnOnRts (void);
+
+  bool NeedRecoveryFallback (void);
+  bool NeedNormalFallback (void);
+
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  bool m_recovery;
+  bool m_justModifyRate;
+  uint32_t m_retry;
+  
+  uint32_t m_successThreshold;
+  uint32_t m_timerTimeout;
+
+  uint32_t m_rate;
+  bool m_rtsOn;
+  uint32_t m_rtsWnd;
+  uint32_t m_rtsCounter;
+  bool m_haveASuccess;
+  
+  Ptr<AarfcdWifiManager> m_manager;
+};
+
+} // namespace ns3
+
+#endif /* MAARF_MAC_STATIONS_H */
--- a/src/devices/wifi/arf-wifi-manager.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/arf-wifi-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -28,15 +28,11 @@
 
 namespace ns3 {
   
-ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
-                                            int minTimerTimeout,
-                                            int minSuccessThreshold)
-  : m_stations (stations)
+ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> manager)
+  : m_manager (manager)
 {
-  m_minTimerTimeout = minTimerTimeout;
-  m_minSuccessThreshold = minSuccessThreshold;
-  m_successThreshold = m_minSuccessThreshold;
-  m_timerTimeout = m_minTimerTimeout;
+  m_successThreshold = m_manager->m_successThreshold;
+  m_timerTimeout = m_manager->m_timerThreshold;
   m_rate = GetMinRate ();
 
   m_success = 0;
@@ -189,11 +185,11 @@
 {}
 uint32_t ArfWifiRemoteStation::GetMinTimerTimeout (void)
 {
-  return m_minTimerTimeout;
+  return m_manager->m_timerThreshold;
 }
 uint32_t ArfWifiRemoteStation::GetMinSuccessThreshold (void)
 {
-  return m_minSuccessThreshold;
+  return m_manager->m_successThreshold;
 }
 uint32_t ArfWifiRemoteStation::GetTimerTimeout (void)
 {
@@ -205,18 +201,18 @@
 }
 void ArfWifiRemoteStation::SetTimerTimeout (uint32_t timerTimeout)
 {
-  NS_ASSERT (timerTimeout >= m_minTimerTimeout);
+  NS_ASSERT (timerTimeout >= m_manager->m_timerThreshold);
   m_timerTimeout = timerTimeout;
 }
 void ArfWifiRemoteStation::SetSuccessThreshold (uint32_t successThreshold)
 {
-  NS_ASSERT (successThreshold >= m_minSuccessThreshold);
+  NS_ASSERT (successThreshold >= m_manager->m_successThreshold);
   m_successThreshold = successThreshold;
 }
 Ptr<WifiRemoteStationManager>
 ArfWifiRemoteStation::GetManager (void) const
 {
-  return m_stations;
+  return m_manager;
 }
 
 NS_OBJECT_ENSURE_REGISTERED (ArfWifiManager);
@@ -247,7 +243,7 @@
 WifiRemoteStation *
 ArfWifiManager::CreateStation (void)
 {
-  return new ArfWifiRemoteStation (this, m_timerThreshold, m_successThreshold);
+  return new ArfWifiRemoteStation (this);
 }
 
 } // namespace ns3
--- a/src/devices/wifi/arf-wifi-manager.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/arf-wifi-manager.h	Fri Apr 17 17:45:16 2009 +0200
@@ -46,6 +46,7 @@
   virtual ~ArfWifiManager ();
 
 private:
+  friend class ArfWifiRemoteStation;
   virtual class WifiRemoteStation *CreateStation (void);
   uint32_t m_timerThreshold;
   uint32_t m_successThreshold;
@@ -55,9 +56,7 @@
 class ArfWifiRemoteStation : public WifiRemoteStation
 {
 public:
-  ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
-                        int minTimerTimeout,
-                        int minSuccessThreshold);
+  ArfWifiRemoteStation (Ptr<ArfWifiManager> manager);
   virtual ~ArfWifiRemoteStation ();
 
 protected:
@@ -85,10 +84,7 @@
 
   uint32_t m_rate;
   
-  uint32_t m_minTimerTimeout;
-  uint32_t m_minSuccessThreshold;
-
-  Ptr<ArfWifiManager> m_stations;
+  Ptr<ArfWifiManager> m_manager;
   
 private:
   // overriden by AarfMacStation.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/cara-wifi-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -0,0 +1,193 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+
+#include "cara-wifi-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+NS_LOG_COMPONENT_DEFINE ("Cara");
+
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(CaraWifiManager);
+
+CaraWifiRemoteStation::CaraWifiRemoteStation (Ptr<CaraWifiManager> manager)
+  : m_manager (manager)
+{
+  m_rate = GetMinRate ();
+
+  m_success = 0;
+  m_failed = 0;
+  m_timer = 0;
+}
+CaraWifiRemoteStation::~CaraWifiRemoteStation ()
+{}
+
+uint32_t
+CaraWifiRemoteStation::GetMaxRate (void)
+{
+  return GetNSupportedModes () - 1;
+}
+uint32_t
+CaraWifiRemoteStation::GetMinRate (void)
+{
+  return 0;
+}
+
+bool 
+CaraWifiRemoteStation::NeedNormalFallback (void)
+{
+  return (m_failed >= m_manager->m_failureThreshold);
+}
+
+void 
+CaraWifiRemoteStation::DoReportRtsFailed (void) 
+{}
+
+void 
+CaraWifiRemoteStation::DoReportDataFailed (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_timer++;
+  m_failed++;
+  m_success = 0;
+  if (NeedNormalFallback ()) 
+    {
+      NS_LOG_DEBUG ("self="<<this<<" dec rate");
+      if (m_rate != GetMinRate ())
+        {
+          m_rate--;
+        }
+      m_failed = 0;
+      m_timer = 0;
+    }
+}
+void 
+CaraWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+CaraWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+}
+void 
+CaraWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  m_timer++;
+  m_success++;
+  m_failed = 0;
+  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
+  if ((m_success == m_manager->m_successThreshold ||
+       m_timer >= m_manager->m_timerTimeout))
+    {
+      if (m_rate < GetMaxRate ())
+        {
+          m_rate++;
+        }
+      NS_LOG_DEBUG ("self="<<this<<" inc rate=" << m_rate);
+      m_timer = 0;
+      m_success = 0;
+    }
+}
+void 
+CaraWifiRemoteStation::DoReportFinalRtsFailed (void)
+{}
+void 
+CaraWifiRemoteStation::DoReportFinalDataFailed (void)
+{}
+
+WifiMode
+CaraWifiRemoteStation::DoGetDataMode (uint32_t size)
+{
+  return GetSupportedMode (m_rate);
+}
+WifiMode
+CaraWifiRemoteStation::DoGetRtsMode (void)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupportedMode (0);
+}
+
+Ptr<WifiRemoteStationManager>
+CaraWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
+bool
+CaraWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
+{
+  bool rts = WifiRemoteStation::NeedRts (packet);
+  if (rts || m_failed >= m_manager->m_probeThreshold)
+    {
+      return true;
+    }
+
+  return false;
+}
+
+
+
+TypeId 
+CaraWifiManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::CaraWifiManager")
+   .SetParent<WifiRemoteStationManager> ()
+   .AddConstructor<CaraWifiManager> ()
+   .AddAttribute ("ProbeThreshold",
+                  "The number of consecutive transmissions failure to activate the RTS probe.",
+                  UintegerValue (1),
+                  MakeUintegerAccessor (&CaraWifiManager::m_probeThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("FailureThreshold",
+                  "The number of consecutive transmissions failure to decrease the rate.",
+                  UintegerValue (2),
+                  MakeUintegerAccessor (&CaraWifiManager::m_failureThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("SuccessThreshold",
+                  "The minimum number of sucessfull transmissions to try a new rate.",
+                  UintegerValue (10),
+                  MakeUintegerAccessor (&CaraWifiManager::m_successThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("Timeout",
+                  "The 'timer' in the CARA algorithm",
+                  UintegerValue (15),
+                  MakeUintegerAccessor (&CaraWifiManager::m_timerTimeout),
+                  MakeUintegerChecker<uint32_t> ())
+ ;
+ return tid;
+}
+
+CaraWifiManager::CaraWifiManager ()
+  : WifiRemoteStationManager ()
+{}
+CaraWifiManager::~CaraWifiManager ()
+{}
+
+WifiRemoteStation *
+CaraWifiManager::CreateStation (void)
+{
+  return new CaraWifiRemoteStation (this);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/cara-wifi-manager.h	Fri Apr 17 17:45:16 2009 +0200
@@ -0,0 +1,91 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+#ifndef CARA_WIFI_MANAGER_H
+#define CARA_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief implement the CARA rate control algorithm
+ *
+ * Implement the CARA algorithm from:
+ * J. Kim, S. Kim, S. Choi, and D. Qiao. 
+ * "CARA: Collision-Aware Rate Adaptation for IEEE 802.11 WLANs."
+ *
+ * Originally implemented by Federico Maguolo for a very early 
+ * prototype version of ns-3.
+ */
+class CaraWifiManager : public WifiRemoteStationManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  CaraWifiManager ();
+  virtual ~CaraWifiManager ();
+
+private:
+  friend class CaraWifiRemoteStation;
+  virtual class WifiRemoteStation *CreateStation (void);
+  uint32_t m_timerTimeout;
+  uint32_t m_successThreshold;
+  uint32_t m_failureThreshold;
+  uint32_t m_probeThreshold;
+};
+
+
+class CaraWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  CaraWifiRemoteStation (Ptr<CaraWifiManager> manager);
+  virtual ~CaraWifiRemoteStation ();
+
+private:
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
+  virtual void DoReportRtsFailed (void);
+  virtual void DoReportDataFailed (void);
+  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (void);
+  virtual void DoReportFinalDataFailed (void);
+  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
+  virtual WifiMode DoGetDataMode (uint32_t size);
+  virtual WifiMode DoGetRtsMode (void);
+
+  virtual bool NeedRts (Ptr<const Packet> packet);
+
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  
+  uint32_t m_rate;
+  
+  Ptr<CaraWifiManager> m_manager;
+  
+  uint32_t GetMaxRate (void);
+  uint32_t GetMinRate (void);
+
+  bool NeedNormalFallback (void);
+  
+};
+
+} // namespace ns3
+
+#endif /* CARA_WIFI_MANAGER_H */
--- a/src/devices/wifi/dcf-manager-test.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/dcf-manager-test.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,4 +1,22 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifdef RUN_SELF_TESTS
 
 #include "ns3/test.h"
--- a/src/devices/wifi/dcf-manager.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/dcf-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,4 +1,22 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 
 #include "ns3/assert.h"
 #include "ns3/log.h"
--- a/src/devices/wifi/interference-helper.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/interference-helper.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #include "interference-helper.h"
 #include "wifi-phy.h"
 #include "error-rate-model.h"
@@ -137,15 +156,15 @@
 }
 
 void 
-InterferenceHelper::SetNoiseFloorW (double noiseFloor)
+InterferenceHelper::SetNoiseFigure (double value)
 {
-  m_noiseFloorW = noiseFloor;
+  m_noiseFigure = value;
 }
 
 double 
-InterferenceHelper::GetNoiseFloorW (void) const
+InterferenceHelper::GetNoiseFigure (void) const
 {
-  return m_noiseFloorW;
+  return m_noiseFigure;
 }
 
 void 
@@ -260,9 +279,10 @@
 {
   // thermal noise at 290K in J/s = W
   static const double BOLTZMANN = 1.3803e-23;
+  // Nt is the power of thermal noise in W
   double Nt = BOLTZMANN * 290.0 * mode.GetBandwidth ();
-  // receiver noise Floor (W)
-  double noiseFloor = m_noiseFloorW * Nt;
+  // receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
+  double noiseFloor = m_noiseFigure * Nt;
   double noise = noiseFloor + noiseInterference;
   double snr = signal / noise;
   return snr;
--- a/src/devices/wifi/interference-helper.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/interference-helper.h	Fri Apr 17 17:45:16 2009 +0200
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifndef INTERFERENCE_HELPER_H
 #define INTERFERENCE_HELPER_H
 
@@ -50,10 +69,10 @@
   ~InterferenceHelper ();
 
   void Configure80211aParameters (void);
-  void SetNoiseFloorW (double noiseFloor);
+  void SetNoiseFigure (double value);
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
 
-  double GetNoiseFloorW (void) const;
+  double GetNoiseFigure (void) const;
   Ptr<ErrorRateModel> GetErrorRateModel (void) const;
 
 
@@ -99,7 +118,7 @@
   WifiMode m_shortPlcpHeaderMode;
   uint32_t m_plcpHeaderLength;
   Time m_maxPacketDuration;
-  double m_noiseFloorW;
+  double m_noiseFigure; /**< noise figure (linear) */
   Events m_events;
   bool m_80211a;
   Ptr<ErrorRateModel> m_errorRateModel;
--- a/src/devices/wifi/rraa-wifi-manager.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/rraa-wifi-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -29,6 +29,8 @@
 NS_LOG_COMPONENT_DEFINE ("RraaWifiManager");
 
 namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(RraaWifiManager);
   
 RraaWifiRemoteStation::RraaWifiRemoteStation (Ptr<RraaWifiManager> stations)
   : m_stations (stations)
@@ -188,7 +190,7 @@
 TypeId 
 RraaWifiManager::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("RraaWifiManager")
+  static TypeId tid = TypeId ("ns3::RraaWifiManager")
     .SetParent<WifiRemoteStationManager> ()
     .AddConstructor<RraaWifiManager> ()
     .AddAttribute ("Basic",
--- a/src/devices/wifi/wifi-mode.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-mode.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -87,6 +87,12 @@
 std::string 
 WifiMode::GetUniqueName (void) const
 {
+  // needed for ostream printing of the invalid mode
+  if (m_uid == 0)
+    {
+      return "Invalid-WifiMode";
+    }
+
   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   return item->uniqueUid;
 }
--- a/src/devices/wifi/wifi-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -137,16 +137,6 @@
 }
 
 void 
-WifiNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-std::string 
-WifiNetDevice::GetName(void) const
-{
-  return m_name;
-}
-void 
 WifiNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/wifi/wifi-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -75,8 +75,6 @@
 
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -123,7 +121,6 @@
   TracedCallback<Ptr<const Packet>, Mac48Address> m_txLogger;
 
   uint32_t m_ifIndex;
-  std::string m_name;
   bool m_linkUp;
   Callback<void> m_linkChange;
   mutable uint16_t m_mtu;
--- a/src/devices/wifi/wifi-phy-test.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-phy-test.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #include "wifi-net-device.h"
 #include "yans-wifi-channel.h"
 #include "yans-wifi-phy.h"
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -97,7 +97,7 @@
 WifiMode 
 NonUnicastWifiRemoteStation::DoGetDataMode (uint32_t size)
 {
-  WifiMode mode = m_stations->GetBasicMode (0);
+  WifiMode mode = m_stations->GetNonUnicastMode ();
   NS_LOG_DEBUG ("non-unicast size="<<size<<", mode="<<mode);
   return mode;
 }
@@ -155,6 +155,10 @@
                    UintegerValue (1500),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
                    MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("NonUnicastMode", "Wifi mode used for non-unicast transmissions.",
+                   WifiModeValue (),
+                   MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode),
+                   MakeWifiModeChecker ())
     ;
   return tid;
 }
@@ -305,6 +309,14 @@
 {
   return m_isLowLatency;
 }
+WifiMode
+WifiRemoteStationManager::GetNonUnicastMode (void) const
+{
+  if (m_nonUnicastMode == WifiMode ())
+    return GetBasicMode(0);
+  else
+    return m_nonUnicastMode;
+}
 
 } // namespace ns3
 
--- a/src/devices/wifi/wifi-remote-station-manager.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Fri Apr 17 17:45:16 2009 +0200
@@ -80,6 +80,8 @@
 
   bool IsLowLatency (void) const;
 
+  WifiMode GetNonUnicastMode (void) const;
+
   WifiRemoteStation *Lookup (Mac48Address address);
   WifiRemoteStation *LookupNonUnicast (void);
 protected:
@@ -97,6 +99,7 @@
   uint32_t m_maxSlrc;
   uint32_t m_rtsCtsThreshold;
   uint32_t m_fragmentationThreshold;
+  WifiMode m_nonUnicastMode;
 };
 
 } // namespace ns3
@@ -259,12 +262,9 @@
   WifiMode GetAckMode (WifiMode dataMode);
 
 private:
-  typedef std::vector<WifiMode> SupportedModes;
   virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
   virtual WifiMode DoGetDataMode (uint32_t size) = 0;
   virtual WifiMode DoGetRtsMode (void) = 0;
-  uint32_t GetNFragments (Ptr<const Packet> packet);
-protected:
   virtual void DoReportRtsFailed (void) = 0;
   virtual void DoReportDataFailed (void) = 0;
   virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) = 0;
@@ -272,9 +272,12 @@
   virtual void DoReportFinalRtsFailed (void) = 0;
   virtual void DoReportFinalDataFailed (void) = 0;
   virtual void DoReportRxOk (double rxSnr, WifiMode txMode) = 0;
+protected:
   uint32_t GetNSupportedModes (void) const;
   WifiMode GetSupportedMode (uint32_t i) const;
 private:
+  typedef std::vector<WifiMode> SupportedModes;
+  uint32_t GetNFragments (Ptr<const Packet> packet);
   bool IsIn (WifiMode mode) const;
   WifiMode GetControlAnswerMode (WifiMode reqMode);
   enum {
--- a/src/devices/wifi/wifi-test.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wifi-test.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifdef RUN_SELF_TESTS
 
 #include "wifi-net-device.h"
--- a/src/devices/wifi/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -42,6 +42,8 @@
         'amrr-wifi-manager.cc',
         'onoe-wifi-manager.cc',
         'rraa-wifi-manager.cc',
+        'aarfcd-wifi-manager.cc',
+        'cara-wifi-manager.cc',
         'constant-rate-wifi-manager.cc',
         'wifi-test.cc',
         ]
--- a/src/devices/wifi/yans-wifi-phy.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/yans-wifi-phy.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -93,11 +93,17 @@
                    MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart, 
                                        &YansWifiPhy::GetTxPowerStart),
                    MakeDoubleChecker<double> ())
-    .AddAttribute ("RxNoise",
-                   "Ratio of energy lost by receiver (dB).",
+    .AddAttribute ("RxNoiseFigure",
+                   "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
+                   " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
+                   "\"the difference in decibels (dB) between"
+                   " the noise output of the actual receiver to the noise output of an "
+                   " ideal receiver with the same overall gain and bandwidth when the receivers "
+                   " are connected to sources at the standard noise temperature T0 (usually 290 K)\"."
+                   " For",
                    DoubleValue (7),
-                   MakeDoubleAccessor (&YansWifiPhy::SetRxNoise,
-                                       &YansWifiPhy::GetRxNoise),
+                   MakeDoubleAccessor (&YansWifiPhy::SetRxNoiseFigure,
+                                       &YansWifiPhy::GetRxNoiseFigure),
                    MakeDoubleChecker<double> ())
     .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes"
                    " and some PHY-specific constants.",
@@ -155,10 +161,10 @@
 
 
 void 
-YansWifiPhy::SetRxNoise (double db)
+YansWifiPhy::SetRxNoiseFigure (double noiseFigureDb)
 {
-  NS_LOG_FUNCTION (this << db);
-  m_interference.SetNoiseFloorW (DbToRatio (db));
+  NS_LOG_FUNCTION (this << noiseFigureDb);
+  m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb));
 }
 void 
 YansWifiPhy::SetTxPowerStart (double start)
@@ -219,9 +225,9 @@
 }
 
 double 
-YansWifiPhy::GetRxNoise (void) const
+YansWifiPhy::GetRxNoiseFigure (void) const
 {
-  return RatioToDb (m_interference.GetNoiseFloorW ());
+  return RatioToDb (m_interference.GetNoiseFigure ());
 }
 double 
 YansWifiPhy::GetTxPowerStart (void) const
--- a/src/devices/wifi/yans-wifi-phy.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/devices/wifi/yans-wifi-phy.h	Fri Apr 17 17:45:16 2009 +0200
@@ -75,7 +75,7 @@
                            WifiPreamble preamble);
 
   void SetStandard (enum WifiPhyStandard standard);
-  void SetRxNoise (double ratio);
+  void SetRxNoiseFigure (double noiseFigureDb);
   void SetTxPowerStart (double start);
   void SetTxPowerEnd (double end);
   void SetNTxPower (uint32_t n);
@@ -86,7 +86,7 @@
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
   void SetDevice (Ptr<Object> device);
   void SetMobility (Ptr<Object> mobility);
-  double GetRxNoise (void) const;
+  double GetRxNoiseFigure (void) const;
   double GetTxGain (void) const;
   double GetRxGain (void) const;
   double GetEdThreshold (void) const;
--- a/src/helper/tap-bridge-helper.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/helper/tap-bridge-helper.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -18,6 +18,7 @@
 
 #include "ns3/log.h"
 #include "ns3/node.h"
+#include "ns3/enum.h"
 #include "ns3/tap-bridge.h"
 #include "ns3/names.h"
 #include "tap-bridge-helper.h"
@@ -26,11 +27,18 @@
 
 namespace ns3 {
 
+TapBridgeHelper::TapBridgeHelper ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_deviceFactory.SetTypeId ("ns3::TapBridge");
+}
+
 TapBridgeHelper::TapBridgeHelper (Ipv4Address gateway)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_deviceFactory.SetTypeId ("ns3::TapBridge");
   SetAttribute ("Gateway", Ipv4AddressValue (gateway));
+  SetAttribute ("Mode", EnumValue(TapBridge::CONFIGURE_LOCAL));
 }
 
 void 
@@ -41,6 +49,14 @@
 }
 
 
+Ptr<NetDevice>
+TapBridgeHelper::Install (Ptr<Node> node, Ptr<NetDevice> nd, const AttributeValue &v1)
+{
+  NS_LOG_FUNCTION (node << nd << &v1);
+  m_deviceFactory.Set ("DeviceName", v1);
+  return Install (node, nd);
+}
+
   Ptr<NetDevice>
 TapBridgeHelper::Install (Ptr<Node> node, Ptr<NetDevice> nd)
 {
--- a/src/helper/tap-bridge-helper.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/helper/tap-bridge-helper.h	Fri Apr 17 17:45:16 2009 +0200
@@ -21,6 +21,7 @@
 
 #include "net-device-container.h"
 #include "ns3/object-factory.h"
+#include "ns3/tap-bridge.h"
 #include <string>
 
 namespace ns3 {
@@ -31,12 +32,14 @@
 class TapBridgeHelper
 {
 public:
+  TapBridgeHelper ();
   TapBridgeHelper (Ipv4Address gateway);
   void SetAttribute (std::string n1, const AttributeValue &v1);
   Ptr<NetDevice> Install (Ptr<Node> node, Ptr<NetDevice> nd);
   Ptr<NetDevice> Install (std::string nodeName, Ptr<NetDevice> nd);
   Ptr<NetDevice> Install (Ptr<Node> node, std::string ndName);
   Ptr<NetDevice> Install (std::string nodeName, std::string ndName);
+  Ptr<NetDevice> Install (Ptr<Node> node, Ptr<NetDevice> nd, const AttributeValue &v1);
 private:
   ObjectFactory m_deviceFactory;
 };
--- a/src/internet-stack/internet-stack.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/internet-stack.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -54,6 +54,8 @@
   Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
   udp->SetNode (node);
   ipv4->Insert (udp);
+  node->AggregateObject (udp);
+
   Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
   udpFactory->SetUdp (udp);
   node->AggregateObject (udpFactory);
@@ -66,6 +68,8 @@
   Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
   icmp->SetNode (node);
   ipv4->Insert (icmp);
+  node->AggregateObject (icmp);
+
   Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
   node->AggregateObject (rawFactory);
 }
@@ -76,8 +80,8 @@
   Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
   Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
   tcp->SetNode (node);
-
   ipv4->Insert (tcp);
+  node->AggregateObject (tcp);
 
   Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
   tcpFactory->SetTcp (tcp);
@@ -114,6 +118,8 @@
   tcp->SetNscLibrary(soname);
   tcp->SetNode (node);
   ipv4->Insert (tcp);
+  node->AggregateObject (tcp);
+
   Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
   tcpFactory->SetTcp (tcp);
   node->AggregateObject (tcpFactory);
--- a/src/internet-stack/ipv4-l3-protocol.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -152,17 +152,16 @@
   NS_LOG_FUNCTION (this);
   for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
     {
-      (*i)->Dispose ();
       *i = 0;
     }
   m_protocols.clear ();
 
-  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
+  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
     {
-      Ptr<Ipv4Interface> interface = *i;
-      interface->Dispose ();
+      *i = 0;
     }
   m_interfaces.clear ();
+  m_routingProtocols.clear ();
   m_node = 0;
   m_staticRouting->Dispose ();
   m_staticRouting = 0;
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -24,12 +24,13 @@
 #include "ns3/packet.h"
 #include "ns3/node.h"
 
+#include "ns3/object-vector.h"
+
 #include "tcp-header.h"
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
 #include "nsc-tcp-l4-protocol.h"
-#include "nsc-tcp-socket-impl.h"
 #include "nsc-sysctl.h"
 
 #include "tcp-typedefs.h"
@@ -70,6 +71,10 @@
                    ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
                    MakeObjectFactoryAccessor (&NscTcpL4Protocol::m_rttFactory),
                    MakeObjectFactoryChecker ())
+    .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&NscTcpL4Protocol::m_sockets),
+                   MakeObjectVectorChecker<NscTcpSocketImpl> ())
     ;
   return tid;
 }
@@ -154,6 +159,14 @@
 NscTcpL4Protocol::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
+
+  for (std::vector<Ptr<NscTcpSocketImpl> >::iterator i = m_sockets.begin (); i != m_sockets.end (); i++)
+    {
+      *i = 0;
+    }
+  m_sockets.clear ();
+
+
   if (m_endPoints != 0)
     {
       delete m_endPoints;
@@ -173,6 +186,7 @@
   socket->SetNode (m_node);
   socket->SetTcp (this);
   socket->SetRtt (rtt);
+  m_sockets.push_back (socket);
   return socket;
 }
 
--- a/src/internet-stack/nsc-tcp-l4-protocol.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Fri Apr 17 17:45:16 2009 +0200
@@ -31,6 +31,7 @@
 
 #include "ns3/timer.h"
 #include "sim_interface.h"
+#include "nsc-tcp-socket-impl.h"
 
 namespace ns3 {
 
@@ -116,6 +117,7 @@
   INetStack* m_nscStack;
   void *m_dlopenHandle;
   Timer m_softTimer;
+  std::vector<Ptr<NscTcpSocketImpl> > m_sockets;
 };
 
 }; // namespace ns3
--- a/src/internet-stack/nsc-tcp-socket-factory-impl.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/nsc-tcp-socket-factory-impl.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -13,8 +13,8 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include "nsc-tcp-l4-protocol.h"
 #include "nsc-tcp-socket-factory-impl.h"
-#include "nsc-tcp-l4-protocol.h"
 #include "ns3/socket.h"
 #include "ns3/assert.h"
 
--- a/src/internet-stack/tcp-l4-protocol.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/tcp-l4-protocol.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -22,6 +22,7 @@
 #include "ns3/log.h"
 #include "ns3/nstime.h"
 #include "ns3/boolean.h"
+#include "ns3/object-vector.h"
 
 #include "ns3/packet.h"
 #include "ns3/node.h"
@@ -31,7 +32,6 @@
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
-#include "tcp-socket-impl.h"
 
 #include "tcp-typedefs.h"
 
@@ -334,6 +334,10 @@
                    BooleanValue (false),
                    MakeBooleanAccessor (&TcpL4Protocol::m_calcChecksum),
                    MakeBooleanChecker ())
+    .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&TcpL4Protocol::m_sockets),
+                   MakeObjectVectorChecker<TcpSocketImpl> ())
     ;
   return tid;
 }
@@ -366,11 +370,18 @@
 TcpL4Protocol::DoDispose (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
+  for (std::vector<Ptr<TcpSocketImpl> >::iterator i = m_sockets.begin (); i != m_sockets.end (); i++)
+    {
+      *i = 0;
+    }
+  m_sockets.clear ();
+
   if (m_endPoints != 0)
     {
       delete m_endPoints;
       m_endPoints = 0;
     }
+
   m_node = 0;
   Ipv4L4Protocol::DoDispose ();
 }
@@ -384,6 +395,7 @@
   socket->SetNode (m_node);
   socket->SetTcp (this);
   socket->SetRtt (rtt);
+  m_sockets.push_back (socket);
   return socket;
 }
 
--- a/src/internet-stack/tcp-l4-protocol.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/internet-stack/tcp-l4-protocol.h	Fri Apr 17 17:45:16 2009 +0200
@@ -31,6 +31,7 @@
 #include "ipv4-l4-protocol.h"
 #include "ipv4-interface.h"
 
+#include "tcp-socket-impl.h"
 #include "tcp-header.h"
 #include "tcp-typedefs.h"
 
@@ -120,6 +121,7 @@
 
   bool m_goodChecksum;
   bool m_calcChecksum;
+  std::vector<Ptr<TcpSocketImpl> > m_sockets;
 };
 
 }; // namespace ns3
--- a/src/mobility/hierarchical-mobility-model.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/mobility/hierarchical-mobility-model.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -52,15 +52,46 @@
 void 
 HierarchicalMobilityModel::SetChild (Ptr<MobilityModel> model)
 {
+  Ptr<MobilityModel> oldChild = m_child;
+  Vector pos;
+  if (m_child)
+    {
+      pos = GetPosition ();
+      m_child->TraceDisconnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+    }
   m_child = model;
   m_child->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+
+  // if we had a child before, then we had a valid position before;
+  // try to preserve the old absolute position.
+  if (oldChild)
+    {
+      SetPosition (pos);
+    }
 }
 
 void 
 HierarchicalMobilityModel::SetParent (Ptr<MobilityModel> model)
 {
+  Vector pos;
+  if (m_child)
+    {
+      pos = GetPosition ();
+    }
+  if (m_parent)
+    {
+      m_parent->TraceDisconnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+    }
   m_parent = model;
-  m_parent->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+  if (m_parent)
+    {
+      m_parent->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+    }
+  // try to preserve the old position across parent changes
+  if (m_child)
+    {
+      SetPosition (pos);
+    }
 }
 
 
@@ -79,6 +110,10 @@
 Vector
 HierarchicalMobilityModel::DoGetPosition (void) const
 {
+  if (!m_parent)
+    {
+      return m_child->GetPosition ();
+    }
   Vector parentPosition = m_parent->GetPosition ();
   Vector childPosition = m_child->GetPosition ();
   return Vector (parentPosition.x + childPosition.x,
@@ -88,27 +123,41 @@
 void 
 HierarchicalMobilityModel::DoSetPosition (const Vector &position)
 {
-  if (m_parent == 0 || m_child == 0)
+  if (m_child == 0)
     {
       return;
     }
   // This implementation of DoSetPosition is really an arbitraty choice.
   // anything else would have been ok.
-  Vector parentPosition = m_parent->GetPosition ();
-  Vector childPosition (position.x - parentPosition.x,
-			  position.y - parentPosition.y,
-			  position.z - parentPosition.z);
-  m_child->SetPosition (childPosition);
+  if (m_parent)
+    {
+      Vector parentPosition = m_parent->GetPosition ();
+      Vector childPosition (position.x - parentPosition.x,
+                            position.y - parentPosition.y,
+                            position.z - parentPosition.z);
+      m_child->SetPosition (childPosition);
+    }
+  else
+    {
+      m_child->SetPosition (position);
+    }
 }
 Vector
 HierarchicalMobilityModel::DoGetVelocity (void) const
 {
-  Vector parentSpeed = m_parent->GetVelocity ();
-  Vector childSpeed = m_child->GetVelocity ();
-  Vector speed (parentSpeed.x + childSpeed.x,
-               parentSpeed.y + childSpeed.y,
-               parentSpeed.z + childSpeed.z);
-  return speed;
+  if (m_parent)
+    {
+      Vector parentSpeed = m_parent->GetVelocity ();
+      Vector childSpeed = m_child->GetVelocity ();
+      Vector speed (parentSpeed.x + childSpeed.x,
+                    parentSpeed.y + childSpeed.y,
+                    parentSpeed.z + childSpeed.z);
+      return speed;
+    }
+  else
+    {
+      return m_child->GetVelocity ();
+    }
 }
 
 void 
--- a/src/mobility/hierarchical-mobility-model.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/mobility/hierarchical-mobility-model.h	Fri Apr 17 17:45:16 2009 +0200
@@ -27,8 +27,31 @@
 /**
  * \brief a hierachical mobility model.
  * 
- * This model allows you to specify the position of a
- * child object relative to a parent object.
+ * This model allows you to specify the position of a child object
+ * relative to a parent object.
+ * 
+ * Basically this is a mobility model that combines two other mobility
+ * models: a "parent" model and a "child" model.  The position of the
+ * hierarchical model is always the vector sum of the parent + child
+ * positions, so that if the parent model "moves", then this model
+ * will report an equal relative movement.  Useful, for instance, if
+ * you want to simulate a node inside another node that moves, such as
+ * a vehicle.
+ *
+ * Setting the position on this model is always done using world
+ * absolute coordinates, and it changes only the child mobility model
+ * position, never the parent.  The child mobility model always uses a
+ * coordinate sytem relative to the parent model position.
+ *
+ * @note: as a special case, the parent model may be NULL, which is
+ * semantically equivalent to having a ConstantPositionMobilityModel
+ * as parent positioned at origin (0,0,0).  In other words, setting
+ * the parent model to NULL makes the child model and the hierarchical
+ * model start using world absolute coordinates.
+ *
+ * @warning: changing the parent/child mobility models in the middle
+ * of a simulation will probably not play very well with the
+ * ConfigStore APIs, so do this only if you know what you are doing.
  */
 class HierarchicalMobilityModel : public MobilityModel
 {
@@ -52,14 +75,26 @@
    * position by the child mobility model.
    */
   Ptr<MobilityModel> GetParent (void) const;
+  /**
+   * Sets the child mobility model to a new one.  If before there
+   * already existed a child model, then the child mobility model
+   * current position is also modified to ensure that the composite
+   * position is preserved.
+   */
+  void SetChild (Ptr<MobilityModel> model);
+  /**
+   * Sets the parent mobility model to a new one.  If before there
+   * already existed a child model, then the child mobility model
+   * current position is also modified to ensure that the composite
+   * position is preserved.
+   */
+  void SetParent (Ptr<MobilityModel> model);
   
 private:
   virtual Vector DoGetPosition (void) const;
   virtual void DoSetPosition (const Vector &position);
   virtual Vector DoGetVelocity (void) const;
 
-  void SetChild (Ptr<MobilityModel> model);
-  void SetParent (Ptr<MobilityModel> model);
   void ParentChanged (Ptr<const MobilityModel> model);
   void ChildChanged (Ptr<const MobilityModel> model);
 
--- a/src/mobility/random-waypoint-mobility-model.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/mobility/random-waypoint-mobility-model.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -45,7 +45,7 @@
                    RandomVariableValue (ConstantVariable (2.0)),
                    MakeRandomVariableAccessor (&RandomWaypointMobilityModel::m_pause),
                    MakeRandomVariableChecker ())
-    .AddAttribute ("Position",
+    .AddAttribute ("PositionAllocator",
                    "The position model used to pick a destination point.",
                    PointerValue (),
                    MakePointerAccessor (&RandomWaypointMobilityModel::m_position),
--- a/src/node/channel.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/channel.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -35,34 +35,14 @@
 }
 
 Channel::Channel ()
-  : m_name("Channel")
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
-Channel::Channel (std::string name)
-  : m_name(name)
-{
-  NS_LOG_FUNCTION (this << name);
-}
 
 Channel::~Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
-  void
-Channel::SetName(std::string name)
-{
-  NS_LOG_FUNCTION (this << name);
-  m_name = name;
-}
-
-  std::string
-Channel::GetName(void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
 } // namespace ns3
--- a/src/node/channel.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/channel.h	Fri Apr 17 17:45:16 2009 +0200
@@ -43,12 +43,8 @@
   static TypeId GetTypeId (void);
 
   Channel ();
-  Channel (std::string name);
   virtual ~Channel ();
 
-  void SetName(std::string);
-  std::string GetName(void);
-
   /**
    * \returns the number of NetDevices connected to this Channel.
    *
@@ -63,10 +59,8 @@
    */
   virtual Ptr<NetDevice> GetDevice (uint32_t i) const = 0;
 
-private:
-  std::string   m_name;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* NS3_CHANNEL_H */
--- a/src/node/ipv6-address.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/ipv6-address.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -338,7 +338,8 @@
     << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[12]
     << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[13] << ":"
     << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[14]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15];
+    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15] 
+    << std::dec << std::setfill(' ');
 }
 
 bool Ipv6Address::IsLocalhost () const
--- a/src/node/net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -68,14 +68,6 @@
   virtual ~NetDevice();
 
   /**
-   * \param name name of the device (e.g. "eth0")
-   */
-  virtual void SetName(const std::string name) = 0;
-  /**
-   * \return name name of the device (e.g. "eth0")
-   */
-  virtual std::string GetName(void) const = 0;
-  /**
    * \param index ifIndex of the device 
    */
   virtual void SetIfIndex(const uint32_t index) = 0;
--- a/src/node/node.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/node.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -225,7 +225,7 @@
 Node::PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                 const Address &from, const Address &to, NetDevice::PacketType packetType)
 {
-  NS_LOG_FUNCTION(device->GetName ());
+  NS_LOG_FUNCTION(this);
   return ReceiveFromDevice (device, packet, protocol, from, to, packetType, true);
 }
 
@@ -233,7 +233,7 @@
 Node::NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                    const Address &from)
 {
-  NS_LOG_FUNCTION(device->GetName ());
+  NS_LOG_FUNCTION(this);
   return ReceiveFromDevice (device, packet, protocol, from, from, NetDevice::PacketType (0), false);
 }
 
@@ -242,8 +242,7 @@
                          const Address &from, const Address &to, NetDevice::PacketType packetType, bool promiscuous)
 {
   NS_LOG_DEBUG("Node " << GetId () << " ReceiveFromDevice:  dev "
-               << device->GetIfIndex () << " ("
-               << device->GetName () << " type " << device->GetInstanceTypeId ().GetName ()
+               << device->GetIfIndex () << " (type=" << device->GetInstanceTypeId ().GetName ()
                << ") Packet UID " << packet->GetUid ());
   bool found = false;
 
--- a/src/node/simple-net-device.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/simple-net-device.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -38,7 +38,6 @@
   : m_channel (0),
     m_node (0),
     m_mtu (0xffff),
-    m_name (""),
     m_ifIndex (0)
 {}
 
@@ -84,16 +83,6 @@
 }
 
 void 
-SimpleNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-std::string 
-SimpleNetDevice::GetName(void) const
-{
-  return m_name;
-}
-void 
 SimpleNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/node/simple-net-device.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/node/simple-net-device.h	Fri Apr 17 17:45:16 2009 +0200
@@ -46,8 +46,6 @@
   void SetAddress (Mac48Address address);
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -82,7 +80,6 @@
   NetDevice::PromiscReceiveCallback m_promiscCallback;
   Ptr<Node> m_node;
   uint16_t m_mtu;
-  std::string m_name;
   uint32_t m_ifIndex;
   Mac48Address m_address;
 };
--- a/src/routing/global-routing/global-route-manager-impl.cc	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Fri Apr 17 17:45:16 2009 +0200
@@ -154,14 +154,14 @@
 }
 
   void 
-SPFVertex::SetOutgoingTypeId (uint32_t id)
+SPFVertex::SetOutgoingInterfaceId (uint32_t id)
 {
   NS_LOG_FUNCTION (id);
   m_rootOif = id;
 }
 
   uint32_t 
-SPFVertex::GetOutgoingTypeId (void) const
+SPFVertex::GetOutgoingInterfaceId (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return m_rootOif;
@@ -872,14 +872,14 @@
 // from the perspective of <v> -- remember that <l> is the link "from"
 // <v> "to" <w>.
 //
-          w->SetOutgoingTypeId (
-            FindOutgoingTypeId (l->GetLinkData ()));
+          w->SetOutgoingInterfaceId (
+            FindOutgoingInterfaceId (l->GetLinkData ()));
           w->SetDistanceFromRoot (distance);
           w->SetParent (v);
           NS_LOG_LOGIC ("Next hop from " << 
             v->GetVertexId () << " to " << w->GetVertexId () << 
             " goes through next hop " << w->GetNextHop () <<
-            " via outgoing interface " << w->GetOutgoingTypeId () <<
+            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
             " with distance " << distance);
         }  // end W is a router vertes
       else 
@@ -889,14 +889,14 @@
           GlobalRoutingLSA* w_lsa = w->GetLSA ();
           NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA);
 // Find outgoing interface ID for this network
-          w->SetOutgoingTypeId (
-            FindOutgoingTypeId (w_lsa->GetLinkStateId (), 
+          w->SetOutgoingInterfaceId (
+            FindOutgoingInterfaceId (w_lsa->GetLinkStateId (), 
             w_lsa->GetNetworkLSANetworkMask () ));
           w->SetDistanceFromRoot (distance);
           w->SetParent (v);
           NS_LOG_LOGIC ("Next hop from " << 
             v->GetVertexId () << " to network " << w->GetVertexId () << 
-            " via outgoing interface " << w->GetOutgoingTypeId () <<
+            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
             " with distance " << distance);
           return 1;
         }
@@ -921,17 +921,17 @@
  * it can be inherited from the parent network).
  */
                 w->SetNextHop (linkRemote->GetLinkData ());
-                w->SetOutgoingTypeId (v->GetOutgoingTypeId ());
+                w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
                 NS_LOG_LOGIC ("Next hop from " << 
                   v->GetVertexId () << " to " << w->GetVertexId () << 
                   " goes through next hop " << w->GetNextHop () <<
-                  " via outgoing interface " << w->GetOutgoingTypeId ());
+                  " via outgoing interface " << w->GetOutgoingInterfaceId ());
             }
         }
       else 
         {
           w->SetNextHop (v->GetNextHop ());
-          w->SetOutgoingTypeId (v->GetOutgoingTypeId ());
+          w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
         }
     }
   else 
@@ -950,7 +950,7 @@
 // (are inherited).
 //
       w->SetNextHop (v->GetNextHop ());
-      w->SetOutgoingTypeId (v->GetOutgoingTypeId ());
+      w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
     }
 //
 // In all cases, we need valid values for the distance metric and a parent.
@@ -1328,7 +1328,7 @@
             " add route to " << tempip <<
             " with mask " << tempmask <<
             " using next hop " << v->GetNextHop () <<
-            " via interface " << v->GetOutgoingTypeId ());
+            " via interface " << v->GetOutgoingInterfaceId ());
 //
 // Here's why we did all of that work.  We're going to add a host route to the
 // host address found in the m_linkData field of the point-to-point link
@@ -1344,7 +1344,7 @@
 //
           Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
           NS_ASSERT (gr);
-          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingTypeId ());
+          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
           return;
         } // if
     } // for
@@ -1356,7 +1356,7 @@
 // have to find the right node pointer to pass to that function.
 //
   uint32_t
-GlobalRouteManagerImpl::FindOutgoingTypeId (Ipv4Address a, Ipv4Mask amask)
+GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask)
 {
   NS_LOG_FUNCTION (a << amask);
 //
@@ -1399,7 +1399,7 @@
 //
           Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
           NS_ASSERT_MSG (ipv4, 
-            "GlobalRouteManagerImpl::FindOutgoingTypeId (): "
+            "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
             "QI for <Ipv4> interface failed");
 //
 // Look through the interfaces on this node for one that has the IP address
@@ -1526,7 +1526,7 @@
               NS_LOG_LOGIC (" Node " << node->GetId () <<
                 " add route to " << lr->GetLinkData () <<
                 " using next hop " << v->GetNextHop () <<
-                " via interface " << v->GetOutgoingTypeId ());
+                " via interface " << v->GetOutgoingInterfaceId ());
 //
 // Here's why we did all of that work.  We're going to add a host route to the
 // host address found in the m_linkData field of the point-to-point link
@@ -1543,7 +1543,7 @@
               Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
               NS_ASSERT (gr);
               gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
-                v->GetOutgoingTypeId ());
+                v->GetOutgoingInterfaceId ());
             }
 //
 // Done adding the routes for the selected node.
@@ -1627,11 +1627,11 @@
           Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
           NS_ASSERT (gr);
           gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
-            v->GetOutgoingTypeId ());
+            v->GetOutgoingInterfaceId ());
           NS_LOG_LOGIC ("Node " << node->GetId () <<
             " add network route to " << tempip <<
             " using next hop " << v->GetNextHop () <<
-            " via interface " << v->GetOutgoingTypeId ());
+            " via interface " << v->GetOutgoingInterfaceId ());
         }
     } 
 }
--- a/src/routing/global-routing/global-route-manager-impl.h	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.h	Fri Apr 17 17:45:16 2009 +0200
@@ -295,7 +295,7 @@
  * @returns The interface index to use when forwarding packets to the host
  * or network represented by "this" SPFVertex.
  */
-  uint32_t GetOutgoingTypeId (void) const;
+  uint32_t GetOutgoingInterfaceId (void) const;
 
 /**
  * @brief Set the interface ID that should be used to begin forwarding packets
@@ -337,7 +337,7 @@
  * @param id The interface index to use when forwarding packets to the host or
  * network represented by "this" SPFVertex.
  */
-  void SetOutgoingTypeId (uint32_t id);
+  void SetOutgoingInterfaceId (uint32_t id);
 
 /**
  * @brief Get the IP address that should be used to begin forwarding packets 
@@ -799,7 +799,7 @@
   void SPFIntraAddRouter (SPFVertex* v);
   void SPFIntraAddTransit (SPFVertex* v);
   void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);
-  uint32_t FindOutgoingTypeId (Ipv4Address a, 
+  uint32_t FindOutgoingInterfaceId (Ipv4Address a, 
     Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
 
   // Local cache of the Ipv4GlobalRouting objects, indexed by nodeId
--- a/src/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/src/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -9,8 +9,7 @@
 import Task
 import Options
 import Build
-from Utils import md5
-
+import Utils
 
 all_modules = (
     'core',
@@ -109,7 +108,7 @@
     def apply(self):
         if self.module is None:
             raise Utils.WafError("'module' missing on ns3headers object %s" % self)
-        ns3_dir_node = Build.bld.path.find_dir("ns3")
+        ns3_dir_node = self.bld.path.find_dir("ns3")
         if self.sub_dir is not None:
             ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
         for filename in self.to_list(self.source):
@@ -176,7 +175,7 @@
         return 0
 
     def sig_explicit_deps(self):
-        m = md5()
+        m = Utils.md5()
         m.update('\n'.join([node.abspath(self.env) for node in self.inputs]))
         return m.digest()
 
@@ -185,7 +184,7 @@
             return self.uid
         except AttributeError:
             "this is not a real hot zone, but we want to avoid surprizes here"
-            m = md5()
+            m = Utils.md5()
             m.update("ns-3-module-header-%s" % self.module)
             self.uid = m.digest()
             return self.uid
@@ -199,13 +198,12 @@
     COLOR = 'BLUE'
     def __init__(self, *args, **kwargs):
         super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs)
-        self.module_name = None
 
     def apply(self):
         ## get all of the ns3 headers
-        ns3_dir_node = Build.bld.path.find_dir("ns3")
+        ns3_dir_node = self.bld.path.find_dir("ns3")
         all_headers_inputs = []
-        for ns3headers in Build.bld.all_task_gen:
+        for ns3headers in self.bld.all_task_gen:
             if isinstance(ns3headers, ns3header_taskgen):
                 if ns3headers.module != self.module:
                     continue
@@ -215,8 +213,10 @@
                     if node is None:
                         fatal("missing header file %s" % (source,))
                     all_headers_inputs.append(node)
+        if not all_headers_inputs:
+            raise Utils.WscriptError("error finding headers for module %s" % self.module)
         assert all_headers_inputs
-        module_obj = Build.bld.name_to_obj("ns3-" + self.module, self.env)
+        module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env)
         assert module_obj is not None
         all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
         task = self.create_task('gen_ns3_module_header', self.env)
--- a/utils/python-unit-tests.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/utils/python-unit-tests.py	Fri Apr 17 17:45:16 2009 +0200
@@ -97,14 +97,14 @@
         ## -- object pointer values
         mobility = ns3.RandomWaypointMobilityModel()
         ptr = ns3.PointerValue()
-        mobility.GetAttribute("Position", ptr)
+        mobility.GetAttribute("PositionAllocator", ptr)
         self.assertEqual(ptr.GetObject(), None)
         
         pos = ns3.ListPositionAllocator()
-        mobility.SetAttribute("Position", ns3.PointerValue(pos))
+        mobility.SetAttribute("PositionAllocator", ns3.PointerValue(pos))
 
         ptr = ns3.PointerValue()
-        mobility.GetAttribute("Position", ptr)
+        mobility.GetAttribute("PositionAllocator", ptr)
         self.assert_(ptr.GetObject() is not None)
 
     def testIdentity(self):
Binary file waf has changed
--- a/wscript	Mon Mar 23 13:16:09 2009 +0100
+++ b/wscript	Fri Apr 17 17:45:16 2009 +0200
@@ -10,6 +10,7 @@
 # WAF modules
 import pproc as subprocess
 import Options
+
 import Logs
 import TaskGen
 import Constants
@@ -23,6 +24,7 @@
 import Utils
 import Build
 import Configure
+import Scripting
 
 import cflags # override the build profiles from waf
 cflags.profiles = {
@@ -133,7 +135,7 @@
                    action="store_true", default=False,
                    dest='valgrind')
     opt.add_option('--shell',
-                   help=('Run a shell with an environment suitably modified to run locally built programs'),
+                   help=('DEPRECATED (run ./waf shell)'),
                    action="store_true", default=False,
                    dest='shell')
     opt.add_option('--enable-sudo',
@@ -161,7 +163,7 @@
     opt.sub_options('src/internet-stack')
 
 
-def check_compilation_flag(conf, flag):
+def _check_compilation_flag(conf, flag):
     """
     Checks if the C++ compiler accepts a certain compilation flag or flags
     flag: can be a string or a list of strings
@@ -186,7 +188,7 @@
 
 def configure(conf):
     # attach some extra methods
-    conf.check_compilation_flag = types.MethodType(check_compilation_flag, conf)
+    conf.check_compilation_flag = types.MethodType(_check_compilation_flag, conf)
     conf.report_optional_feature = types.MethodType(report_optional_feature, conf)
     conf.env['NS3_OPTIONAL_FEATURES'] = []
 
@@ -235,7 +237,7 @@
     env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
     
     if env['COMPILER_CXX'] == 'g++' and 'CXXFLAGS' not in os.environ:
-        if check_compilation_flag(conf, '-Wno-error=deprecated-declarations'):
+        if conf.check_compilation_flag('-Wno-error=deprecated-declarations'):
             env.append_value('CXXFLAGS', '-Wno-error=deprecated-declarations')
         
     if Options.options.build_profile == 'debug':
@@ -244,9 +246,11 @@
 
     env['PLATFORM'] = sys.platform
 
-    if sys.platform == 'win32':
-        if env['COMPILER_CXX'] == 'g++':
+    if conf.env['CXX_NAME'] == 'gcc':
+        if sys.platform == 'win32':
             env.append_value("LINKFLAGS", "-Wl,--enable-runtime-pseudo-reloc")
+        elif sys.platform == 'cygwin':
+            env.append_value("LINKFLAGS", "-Wl,--enable-auto-import")
 
     conf.sub_config('src')
     conf.sub_config('utils')
@@ -363,6 +367,7 @@
 
 
 def build(bld):
+    wutils.bld = bld
     if Options.options.no_task_lines:
         import Runner
         def null_printout(s):
@@ -378,21 +383,6 @@
     variant_env = bld.env_of_name(variant_name)
     bld.all_envs['default'] = variant_env
 
-    if Options.options.shell:
-        run_shell()
-        raise SystemExit(0)
-
-    if Options.options.doxygen:
-        doxygen()
-        raise SystemExit(0)
-
-    check_shell()
-
-    if Options.options.doxygen:
-        doxygen()
-        raise SystemExit(0)
-
-    print "Entering directory `%s'" % os.path.join(bld.path.abspath(), 'build')
     # process subfolders from here
     bld.add_subdirs('src')
     bld.add_subdirs('samples utils examples')
@@ -427,14 +417,14 @@
                         changed = True
 
         ## remove objects that depend on modules not listed
-        for obj in list(Build.bld.all_task_gen):
+        for obj in list(bld.all_task_gen):
             if hasattr(obj, 'ns3_module_dependencies'):
                 for dep in obj.ns3_module_dependencies:
                     if dep not in modules:
-                        Build.bld.all_task_gen.remove(obj)
+                        bld.all_task_gen.remove(obj)
                         break
             if obj.name in env['NS3_MODULES'] and obj.name not in modules:
-                Build.bld.all_task_gen.remove(obj)
+                bld.all_task_gen.remove(obj)
 
     ## Create a single ns3 library containing all enabled modules
     lib = bld.new_task_gen('cxx', 'shlib')
@@ -468,26 +458,47 @@
         regression.run_regression(bld, regression_traces)
 
 
-def shutdown():
-    env = Build.bld.env
 
-    if Options.commands['check']:
-        _run_waf_check()
+def shutdown(ctx):
+    bld = wutils.bld
+    if wutils.bld is None:
+        return
+    env = bld.env
+
+    #if Options.commands['check']:
+    #    _run_waf_check()
 
     if Options.options.lcov_report:
         lcov_report()
 
     if Options.options.run:
-        wutils.run_program(Options.options.run, wutils.get_command_template(env))
+        wutils.run_program(Options.options.run, env, wutils.get_command_template(env))
         raise SystemExit(0)
 
     if Options.options.pyrun:
-        wutils.run_python_program(Options.options.pyrun)
+        wutils.run_python_program(Options.options.pyrun, env)
+        raise SystemExit(0)
+
+    if Options.options.shell:
+        raise Utils.WafError("Run `./waf shell' now, instead of `./waf shell'")
+
+    if Options.options.doxygen:
+        doxygen()
         raise SystemExit(0)
 
-def _run_waf_check():
+    check_shell(bld)
+
+    if Options.options.doxygen:
+        doxygen()
+        raise SystemExit(0)
+
+
+check_context = Build.BuildContext
+def check(bld):
+    "run the NS-3 unit tests"
+    Scripting.build(bld)
     ## generate the trace sources list docs
-    env = Build.bld.env
+    env = bld.env
     proc_env = wutils.get_proc_env()
     try:
         program_obj = wutils.find_program('print-introspected-doxygen', env)
@@ -507,21 +518,21 @@
 
     if env['ENABLE_PYTHON_BINDINGS']:
         print "-- Running NS-3 Python bindings unit tests..."
-        wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")], proc_env)
+        wutils.run_argv([env['PYTHON'], os.path.join("utils", "python-unit-tests.py")], env, proc_env)
     else:
         print "-- Skipping NS-3 Python bindings unit tests: Python bindings not enabled."
 
 
 
 
-def check_shell():
+def check_shell(bld):
     if 'NS3_MODULE_PATH' not in os.environ:
         return
-    env = Build.bld.env
+    env = bld.env
     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"
+        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"
@@ -533,14 +544,20 @@
         raise Utils.WafError(msg)
 
 
-def run_shell():
+shell_context = Build.BuildContext
+def shell(ctx):
+    """run a shell with an environment suitably modified to run locally built programs"""
+
+    #make sure we build first"
+    Scripting.build(ctx)
+
     if sys.platform == 'win32':
         shell = os.environ.get("COMSPEC", "cmd.exe")
     else:
         shell = os.environ.get("SHELL", "/bin/sh")
 
-    env = Build.bld.env
-    wutils.run_argv([shell], {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
+    env = wutils.bld.env
+    wutils.run_argv([shell], env, {'NS3_MODULE_PATH': os.pathsep.join(env['NS3_MODULE_PATH'])})
 
 def doxygen():
     if not os.path.exists('doc/introspected-doxygen.h'):
@@ -598,7 +615,7 @@
 import Utils
 import os
 
-def copytree(src, dst, symlinks=False, excludes=(), build_dir=None):
+def _copytree(src, dst, symlinks=False, excludes=(), build_dir=None):
     """Recursively copy a directory tree using copy2().
 
     The destination directory must not already exist.
@@ -668,7 +685,7 @@
 
 
 def DistDir(appname, version):
-    "make a distribution directory with all the sources in it"
+    #"make a distribution directory with all the sources in it"
     import shutil
 
     # Our temporary folder where to put our files
@@ -683,7 +700,7 @@
     build_dir = getattr(Utils.g_module, BLDDIR, None)
 
     # Copy everything into the new folder
-    copytree('.', TMPFOLDER, excludes=excludes, build_dir=build_dir)
+    _copytree('.', TMPFOLDER, excludes=excludes, build_dir=build_dir)
 
     # TODO undocumented hook
     dist_hook = getattr(Utils.g_module, 'dist_hook', None)
--- a/wutils.py	Mon Mar 23 13:16:09 2009 +0100
+++ b/wutils.py	Fri Apr 17 17:45:16 2009 +0200
@@ -11,11 +11,13 @@
 import Logs
 import TaskGen
 import Build
+import re
 
 
 # these are set from the main wscript file
 APPNAME=None
 VERSION=None
+bld=None
 
 #
 # The last part of the path name to use to find the regression traces tarball.
@@ -27,14 +29,7 @@
 
 
 def get_command_template(env, arguments=()):
-    if Options.options.valgrind:
-        if Options.options.command_template:
-            raise Utils.WafError("Options --command-template and --valgrind are conflicting")
-        if not env['VALGRIND']:
-            raise Utils.WafError("valgrind is not installed")
-        cmd = env['VALGRIND'] + " --leak-check=full --error-exitcode=1 %s"
-    else:
-        cmd = Options.options.command_template or '%s'
+    cmd = Options.options.command_template or '%s'
     for arg in arguments:
         cmd = cmd + " " + arg
     return cmd
@@ -65,7 +60,7 @@
     launch_dir = os.path.abspath(Options.cwd_launch)
     top_dir = os.path.abspath(Options.launch_dir)
     found_programs = []
-    for obj in Build.bld.all_task_gen:
+    for obj in bld.all_task_gen:
         if not getattr(obj, 'is_ns3_program', False):
             continue
 
@@ -84,7 +79,7 @@
                      % (program_name, found_programs))
 
 def get_proc_env(os_env=None):
-    env = Build.bld.env
+    env = bld.env
     if sys.platform == 'linux2':
         pathvar = 'LD_LIBRARY_PATH'
     elif sys.platform == 'darwin':
@@ -111,7 +106,7 @@
         else:
             proc_env[pathvar] = os.pathsep.join(list(env['NS3_MODULE_PATH']))
 
-    pymoddir = Build.bld.path.find_dir('bindings/python').abspath(env)
+    pymoddir = bld.path.find_dir('bindings/python').abspath(env)
     if 'PYTHONPATH' in proc_env:
         proc_env['PYTHONPATH'] = os.pathsep.join([pymoddir] + [proc_env['PYTHONPATH']])
     else:
@@ -119,10 +114,29 @@
 
     return proc_env
 
-def run_argv(argv, os_env=None, cwd=None):
+def run_argv(argv, env, os_env=None, cwd=None):
     proc_env = get_proc_env(os_env)
-    #env = Build.bld.env
-    retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
+    if Options.options.valgrind:
+        if Options.options.command_template:
+            raise Utils.WafError("Options --command-template and --valgrind are conflicting")
+        if not env['VALGRIND']:
+            raise Utils.WafError("valgrind is not installed")
+        argv = [env['VALGRIND'], "--leak-check=full", "--error-exitcode=1"] + argv
+        proc = subprocess.Popen(argv, env=proc_env, cwd=cwd, stderr=subprocess.PIPE)
+        reg = re.compile ('definitely lost: ([^ ]+) bytes')
+        error = False
+        for line in proc.stderr:
+            sys.stderr.write(line)
+            result = reg.search(line)
+            if result is None:
+                continue
+            if result.group(1) != "0":
+                error = True
+        retval = proc.wait()
+        if retval == 0 and error:
+            retval = 1
+    else:
+        retval = subprocess.Popen(argv, env=proc_env, cwd=cwd).wait()
     if retval:
         raise Utils.WafError("Command %s exited with code %i" % (argv, retval))
     return retval
@@ -133,7 +147,7 @@
     run_program(program_string, command_template).
     """
     #print "get_run_program_argv(program_string=%r, command_template=%r)" % (program_string, command_template)
-    env = Build.bld.env
+    env = bld.env
 
     if command_template in (None, '%s'):
         argv = shlex.split(program_string)
@@ -169,7 +183,7 @@
         execvec = shlex.split(command_template % (program_node.abspath(env),))
     return program_name, execvec
 
-def run_program(program_string, command_template=None, cwd=None):
+def run_program(program_string, env, command_template=None, cwd=None):
     """
     if command_template is not None, then program_string == program
     name and argv is given by command_template with %s replaced by the
@@ -182,17 +196,17 @@
             cwd = Options.options.cwd_launch
         else:
             cwd = Options.cwd_launch
-    return run_argv(execvec, cwd=cwd)
+    return run_argv(execvec, env, cwd=cwd)
 
 
 
-def run_python_program(program_string):
-    env = Build.bld.env
+def run_python_program(program_string, env):
+    env = bld.env
     execvec = shlex.split(program_string)
     if (Options.options.cwd_launch):
         cwd = Options.options.cwd_launch
     else:
         cwd = Options.cwd_launch
-    return run_argv([env['PYTHON']] + execvec, cwd=cwd)
+    return run_argv([env['PYTHON']] + execvec, env, cwd=cwd)