merge
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Sat, 30 May 2009 17:37:38 +0100
changeset 4539 df8bf70eb486
parent 4538 3048bd67e5cf (current diff)
parent 4479 ba809221f9b3 (diff)
child 4540 e8a12e172432
merge
examples/wscript
src/helper/static-multicast-route-helper.cc
src/helper/static-multicast-route-helper.h
src/internet-stack/arp-ipv4-interface.cc
src/internet-stack/arp-ipv4-interface.h
src/internet-stack/internet-stack.cc
src/internet-stack/internet-stack.h
src/internet-stack/ipv4-loopback-interface.cc
src/internet-stack/ipv4-loopback-interface.h
src/internet-stack/ipv4-static-routing.cc
src/internet-stack/ipv4-static-routing.h
src/wscript
--- a/CHANGES.html	Sat May 30 17:36:50 2009 +0100
+++ b/CHANGES.html	Sat May 30 17:37:38 2009 +0100
@@ -52,11 +52,94 @@
 
 <h2>New API:</h2>
 <ul>
+<li> <b>attributes for class Ipv4</b>
+<p> class Ipv4 now contains attributes in ipv4.cc; the first one
+is called "IpForward" that will enable/disable Ipv4 forwarding.  
+</li>
 </ul>
 
 <h2>Changes to existing API:</h2>
 <ul>
 
+<li><b> Routing decoupled from class Ipv4</b>
+<p> All calls of the form "Ipv4::AddHostRouteTo ()" etc. (i.e. to 
+add static routes, both unicast and multicast) have been moved to a new 
+class Ipv4StaticRouting.  In addition, class Ipv4 now holds only
+one possible routing protocol; the previous way to add routing protocols
+(by ordered list of priority) has been moved to a new class Ipv4ListRouting.
+Class Ipv4 has a new minimal routing API (just to set and get the routing
+protocol):
+<pre>
+-  virtual void AddRoutingProtocol (Ptr&lt;Ipv4RoutingProtocol&gt; routingProtocol, int16_t priority) = 0;
++  virtual void SetRoutingProtocol (Ptr&lt;Ipv4RoutingProtocol&gt; routingProtocol) = 0;
++  virtual Ptr&lt;Ipv4RoutingProtocol&gt; GetRoutingProtocol (void) const = 0;
+</pre>
+</li>
+
+<li><b> class Ipv4RoutingProtocol is refactored</b>
+<p> The abstract base class Ipv4RoutingProtocol has been refactored to
+align with corresponding Linux Ipv4 routing architecture, and has been
+moved from ipv4.h to a new file ipv4-routing-protocol.h.  The new
+methods (RouteOutput () and RouteInput ()) are aligned with Linux 
+ip_route_output() and ip_route_input().  However,
+the general nature of these calls (synchronous routing lookup for
+locally originated packets, and an asynchronous, callback-based lookup
+for forwarded packets) is still the same.
+<pre>
+-  typedef Callback&lt;void, bool, const Ipv4Route&, Ptr&lt;Packet&gt;, const Ipv4Header&&gt; RouteReplyCallback;
++  typedef Callback&lt;void, Ptr&lt;Ipv4Route&gt;, Ptr&lt;const Packet&gt;, const Ipv4Header &&gt; UnicastForwardCallback;
++  typedef Callback&lt;void, Ptr&lt;Ipv4MulticastRoute&gt;, Ptr&lt;const Packet&gt;, const Ipv4Header &&gt; MulticastForwardCallback;
++  typedef Callback&lt;void, Ptr&lt;const Packet&gt;, const Ipv4Header &, uint32_t &gt; LocalDeliverCallback;
++  typedef Callback&lt;void, Ptr&lt;const Packet&gt;, const Ipv4Header &&gt; ErrorCallback;
+-  virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface) = 0;
++  virtual Ptr&lt;Ipv4Route&gt; RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &errno) = 0;
+-  virtual bool RequestRoute (uint32_t interface,
+-                            const Ipv4Header &ipHeader,
+-                            Ptr&lt;Packet&gt; packet,
+-                            RouteReplyCallback routeReply) = 0;
++  virtual bool RouteInput  (Ptr&lt;const Packet&gt; p, const Ipv4Header &header, Ptr&lt;const NetDevice&gt; idev,
++                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
++                             LocalDeliverCallback lcb, ErrorCallback ecb) = 0;
+</pre>
+
+</li>
+<li><b> previous class Ipv4Route, Ipv4MulticastRoute renamed; new classes with
+those same names added</b>
+<p> The previous class Ipv4Route and Ipv4MulticastRoute are used by 
+Ipv4StaticRouting and Ipv4GlobalRouting to record internal routing table
+entries, so they were renamed to class Ipv4RoutingTableEntry and
+Ipv4MulticastRoutingTableEntry, respectively.  In their place, new
+class Ipv4Route and class Ipv4MulticastRoute have been added.  These
+are reference-counted objects that are analogous to Linux struct
+rtable and struct mfc_cache, respectively, to achieve better compatibility
+with Linux routing architecture in the future.  
+
+<li><b> class Ipv4 address-to-interface mapping functions changed</b>
+<p>  There was some general cleanup of functions that involve mappings
+from Ipv4Address to either NetDevice or Ipv4 interface index.  
+<pre>
+-  virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0;
+-  virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const = 0;
++  virtual int32_t GetInterfaceForAddress (Ipv4Address address) const = 0;
++  virtual int32_t GetInterfaceForPrefix (Ipv4Address address, Ipv4Mask mask) const = 0;
+-  virtual int32_t FindInterfaceForDevice(Ptr&lt;NetDevice&gt; nd) const = 0;
++  virtual int32_t GetInterfaceForDevice (Ptr&lt;const NetDevice&gt; device) const = 0;
+-  virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0;
+-  virtual bool GetInterfaceForDestination (Ipv4Address dest,
+-  virtual uint32_t GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask = Ipv4Mask("255.255.255.255"));
+</pre>
+
+<li><b> class Ipv4 multicast join API deleted</b>
+<p> The following methods are not really used in present form since IGMP
+is not being generated, so they have been removed (planned to be replaced
+by multicast socket-based calls in the future):
+
+<pre>
+- virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
+- virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
+</pre>
+
+
 <li><b>Deconflict NetDevice::ifIndex and Ipv4::ifIndex (bug 85).</b>
 <p>All function parameters named "ifIndex" that refer 
 to an Ipv4 interface are instead named "interface".
--- a/RELEASE_NOTES	Sat May 30 17:36:50 2009 +0100
+++ b/RELEASE_NOTES	Sat May 30 17:37:38 2009 +0100
@@ -17,13 +17,21 @@
 
 New user-visible features
 -------------------------
-  a) 802.11e EDCA support: Has been added possibilty to manage QoS traffic on wifi stations.
 
-  b) 802.11n initial support: Has been added support for A-MSDU frame aggregation feature.
+  a) 802.11 MAC:
+     - EDCA multi-qos-class support (Mirko Banchi)
+     - 802.11n initial support for A-MSDU frame aggregation (Mirko Banchi)
+     - aarf-cd and cara rate control algorithms (Federico Maguolo)
+  b) 802.11 PHY:
+     - 802.11b PHY support (Gary Pei)
+     - Nakagami propagation loss model (Timo Bingmann)
+  c) GammaVariable and ErlangVariable (Timo Bingmann)
  
 API changes from ns-3.4
 -----------------------
-API changes for this release are documented in the file CHANGES.html
+API changes for this release are documented in the file CHANGES.html.  The
+internal API and composition of the IPv4 stack underwent significant
+refactoring in this release cycle.
 
 Release 3.4
 ===========
--- a/bindings/python/ns3_module_bridge.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_bridge.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -20,6 +20,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -40,6 +46,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -254,6 +264,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -264,6 +275,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_common.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_common.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -66,6 +66,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -86,6 +92,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -1115,6 +1125,7 @@
                         [])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -1125,6 +1136,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_contrib.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_contrib.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -52,6 +52,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -72,6 +78,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -470,6 +480,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -480,6 +491,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_core.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_core.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -186,6 +186,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -209,6 +215,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -1641,6 +1651,11 @@
                    'ns3::Object::AggregateIterator', 
                    [], 
                    is_const=True)
+    ## object.h: void ns3::Object::NotifyNewAggregate() [member function]
+    cls.add_method('NotifyNewAggregate', 
+                   'void', 
+                   [], 
+                   visibility='protected', is_virtual=True)
     ## object.h: void ns3::Object::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
@@ -2222,6 +2237,7 @@
                         template_parameters=['unsigned char'])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -2288,6 +2304,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     ## double.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::internal::MakeDoubleChecker(double min, double max, std::string name) [free function]
     module.add_function('MakeDoubleChecker', 
--- a/bindings/python/ns3_module_csma.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_csma.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -28,6 +28,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -48,6 +54,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -414,6 +424,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -424,6 +435,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_emu.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_emu.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -18,6 +18,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -38,6 +44,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -206,6 +216,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -216,6 +227,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_global_routing.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_global_routing.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -30,6 +30,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -50,6 +56,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -287,6 +297,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -297,6 +308,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_helper.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_helper.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -17,6 +17,8 @@
     module.add_class('Ipv4AddressHelper', allow_subclassing=False)
     ## ipv4-interface-container.h: ns3::Ipv4InterfaceContainer [class]
     module.add_class('Ipv4InterfaceContainer')
+    ## ipv4-static-routing-helper.h: ns3::Ipv4StaticRoutingHelper [class]
+    module.add_class('Ipv4StaticRoutingHelper', allow_subclassing=False)
     ## mobility-helper.h: ns3::MobilityHelper [class]
     module.add_class('MobilityHelper', allow_subclassing=False)
     ## net-device-container.h: ns3::NetDeviceContainer [class]
@@ -35,8 +37,6 @@
     module.add_class('PacketSocketHelper', allow_subclassing=False)
     ## point-to-point-helper.h: ns3::PointToPointHelper [class]
     module.add_class('PointToPointHelper', allow_subclassing=False)
-    ## static-multicast-route-helper.h: ns3::StaticMulticastRouteHelper [class]
-    module.add_class('StaticMulticastRouteHelper', allow_subclassing=False)
     ## tap-bridge-helper.h: ns3::TapBridgeHelper [class]
     module.add_class('TapBridgeHelper', allow_subclassing=False)
     ## udp-echo-helper.h: ns3::UdpEchoClientHelper [class]
@@ -72,6 +72,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -92,6 +98,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -108,6 +118,7 @@
     register_Ns3InternetStackHelper_methods(root_module, root_module['ns3::InternetStackHelper'])
     register_Ns3Ipv4AddressHelper_methods(root_module, root_module['ns3::Ipv4AddressHelper'])
     register_Ns3Ipv4InterfaceContainer_methods(root_module, root_module['ns3::Ipv4InterfaceContainer'])
+    register_Ns3Ipv4StaticRoutingHelper_methods(root_module, root_module['ns3::Ipv4StaticRoutingHelper'])
     register_Ns3MobilityHelper_methods(root_module, root_module['ns3::MobilityHelper'])
     register_Ns3NetDeviceContainer_methods(root_module, root_module['ns3::NetDeviceContainer'])
     register_Ns3NodeContainer_methods(root_module, root_module['ns3::NodeContainer'])
@@ -117,7 +128,6 @@
     register_Ns3PacketSinkHelper_methods(root_module, root_module['ns3::PacketSinkHelper'])
     register_Ns3PacketSocketHelper_methods(root_module, root_module['ns3::PacketSocketHelper'])
     register_Ns3PointToPointHelper_methods(root_module, root_module['ns3::PointToPointHelper'])
-    register_Ns3StaticMulticastRouteHelper_methods(root_module, root_module['ns3::StaticMulticastRouteHelper'])
     register_Ns3TapBridgeHelper_methods(root_module, root_module['ns3::TapBridgeHelper'])
     register_Ns3UdpEchoClientHelper_methods(root_module, root_module['ns3::UdpEchoClientHelper'])
     register_Ns3UdpEchoServerHelper_methods(root_module, root_module['ns3::UdpEchoServerHelper'])
@@ -423,10 +433,14 @@
                    'void', 
                    [param('ns3::NodeContainer', 'c')], 
                    is_const=True)
-    ## internet-stack-helper.h: void ns3::InternetStackHelper::SetNscStack(std::string soname) [member function]
-    cls.add_method('SetNscStack', 
+    ## internet-stack-helper.h: void ns3::InternetStackHelper::SetTcp(std::string tid) [member function]
+    cls.add_method('SetTcp', 
                    'void', 
-                   [param('std::string', 'soname')])
+                   [param('std::string', 'tid')])
+    ## internet-stack-helper.h: void ns3::InternetStackHelper::SetTcp(std::string tid, std::string attr, ns3::AttributeValue const & val) [member function]
+    cls.add_method('SetTcp', 
+                   'void', 
+                   [param('std::string', 'tid'), param('std::string', 'attr'), param('ns3::AttributeValue const &', 'val')])
     ## internet-stack-helper.h: static void ns3::InternetStackHelper::EnableAscii(std::ostream & os, ns3::NodeContainer n) [member function]
     cls.add_method('EnableAscii', 
                    'void', 
@@ -500,6 +514,50 @@
                    [param('std::string', 'ipv4Name'), param('uint32_t', 'interface')])
     return
 
+def register_Ns3Ipv4StaticRoutingHelper_methods(root_module, cls):
+    ## ipv4-static-routing-helper.h: ns3::Ipv4StaticRoutingHelper::Ipv4StaticRoutingHelper(ns3::Ipv4StaticRoutingHelper const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4StaticRoutingHelper const &', 'arg0')])
+    ## ipv4-static-routing-helper.h: ns3::Ipv4StaticRoutingHelper::Ipv4StaticRoutingHelper() [constructor]
+    cls.add_constructor([])
+    ## ipv4-static-routing-helper.h: ns3::Ptr<ns3::Ipv4StaticRouting> ns3::Ipv4StaticRoutingHelper::GetStaticRouting(ns3::Ptr<ns3::Ipv4> ipv4) const [member function]
+    cls.add_method('GetStaticRouting', 
+                   'ns3::Ptr< ns3::Ipv4StaticRouting >', 
+                   [param('ns3::Ptr< ns3::Ipv4 >', 'ipv4')], 
+                   is_const=True)
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::AddMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ipv4Address source, ns3::Ipv4Address group, ns3::Ptr<ns3::NetDevice> input, ns3::NetDeviceContainer output) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('ns3::Ptr< ns3::NetDevice >', 'input'), param('ns3::NetDeviceContainer', 'output')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::AddMulticastRoute(std::string n, ns3::Ipv4Address source, ns3::Ipv4Address group, ns3::Ptr<ns3::NetDevice> input, ns3::NetDeviceContainer output) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('std::string', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('ns3::Ptr< ns3::NetDevice >', 'input'), param('ns3::NetDeviceContainer', 'output')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::AddMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ipv4Address source, ns3::Ipv4Address group, std::string inputName, ns3::NetDeviceContainer output) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('std::string', 'inputName'), param('ns3::NetDeviceContainer', 'output')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::AddMulticastRoute(std::string nName, ns3::Ipv4Address source, ns3::Ipv4Address group, std::string inputName, ns3::NetDeviceContainer output) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('std::string', 'nName'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('std::string', 'inputName'), param('ns3::NetDeviceContainer', 'output')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ptr<ns3::NetDevice> nd) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ptr< ns3::NetDevice >', 'nd')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(ns3::Ptr<ns3::Node> n, std::string ndName) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'n'), param('std::string', 'ndName')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(std::string nName, ns3::Ptr<ns3::NetDevice> nd) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('std::string', 'nName'), param('ns3::Ptr< ns3::NetDevice >', 'nd')])
+    ## ipv4-static-routing-helper.h: void ns3::Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(std::string nName, std::string ndName) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('std::string', 'nName'), param('std::string', 'ndName')])
+    return
+
 def register_Ns3MobilityHelper_methods(root_module, cls):
     ## mobility-helper.h: ns3::MobilityHelper::MobilityHelper(ns3::MobilityHelper const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::MobilityHelper const &', 'arg0')])
@@ -885,53 +943,6 @@
                    [param('std::string', 'hubName'), param('ns3::NodeContainer', 'spokes'), param('ns3::NetDeviceContainer &', 'hubDevices'), param('ns3::NetDeviceContainer &', 'spokeDevices')])
     return
 
-def register_Ns3StaticMulticastRouteHelper_methods(root_module, cls):
-    ## static-multicast-route-helper.h: ns3::StaticMulticastRouteHelper::StaticMulticastRouteHelper(ns3::StaticMulticastRouteHelper const & arg0) [copy constructor]
-    cls.add_constructor([param('ns3::StaticMulticastRouteHelper const &', 'arg0')])
-    ## static-multicast-route-helper.h: ns3::StaticMulticastRouteHelper::StaticMulticastRouteHelper() [constructor]
-    cls.add_constructor([])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::AddMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ipv4Address source, ns3::Ipv4Address group, ns3::Ptr<ns3::NetDevice> input, ns3::NetDeviceContainer output) [member function]
-    cls.add_method('AddMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('ns3::Ptr< ns3::NetDevice >', 'input'), param('ns3::NetDeviceContainer', 'output')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::AddMulticastRoute(std::string n, ns3::Ipv4Address source, ns3::Ipv4Address group, ns3::Ptr<ns3::NetDevice> input, ns3::NetDeviceContainer output) [member function]
-    cls.add_method('AddMulticastRoute', 
-                   'void', 
-                   [param('std::string', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('ns3::Ptr< ns3::NetDevice >', 'input'), param('ns3::NetDeviceContainer', 'output')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::AddMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ipv4Address source, ns3::Ipv4Address group, std::string inputName, ns3::NetDeviceContainer output) [member function]
-    cls.add_method('AddMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('std::string', 'inputName'), param('ns3::NetDeviceContainer', 'output')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::AddMulticastRoute(std::string nName, ns3::Ipv4Address source, ns3::Ipv4Address group, std::string inputName, ns3::NetDeviceContainer output) [member function]
-    cls.add_method('AddMulticastRoute', 
-                   'void', 
-                   [param('std::string', 'nName'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group'), param('std::string', 'inputName'), param('ns3::NetDeviceContainer', 'output')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::SetDefaultMulticastRoute(ns3::Ptr<ns3::Node> n, ns3::Ptr<ns3::NetDevice> nd) [member function]
-    cls.add_method('SetDefaultMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ptr< ns3::NetDevice >', 'nd')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::SetDefaultMulticastRoute(ns3::Ptr<ns3::Node> n, std::string ndName) [member function]
-    cls.add_method('SetDefaultMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'n'), param('std::string', 'ndName')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::SetDefaultMulticastRoute(std::string nName, ns3::Ptr<ns3::NetDevice> nd) [member function]
-    cls.add_method('SetDefaultMulticastRoute', 
-                   'void', 
-                   [param('std::string', 'nName'), param('ns3::Ptr< ns3::NetDevice >', 'nd')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::SetDefaultMulticastRoute(std::string nName, std::string ndName) [member function]
-    cls.add_method('SetDefaultMulticastRoute', 
-                   'void', 
-                   [param('std::string', 'nName'), param('std::string', 'ndName')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::JoinMulticastGroup(ns3::Ptr<ns3::Node> n, ns3::Ipv4Address source, ns3::Ipv4Address group) [member function]
-    cls.add_method('JoinMulticastGroup', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'n'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group')])
-    ## static-multicast-route-helper.h: void ns3::StaticMulticastRouteHelper::JoinMulticastGroup(std::string nName, ns3::Ipv4Address source, ns3::Ipv4Address group) [member function]
-    cls.add_method('JoinMulticastGroup', 
-                   'void', 
-                   [param('std::string', 'nName'), param('ns3::Ipv4Address', 'source'), param('ns3::Ipv4Address', 'group')])
-    return
-
 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')])
@@ -1264,6 +1275,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -1274,6 +1286,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_internet_stack.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_internet_stack.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -23,8 +23,12 @@
     module.add_enum('Flags_t', ['NONE', 'FIN', 'SYN', 'RST', 'PSH', 'ACK', 'URG'], outer_class=root_module['ns3::TcpHeader'])
     ## udp-header.h: ns3::UdpHeader [class]
     module.add_class('UdpHeader', parent=root_module['ns3::Header'])
+    ## ipv4-static-routing-impl.h: ns3::Ipv4StaticRoutingImpl [class]
+    module.add_class('Ipv4StaticRoutingImpl', parent=root_module['ns3::Ipv4StaticRouting'])
     ## ipv4-global-routing.h: ns3::Ipv4GlobalRouting [class]
     module.add_class('Ipv4GlobalRouting', parent=root_module['ns3::Ipv4RoutingProtocol'])
+    ## ipv4-list-routing-impl.h: ns3::Ipv4ListRoutingImpl [class]
+    module.add_class('Ipv4ListRoutingImpl', parent=root_module['ns3::Ipv4ListRouting'])
     
     ## Register a nested module for the namespace Config
     
@@ -38,6 +42,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -58,6 +68,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -73,7 +87,9 @@
     register_Ns3Icmpv4TimeExceeded_methods(root_module, root_module['ns3::Icmpv4TimeExceeded'])
     register_Ns3TcpHeader_methods(root_module, root_module['ns3::TcpHeader'])
     register_Ns3UdpHeader_methods(root_module, root_module['ns3::UdpHeader'])
+    register_Ns3Ipv4StaticRoutingImpl_methods(root_module, root_module['ns3::Ipv4StaticRoutingImpl'])
     register_Ns3Ipv4GlobalRouting_methods(root_module, root_module['ns3::Ipv4GlobalRouting'])
+    register_Ns3Ipv4ListRoutingImpl_methods(root_module, root_module['ns3::Ipv4ListRoutingImpl'])
     return
 
 def register_Ns3Icmpv4DestinationUnreachable_methods(root_module, cls):
@@ -508,6 +524,118 @@
                    is_const=True)
     return
 
+def register_Ns3Ipv4StaticRoutingImpl_methods(root_module, cls):
+    ## ipv4-static-routing-impl.h: ns3::Ipv4StaticRoutingImpl::Ipv4StaticRoutingImpl(ns3::Ipv4StaticRoutingImpl const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4StaticRoutingImpl const &', 'arg0')])
+    ## ipv4-static-routing-impl.h: static ns3::TypeId ns3::Ipv4StaticRoutingImpl::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## ipv4-static-routing-impl.h: ns3::Ipv4StaticRoutingImpl::Ipv4StaticRoutingImpl() [constructor]
+    cls.add_constructor([])
+    ## ipv4-static-routing-impl.h: ns3::Ptr<ns3::Ipv4Route> ns3::Ipv4StaticRoutingImpl::RouteOutput(ns3::Ipv4Header const & header, uint32_t oif, ns3::Socket::SocketErrno & sockerr) [member function]
+    cls.add_method('RouteOutput', 
+                   'ns3::Ptr< ns3::Ipv4Route >', 
+                   [param('ns3::Ipv4Header const &', 'header'), param('uint32_t', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: bool ns3::Ipv4StaticRoutingImpl::RouteInput(ns3::Ptr<ns3::Packet const> p, ns3::Ipv4Header const & header, ns3::Ptr<const ns3::NetDevice> idev, ns3::Callback<void,ns3::Ptr<ns3::Ipv4Route>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback<void,ns3::Ptr<ns3::Ipv4MulticastRoute>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function]
+    cls.add_method('RouteInput', 
+                   'bool', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv4Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::AddHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('AddHostRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'dest'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::AddHostRouteTo(ns3::Ipv4Address dest, uint32_t interface) [member function]
+    cls.add_method('AddHostRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'dest'), param('uint32_t', 'interface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('AddNetworkRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, uint32_t interface) [member function]
+    cls.add_method('AddNetworkRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('uint32_t', 'interface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::SetDefaultRoute(ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('SetDefaultRoute', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: uint32_t ns3::Ipv4StaticRoutingImpl::GetNRoutes() [member function]
+    cls.add_method('GetNRoutes', 
+                   'uint32_t', 
+                   [], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: ns3::Ipv4RoutingTableEntry ns3::Ipv4StaticRoutingImpl::GetDefaultRoute() [member function]
+    cls.add_method('GetDefaultRoute', 
+                   'ns3::Ipv4RoutingTableEntry', 
+                   [], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: ns3::Ipv4RoutingTableEntry ns3::Ipv4StaticRoutingImpl::GetRoute(uint32_t i) [member function]
+    cls.add_method('GetRoute', 
+                   'ns3::Ipv4RoutingTableEntry', 
+                   [param('uint32_t', 'i')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::RemoveRoute(uint32_t i) [member function]
+    cls.add_method('RemoveRoute', 
+                   'void', 
+                   [param('uint32_t', 'i')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::AddMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface, std::vector<unsigned int, std::allocator<unsigned int> > outputInterfaces) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface'), param('std::vector< unsigned int >', 'outputInterfaces')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::SetDefaultMulticastRoute(uint32_t outputInterface) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('uint32_t', 'outputInterface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: uint32_t ns3::Ipv4StaticRoutingImpl::GetNMulticastRoutes() const [member function]
+    cls.add_method('GetNMulticastRoutes', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-static-routing-impl.h: ns3::Ipv4MulticastRoutingTableEntry ns3::Ipv4StaticRoutingImpl::GetMulticastRoute(uint32_t i) const [member function]
+    cls.add_method('GetMulticastRoute', 
+                   'ns3::Ipv4MulticastRoutingTableEntry', 
+                   [param('uint32_t', 'i')], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-static-routing-impl.h: bool ns3::Ipv4StaticRoutingImpl::RemoveMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface) [member function]
+    cls.add_method('RemoveMulticastRoute', 
+                   'bool', 
+                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::RemoveMulticastRoute(uint32_t index) [member function]
+    cls.add_method('RemoveMulticastRoute', 
+                   'void', 
+                   [param('uint32_t', 'index')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::SetNode(ns3::Ptr<ns3::Node> node) [member function]
+    cls.add_method('SetNode', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'node')], 
+                   is_virtual=True)
+    ## ipv4-static-routing-impl.h: ns3::Ptr<ns3::Node> ns3::Ipv4StaticRoutingImpl::GetNode() const [member function]
+    cls.add_method('GetNode', 
+                   'ns3::Ptr< ns3::Node >', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-static-routing-impl.h: void ns3::Ipv4StaticRoutingImpl::DoDispose() [member function]
+    cls.add_method('DoDispose', 
+                   'void', 
+                   [], 
+                   visibility='protected', is_virtual=True)
+    return
+
 def register_Ns3Ipv4GlobalRouting_methods(root_module, cls):
     ## ipv4-global-routing.h: ns3::Ipv4GlobalRouting::Ipv4GlobalRouting(ns3::Ipv4GlobalRouting const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::Ipv4GlobalRouting const &', 'arg0')])
@@ -518,15 +646,15 @@
                    is_static=True)
     ## ipv4-global-routing.h: ns3::Ipv4GlobalRouting::Ipv4GlobalRouting() [constructor]
     cls.add_constructor([])
-    ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestRoute(uint32_t interface, ns3::Ipv4Header const & ipHeader, ns3::Ptr<ns3::Packet> packet, ns3::Callback<void,bool,const ns3::Ipv4Route&,ns3::Ptr<ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function]
-    cls.add_method('RequestRoute', 
-                   'bool', 
-                   [param('uint32_t', 'interface'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], 
+    ## ipv4-global-routing.h: ns3::Ptr<ns3::Ipv4Route> ns3::Ipv4GlobalRouting::RouteOutput(ns3::Ipv4Header const & header, uint32_t oif, ns3::Socket::SocketErrno & sockerr) [member function]
+    cls.add_method('RouteOutput', 
+                   'ns3::Ptr< ns3::Ipv4Route >', 
+                   [param('ns3::Ipv4Header const &', 'header'), param('uint32_t', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], 
                    is_virtual=True)
-    ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RequestInterface(ns3::Ipv4Address destination, uint32_t & interface) [member function]
-    cls.add_method('RequestInterface', 
+    ## ipv4-global-routing.h: bool ns3::Ipv4GlobalRouting::RouteInput(ns3::Ptr<ns3::Packet const> p, ns3::Ipv4Header const & header, ns3::Ptr<const ns3::NetDevice> idev, ns3::Callback<void,ns3::Ptr<ns3::Ipv4Route>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback<void,ns3::Ptr<ns3::Ipv4MulticastRoute>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function]
+    cls.add_method('RouteInput', 
                    'bool', 
-                   [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'interface')], 
+                   [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv4Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], 
                    is_virtual=True)
     ## ipv4-global-routing.h: void ns3::Ipv4GlobalRouting::AddHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
     cls.add_method('AddHostRouteTo', 
@@ -548,14 +676,23 @@
     cls.add_method('GetNRoutes', 
                    'uint32_t', 
                    [])
-    ## ipv4-global-routing.h: ns3::Ipv4Route * ns3::Ipv4GlobalRouting::GetRoute(uint32_t i) [member function]
+    ## ipv4-global-routing.h: ns3::Ipv4RoutingTableEntry * ns3::Ipv4GlobalRouting::GetRoute(uint32_t i) [member function]
     cls.add_method('GetRoute', 
-                   'ns3::Ipv4Route *', 
+                   'ns3::Ipv4RoutingTableEntry *', 
                    [param('uint32_t', 'i')])
     ## ipv4-global-routing.h: void ns3::Ipv4GlobalRouting::RemoveRoute(uint32_t i) [member function]
     cls.add_method('RemoveRoute', 
                    'void', 
                    [param('uint32_t', 'i')])
+    ## ipv4-global-routing.h: void ns3::Ipv4GlobalRouting::SetNode(ns3::Ptr<ns3::Node> node) [member function]
+    cls.add_method('SetNode', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'node')])
+    ## ipv4-global-routing.h: ns3::Ptr<ns3::Node> ns3::Ipv4GlobalRouting::GetNode() const [member function]
+    cls.add_method('GetNode', 
+                   'ns3::Ptr< ns3::Node >', 
+                   [], 
+                   is_const=True)
     ## ipv4-global-routing.h: void ns3::Ipv4GlobalRouting::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
@@ -563,18 +700,67 @@
                    visibility='protected', is_virtual=True)
     return
 
+def register_Ns3Ipv4ListRoutingImpl_methods(root_module, cls):
+    ## ipv4-list-routing-impl.h: ns3::Ipv4ListRoutingImpl::Ipv4ListRoutingImpl(ns3::Ipv4ListRoutingImpl const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4ListRoutingImpl const &', 'arg0')])
+    ## ipv4-list-routing-impl.h: static ns3::TypeId ns3::Ipv4ListRoutingImpl::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## ipv4-list-routing-impl.h: ns3::Ipv4ListRoutingImpl::Ipv4ListRoutingImpl() [constructor]
+    cls.add_constructor([])
+    ## ipv4-list-routing-impl.h: ns3::Ptr<ns3::Ipv4Route> ns3::Ipv4ListRoutingImpl::RouteOutput(ns3::Ipv4Header const & header, uint32_t oif, ns3::Socket::SocketErrno & sockerr) [member function]
+    cls.add_method('RouteOutput', 
+                   'ns3::Ptr< ns3::Ipv4Route >', 
+                   [param('ns3::Ipv4Header const &', 'header'), param('uint32_t', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], 
+                   is_virtual=True)
+    ## ipv4-list-routing-impl.h: bool ns3::Ipv4ListRoutingImpl::RouteInput(ns3::Ptr<ns3::Packet const> p, ns3::Ipv4Header const & header, ns3::Ptr<const ns3::NetDevice> idev, ns3::Callback<void,ns3::Ptr<ns3::Ipv4Route>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback<void,ns3::Ptr<ns3::Ipv4MulticastRoute>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function]
+    cls.add_method('RouteInput', 
+                   'bool', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv4Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], 
+                   is_virtual=True)
+    ## ipv4-list-routing-impl.h: void ns3::Ipv4ListRoutingImpl::AddRoutingProtocol(ns3::Ptr<ns3::Ipv4RoutingProtocol> routingProtocol, int16_t priority) [member function]
+    cls.add_method('AddRoutingProtocol', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Ipv4RoutingProtocol >', 'routingProtocol'), param('int16_t', 'priority')], 
+                   is_virtual=True)
+    ## ipv4-list-routing-impl.h: uint32_t ns3::Ipv4ListRoutingImpl::GetNRoutingProtocols() const [member function]
+    cls.add_method('GetNRoutingProtocols', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-list-routing-impl.h: ns3::Ptr<ns3::Ipv4RoutingProtocol> ns3::Ipv4ListRoutingImpl::GetRoutingProtocol(uint32_t index, int16_t & priority) const [member function]
+    cls.add_method('GetRoutingProtocol', 
+                   'ns3::Ptr< ns3::Ipv4RoutingProtocol >', 
+                   [param('uint32_t', 'index'), param('int16_t &', 'priority')], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-list-routing-impl.h: ns3::Ptr<ns3::Ipv4StaticRouting> ns3::Ipv4ListRoutingImpl::GetStaticRouting() const [member function]
+    cls.add_method('GetStaticRouting', 
+                   'ns3::Ptr< ns3::Ipv4StaticRouting >', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## ipv4-list-routing-impl.h: void ns3::Ipv4ListRoutingImpl::SetNode(ns3::Ptr<ns3::Node> node) [member function]
+    cls.add_method('SetNode', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'node')])
+    ## ipv4-list-routing-impl.h: ns3::Ptr<ns3::Node> ns3::Ipv4ListRoutingImpl::GetNode() const [member function]
+    cls.add_method('GetNode', 
+                   'ns3::Ptr< ns3::Node >', 
+                   [], 
+                   is_const=True)
+    ## ipv4-list-routing-impl.h: void ns3::Ipv4ListRoutingImpl::DoDispose() [member function]
+    cls.add_method('DoDispose', 
+                   'void', 
+                   [], 
+                   visibility='protected', is_virtual=True)
+    return
+
 def register_functions(root_module):
     module = root_module
-    ## internet-stack.h: extern void ns3::AddInternetStack(ns3::Ptr<ns3::Node> node) [free function]
-    module.add_function('AddInternetStack', 
-                        'void', 
-                        [param('ns3::Ptr< ns3::Node >', 'node')])
-    ## internet-stack.h: extern void ns3::AddNscInternetStack(ns3::Ptr<ns3::Node> node, std::string const & soname) [free function]
-    module.add_function('AddNscInternetStack', 
-                        'void', 
-                        [param('ns3::Ptr< ns3::Node >', 'node'), param('std::string const &', 'soname')])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -585,6 +771,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_mobility.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_mobility.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -62,6 +62,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -82,6 +88,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -748,6 +758,7 @@
                         [])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -758,6 +769,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_node.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_node.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -29,10 +29,10 @@
     module.add_enum('InterfaceAddressScope_e', ['HOST', 'LINK', 'GLOBAL'], outer_class=root_module['ns3::Ipv4InterfaceAddress'])
     ## ipv4-address.h: ns3::Ipv4Mask [class]
     module.add_class('Ipv4Mask')
-    ## ipv4-route.h: ns3::Ipv4MulticastRoute [class]
-    module.add_class('Ipv4MulticastRoute')
-    ## ipv4-route.h: ns3::Ipv4Route [class]
-    module.add_class('Ipv4Route')
+    ## ipv4-routing-table-entry.h: ns3::Ipv4MulticastRoutingTableEntry [class]
+    module.add_class('Ipv4MulticastRoutingTableEntry')
+    ## ipv4-routing-table-entry.h: ns3::Ipv4RoutingTableEntry [class]
+    module.add_class('Ipv4RoutingTableEntry')
     ## ipv6-address.h: ns3::Ipv6Address [class]
     module.add_class('Ipv6Address')
     ## ipv6-address.h: ns3::Ipv6Address [class]
@@ -63,6 +63,10 @@
     module.add_class('Ipv4MaskChecker', parent=root_module['ns3::AttributeChecker'])
     ## ipv4-address.h: ns3::Ipv4MaskValue [class]
     module.add_class('Ipv4MaskValue', parent=root_module['ns3::AttributeValue'])
+    ## ipv4-route.h: ns3::Ipv4MulticastRoute [class]
+    module.add_class('Ipv4MulticastRoute', parent=root_module['ns3::RefCountBase'])
+    ## ipv4-route.h: ns3::Ipv4Route [class]
+    module.add_class('Ipv4Route', parent=root_module['ns3::RefCountBase'])
     ## ipv6-address.h: ns3::Ipv6AddressChecker [class]
     module.add_class('Ipv6AddressChecker', parent=root_module['ns3::AttributeChecker'])
     ## ipv6-address.h: ns3::Ipv6AddressValue [class]
@@ -123,8 +127,10 @@
     module.add_class('Ipv4', parent=root_module['ns3::Object'])
     ## ipv4-raw-socket-factory.h: ns3::Ipv4RawSocketFactory [class]
     module.add_class('Ipv4RawSocketFactory', parent=root_module['ns3::SocketFactory'])
-    ## ipv4.h: ns3::Ipv4RoutingProtocol [class]
+    ## ipv4-routing-protocol.h: ns3::Ipv4RoutingProtocol [class]
     module.add_class('Ipv4RoutingProtocol', parent=root_module['ns3::Object'])
+    ## ipv4-static-routing.h: ns3::Ipv4StaticRouting [class]
+    module.add_class('Ipv4StaticRouting', parent=root_module['ns3::Ipv4RoutingProtocol'])
     ## net-device.h: ns3::NetDevice [class]
     module.add_class('NetDevice', parent=root_module['ns3::Object'])
     ## net-device.h: ns3::NetDevice::PacketType [enumeration]
@@ -137,6 +143,8 @@
     module.add_class('SimpleChannel', parent=root_module['ns3::Channel'])
     ## simple-net-device.h: ns3::SimpleNetDevice [class]
     module.add_class('SimpleNetDevice', parent=root_module['ns3::NetDevice'])
+    ## ipv4-list-routing.h: ns3::Ipv4ListRouting [class]
+    module.add_class('Ipv4ListRouting', parent=root_module['ns3::Ipv4RoutingProtocol'])
     module.add_container('ns3::olsr::MprSet', 'ns3::Ipv4Address', container_type='set')
     module.add_container('std::vector< ns3::Ipv4Address >', 'ns3::Ipv4Address', container_type='vector')
     
@@ -152,6 +160,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -172,6 +186,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -188,8 +206,8 @@
     register_Ns3Ipv4AddressGenerator_methods(root_module, root_module['ns3::Ipv4AddressGenerator'])
     register_Ns3Ipv4InterfaceAddress_methods(root_module, root_module['ns3::Ipv4InterfaceAddress'])
     register_Ns3Ipv4Mask_methods(root_module, root_module['ns3::Ipv4Mask'])
-    register_Ns3Ipv4MulticastRoute_methods(root_module, root_module['ns3::Ipv4MulticastRoute'])
-    register_Ns3Ipv4Route_methods(root_module, root_module['ns3::Ipv4Route'])
+    register_Ns3Ipv4MulticastRoutingTableEntry_methods(root_module, root_module['ns3::Ipv4MulticastRoutingTableEntry'])
+    register_Ns3Ipv4RoutingTableEntry_methods(root_module, root_module['ns3::Ipv4RoutingTableEntry'])
     register_Ns3Ipv6Address_methods(root_module, root_module['ns3::Ipv6Address'])
     register_Ns3Ipv6Prefix_methods(root_module, root_module['ns3::Ipv6Prefix'])
     register_Ns3Mac48Address_methods(root_module, root_module['ns3::Mac48Address'])
@@ -201,6 +219,8 @@
     register_Ns3Ipv4Header_methods(root_module, root_module['ns3::Ipv4Header'])
     register_Ns3Ipv4MaskChecker_methods(root_module, root_module['ns3::Ipv4MaskChecker'])
     register_Ns3Ipv4MaskValue_methods(root_module, root_module['ns3::Ipv4MaskValue'])
+    register_Ns3Ipv4MulticastRoute_methods(root_module, root_module['ns3::Ipv4MulticastRoute'])
+    register_Ns3Ipv4Route_methods(root_module, root_module['ns3::Ipv4Route'])
     register_Ns3Ipv6AddressChecker_methods(root_module, root_module['ns3::Ipv6AddressChecker'])
     register_Ns3Ipv6AddressValue_methods(root_module, root_module['ns3::Ipv6AddressValue'])
     register_Ns3Ipv6Header_methods(root_module, root_module['ns3::Ipv6Header'])
@@ -229,11 +249,13 @@
     register_Ns3Ipv4_methods(root_module, root_module['ns3::Ipv4'])
     register_Ns3Ipv4RawSocketFactory_methods(root_module, root_module['ns3::Ipv4RawSocketFactory'])
     register_Ns3Ipv4RoutingProtocol_methods(root_module, root_module['ns3::Ipv4RoutingProtocol'])
+    register_Ns3Ipv4StaticRouting_methods(root_module, root_module['ns3::Ipv4StaticRouting'])
     register_Ns3NetDevice_methods(root_module, root_module['ns3::NetDevice'])
     register_Ns3Node_methods(root_module, root_module['ns3::Node'])
     register_Ns3PacketSocketFactory_methods(root_module, root_module['ns3::PacketSocketFactory'])
     register_Ns3SimpleChannel_methods(root_module, root_module['ns3::SimpleChannel'])
     register_Ns3SimpleNetDevice_methods(root_module, root_module['ns3::SimpleNetDevice'])
+    register_Ns3Ipv4ListRouting_methods(root_module, root_module['ns3::Ipv4ListRouting'])
     return
 
 def register_Ns3Address_methods(root_module, cls):
@@ -664,125 +686,125 @@
                    [param('uint32_t', 'mask')])
     return
 
-def register_Ns3Ipv4MulticastRoute_methods(root_module, cls):
+def register_Ns3Ipv4MulticastRoutingTableEntry_methods(root_module, cls):
     cls.add_output_stream_operator()
-    ## ipv4-route.h: ns3::Ipv4MulticastRoute::Ipv4MulticastRoute() [constructor]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry() [constructor]
     cls.add_constructor([])
-    ## ipv4-route.h: ns3::Ipv4MulticastRoute::Ipv4MulticastRoute(ns3::Ipv4MulticastRoute const & route) [copy constructor]
-    cls.add_constructor([param('ns3::Ipv4MulticastRoute const &', 'route')])
-    ## ipv4-route.h: ns3::Ipv4MulticastRoute::Ipv4MulticastRoute(ns3::Ipv4MulticastRoute const * route) [constructor]
-    cls.add_constructor([param('ns3::Ipv4MulticastRoute const *', 'route')])
-    ## ipv4-route.h: static ns3::Ipv4MulticastRoute ns3::Ipv4MulticastRoute::CreateMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface, std::vector<unsigned int, std::allocator<unsigned int> > outputInterfaces) [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry(ns3::Ipv4MulticastRoutingTableEntry const & route) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4MulticastRoutingTableEntry const &', 'route')])
+    ## ipv4-routing-table-entry.h: ns3::Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry(ns3::Ipv4MulticastRoutingTableEntry const * route) [constructor]
+    cls.add_constructor([param('ns3::Ipv4MulticastRoutingTableEntry const *', 'route')])
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4MulticastRoutingTableEntry ns3::Ipv4MulticastRoutingTableEntry::CreateMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface, std::vector<unsigned int, std::allocator<unsigned int> > outputInterfaces) [member function]
     cls.add_method('CreateMulticastRoute', 
-                   'ns3::Ipv4MulticastRoute', 
+                   'ns3::Ipv4MulticastRoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface'), param('std::vector< unsigned int >', 'outputInterfaces')], 
                    is_static=True)
-    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4MulticastRoute::GetGroup() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Address ns3::Ipv4MulticastRoutingTableEntry::GetGroup() const [member function]
     cls.add_method('GetGroup', 
                    'ns3::Ipv4Address', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: uint32_t ns3::Ipv4MulticastRoute::GetInputInterface() const [member function]
+    ## ipv4-routing-table-entry.h: uint32_t ns3::Ipv4MulticastRoutingTableEntry::GetInputInterface() const [member function]
     cls.add_method('GetInputInterface', 
                    'uint32_t', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: uint32_t ns3::Ipv4MulticastRoute::GetNOutputInterfaces() const [member function]
+    ## ipv4-routing-table-entry.h: uint32_t ns3::Ipv4MulticastRoutingTableEntry::GetNOutputInterfaces() const [member function]
     cls.add_method('GetNOutputInterfaces', 
                    'uint32_t', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4MulticastRoute::GetOrigin() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Address ns3::Ipv4MulticastRoutingTableEntry::GetOrigin() const [member function]
     cls.add_method('GetOrigin', 
                    'ns3::Ipv4Address', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: uint32_t ns3::Ipv4MulticastRoute::GetOutputInterface(uint32_t n) const [member function]
+    ## ipv4-routing-table-entry.h: uint32_t ns3::Ipv4MulticastRoutingTableEntry::GetOutputInterface(uint32_t n) const [member function]
     cls.add_method('GetOutputInterface', 
                    'uint32_t', 
                    [param('uint32_t', 'n')], 
                    is_const=True)
-    ## ipv4-route.h: std::vector<unsigned int, std::allocator<unsigned int> > ns3::Ipv4MulticastRoute::GetOutputInterfaces() const [member function]
+    ## ipv4-routing-table-entry.h: std::vector<unsigned int, std::allocator<unsigned int> > ns3::Ipv4MulticastRoutingTableEntry::GetOutputInterfaces() const [member function]
     cls.add_method('GetOutputInterfaces', 
                    'std::vector< unsigned int >', 
                    [], 
                    is_const=True)
     return
 
-def register_Ns3Ipv4Route_methods(root_module, cls):
+def register_Ns3Ipv4RoutingTableEntry_methods(root_module, cls):
     cls.add_output_stream_operator()
-    ## ipv4-route.h: ns3::Ipv4Route::Ipv4Route() [constructor]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4RoutingTableEntry::Ipv4RoutingTableEntry() [constructor]
     cls.add_constructor([])
-    ## ipv4-route.h: ns3::Ipv4Route::Ipv4Route(ns3::Ipv4Route const & route) [copy constructor]
-    cls.add_constructor([param('ns3::Ipv4Route const &', 'route')])
-    ## ipv4-route.h: ns3::Ipv4Route::Ipv4Route(ns3::Ipv4Route const * route) [constructor]
-    cls.add_constructor([param('ns3::Ipv4Route const *', 'route')])
-    ## ipv4-route.h: static ns3::Ipv4Route ns3::Ipv4Route::CreateDefaultRoute(ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4RoutingTableEntry::Ipv4RoutingTableEntry(ns3::Ipv4RoutingTableEntry const & route) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4RoutingTableEntry const &', 'route')])
+    ## ipv4-routing-table-entry.h: ns3::Ipv4RoutingTableEntry::Ipv4RoutingTableEntry(ns3::Ipv4RoutingTableEntry const * route) [constructor]
+    cls.add_constructor([param('ns3::Ipv4RoutingTableEntry const *', 'route')])
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4RoutingTableEntry ns3::Ipv4RoutingTableEntry::CreateDefaultRoute(ns3::Ipv4Address nextHop, uint32_t interface) [member function]
     cls.add_method('CreateDefaultRoute', 
-                   'ns3::Ipv4Route', 
+                   'ns3::Ipv4RoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
                    is_static=True)
-    ## ipv4-route.h: static ns3::Ipv4Route ns3::Ipv4Route::CreateHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4RoutingTableEntry ns3::Ipv4RoutingTableEntry::CreateHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
     cls.add_method('CreateHostRouteTo', 
-                   'ns3::Ipv4Route', 
+                   'ns3::Ipv4RoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'dest'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
                    is_static=True)
-    ## ipv4-route.h: static ns3::Ipv4Route ns3::Ipv4Route::CreateHostRouteTo(ns3::Ipv4Address dest, uint32_t interface) [member function]
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4RoutingTableEntry ns3::Ipv4RoutingTableEntry::CreateHostRouteTo(ns3::Ipv4Address dest, uint32_t interface) [member function]
     cls.add_method('CreateHostRouteTo', 
-                   'ns3::Ipv4Route', 
+                   'ns3::Ipv4RoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'dest'), param('uint32_t', 'interface')], 
                    is_static=True)
-    ## ipv4-route.h: static ns3::Ipv4Route ns3::Ipv4Route::CreateNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4RoutingTableEntry ns3::Ipv4RoutingTableEntry::CreateNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
     cls.add_method('CreateNetworkRouteTo', 
-                   'ns3::Ipv4Route', 
+                   'ns3::Ipv4RoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
                    is_static=True)
-    ## ipv4-route.h: static ns3::Ipv4Route ns3::Ipv4Route::CreateNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, uint32_t interface) [member function]
+    ## ipv4-routing-table-entry.h: static ns3::Ipv4RoutingTableEntry ns3::Ipv4RoutingTableEntry::CreateNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, uint32_t interface) [member function]
     cls.add_method('CreateNetworkRouteTo', 
-                   'ns3::Ipv4Route', 
+                   'ns3::Ipv4RoutingTableEntry', 
                    [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('uint32_t', 'interface')], 
                    is_static=True)
-    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetDest() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Address ns3::Ipv4RoutingTableEntry::GetDest() const [member function]
     cls.add_method('GetDest', 
                    'ns3::Ipv4Address', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetDestNetwork() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Address ns3::Ipv4RoutingTableEntry::GetDestNetwork() const [member function]
     cls.add_method('GetDestNetwork', 
                    'ns3::Ipv4Address', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: ns3::Ipv4Mask ns3::Ipv4Route::GetDestNetworkMask() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Mask ns3::Ipv4RoutingTableEntry::GetDestNetworkMask() const [member function]
     cls.add_method('GetDestNetworkMask', 
                    'ns3::Ipv4Mask', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetGateway() const [member function]
+    ## ipv4-routing-table-entry.h: ns3::Ipv4Address ns3::Ipv4RoutingTableEntry::GetGateway() const [member function]
     cls.add_method('GetGateway', 
                    'ns3::Ipv4Address', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: uint32_t ns3::Ipv4Route::GetInterface() const [member function]
+    ## ipv4-routing-table-entry.h: uint32_t ns3::Ipv4RoutingTableEntry::GetInterface() const [member function]
     cls.add_method('GetInterface', 
                    'uint32_t', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: bool ns3::Ipv4Route::IsDefault() const [member function]
+    ## ipv4-routing-table-entry.h: bool ns3::Ipv4RoutingTableEntry::IsDefault() const [member function]
     cls.add_method('IsDefault', 
                    'bool', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: bool ns3::Ipv4Route::IsGateway() const [member function]
+    ## ipv4-routing-table-entry.h: bool ns3::Ipv4RoutingTableEntry::IsGateway() const [member function]
     cls.add_method('IsGateway', 
                    'bool', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: bool ns3::Ipv4Route::IsHost() const [member function]
+    ## ipv4-routing-table-entry.h: bool ns3::Ipv4RoutingTableEntry::IsHost() const [member function]
     cls.add_method('IsHost', 
                    'bool', 
                    [], 
                    is_const=True)
-    ## ipv4-route.h: bool ns3::Ipv4Route::IsNetwork() const [member function]
+    ## ipv4-routing-table-entry.h: bool ns3::Ipv4RoutingTableEntry::IsNetwork() const [member function]
     cls.add_method('IsNetwork', 
                    'bool', 
                    [], 
@@ -1403,6 +1425,97 @@
                    is_virtual=True)
     return
 
+def register_Ns3Ipv4MulticastRoute_methods(root_module, cls):
+    ## ipv4-route.h: ns3::Ipv4MulticastRoute::MAX_INTERFACES [variable]
+    cls.add_static_attribute('MAX_INTERFACES', 'uint32_t const', is_const=True)
+    ## ipv4-route.h: ns3::Ipv4MulticastRoute::MAX_TTL [variable]
+    cls.add_static_attribute('MAX_TTL', 'uint32_t const', is_const=True)
+    ## ipv4-route.h: ns3::Ipv4MulticastRoute::Ipv4MulticastRoute(ns3::Ipv4MulticastRoute const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4MulticastRoute const &', 'arg0')])
+    ## ipv4-route.h: ns3::Ipv4MulticastRoute::Ipv4MulticastRoute() [constructor]
+    cls.add_constructor([])
+    ## ipv4-route.h: void ns3::Ipv4MulticastRoute::SetGroup(ns3::Ipv4Address const group) [member function]
+    cls.add_method('SetGroup', 
+                   'void', 
+                   [param('ns3::Ipv4Address const', 'group')])
+    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4MulticastRoute::GetGroup() const [member function]
+    cls.add_method('GetGroup', 
+                   'ns3::Ipv4Address', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: void ns3::Ipv4MulticastRoute::SetOrigin(ns3::Ipv4Address const group) [member function]
+    cls.add_method('SetOrigin', 
+                   'void', 
+                   [param('ns3::Ipv4Address const', 'group')])
+    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4MulticastRoute::GetOrigin() const [member function]
+    cls.add_method('GetOrigin', 
+                   'ns3::Ipv4Address', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: void ns3::Ipv4MulticastRoute::SetParent(uint32_t iif) [member function]
+    cls.add_method('SetParent', 
+                   'void', 
+                   [param('uint32_t', 'iif')])
+    ## ipv4-route.h: uint32_t ns3::Ipv4MulticastRoute::GetParent() const [member function]
+    cls.add_method('GetParent', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: void ns3::Ipv4MulticastRoute::SetOutputTtl(uint32_t oif, uint32_t ttl) [member function]
+    cls.add_method('SetOutputTtl', 
+                   'void', 
+                   [param('uint32_t', 'oif'), param('uint32_t', 'ttl')])
+    ## ipv4-route.h: uint32_t ns3::Ipv4MulticastRoute::GetOutputTtl(uint32_t oif) const [member function]
+    cls.add_method('GetOutputTtl', 
+                   'uint32_t', 
+                   [param('uint32_t', 'oif')], 
+                   is_const=True)
+    return
+
+def register_Ns3Ipv4Route_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    ## ipv4-route.h: ns3::Ipv4Route::Ipv4Route(ns3::Ipv4Route const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4Route const &', 'arg0')])
+    ## ipv4-route.h: ns3::Ipv4Route::Ipv4Route() [constructor]
+    cls.add_constructor([])
+    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetDestination() const [member function]
+    cls.add_method('GetDestination', 
+                   'ns3::Ipv4Address', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetGateway() const [member function]
+    cls.add_method('GetGateway', 
+                   'ns3::Ipv4Address', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: ns3::Ptr<ns3::NetDevice> ns3::Ipv4Route::GetOutputDevice() const [member function]
+    cls.add_method('GetOutputDevice', 
+                   'ns3::Ptr< ns3::NetDevice >', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: ns3::Ipv4Address ns3::Ipv4Route::GetSource() const [member function]
+    cls.add_method('GetSource', 
+                   'ns3::Ipv4Address', 
+                   [], 
+                   is_const=True)
+    ## ipv4-route.h: void ns3::Ipv4Route::SetDestination(ns3::Ipv4Address dest) [member function]
+    cls.add_method('SetDestination', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'dest')])
+    ## ipv4-route.h: void ns3::Ipv4Route::SetGateway(ns3::Ipv4Address gw) [member function]
+    cls.add_method('SetGateway', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'gw')])
+    ## ipv4-route.h: void ns3::Ipv4Route::SetOutputDevice(ns3::Ptr<ns3::NetDevice> outputDevice) [member function]
+    cls.add_method('SetOutputDevice', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::NetDevice >', 'outputDevice')])
+    ## ipv4-route.h: void ns3::Ipv4Route::SetSource(ns3::Ipv4Address src) [member function]
+    cls.add_method('SetSource', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'src')])
+    return
+
 def register_Ns3Ipv6AddressChecker_methods(root_module, cls):
     ## ipv6-address.h: ns3::Ipv6AddressChecker::Ipv6AddressChecker(ns3::Ipv6AddressChecker const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::Ipv6AddressChecker const &', 'arg0')])
@@ -2219,6 +2332,16 @@
                    is_static=True)
     ## udp-socket.h: ns3::UdpSocket::UdpSocket() [constructor]
     cls.add_constructor([])
+    ## udp-socket.h: int ns3::UdpSocket::MulticastJoinGroup(uint32_t interface, ns3::Address const & groupAddress) [member function]
+    cls.add_method('MulticastJoinGroup', 
+                   'int', 
+                   [param('uint32_t', 'interface'), param('ns3::Address const &', 'groupAddress')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## udp-socket.h: int ns3::UdpSocket::MulticastLeaveGroup(uint32_t interface, ns3::Address const & groupAddress) [member function]
+    cls.add_method('MulticastLeaveGroup', 
+                   'int', 
+                   [param('uint32_t', 'interface'), param('ns3::Address const &', 'groupAddress')], 
+                   is_pure_virtual=True, is_virtual=True)
     ## udp-socket.h: void ns3::UdpSocket::SetRcvBufSize(uint32_t size) [member function]
     cls.add_method('SetRcvBufSize', 
                    'void', 
@@ -2229,24 +2352,44 @@
                    'uint32_t', 
                    [], 
                    is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
-    ## udp-socket.h: void ns3::UdpSocket::SetIpTtl(uint32_t ipTtl) [member function]
+    ## udp-socket.h: void ns3::UdpSocket::SetIpTtl(uint8_t ipTtl) [member function]
     cls.add_method('SetIpTtl', 
                    'void', 
-                   [param('uint32_t', 'ipTtl')], 
+                   [param('uint8_t', 'ipTtl')], 
                    is_pure_virtual=True, visibility='private', is_virtual=True)
-    ## udp-socket.h: uint32_t ns3::UdpSocket::GetIpTtl() const [member function]
+    ## udp-socket.h: uint8_t ns3::UdpSocket::GetIpTtl() const [member function]
     cls.add_method('GetIpTtl', 
-                   'uint32_t', 
+                   'uint8_t', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: void ns3::UdpSocket::SetIpMulticastTtl(uint8_t ipTtl) [member function]
+    cls.add_method('SetIpMulticastTtl', 
+                   'void', 
+                   [param('uint8_t', 'ipTtl')], 
+                   is_pure_virtual=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: uint8_t ns3::UdpSocket::GetIpMulticastTtl() const [member function]
+    cls.add_method('GetIpMulticastTtl', 
+                   'uint8_t', 
                    [], 
                    is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
-    ## udp-socket.h: void ns3::UdpSocket::SetIpMulticastTtl(uint32_t ipTtl) [member function]
-    cls.add_method('SetIpMulticastTtl', 
+    ## udp-socket.h: void ns3::UdpSocket::SetIpMulticastIf(int32_t ipIf) [member function]
+    cls.add_method('SetIpMulticastIf', 
                    'void', 
-                   [param('uint32_t', 'ipTtl')], 
+                   [param('int32_t', 'ipIf')], 
                    is_pure_virtual=True, visibility='private', is_virtual=True)
-    ## udp-socket.h: uint32_t ns3::UdpSocket::GetIpMulticastTtl() const [member function]
-    cls.add_method('GetIpMulticastTtl', 
-                   'uint32_t', 
+    ## udp-socket.h: int32_t ns3::UdpSocket::GetIpMulticastIf() const [member function]
+    cls.add_method('GetIpMulticastIf', 
+                   'int32_t', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: void ns3::UdpSocket::SetIpMulticastLoop(bool loop) [member function]
+    cls.add_method('SetIpMulticastLoop', 
+                   'void', 
+                   [param('bool', 'loop')], 
+                   is_pure_virtual=True, visibility='private', is_virtual=True)
+    ## udp-socket.h: bool ns3::UdpSocket::GetIpMulticastLoop() const [member function]
+    cls.add_method('GetIpMulticastLoop', 
+                   'bool', 
                    [], 
                    is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
     ## udp-socket.h: void ns3::UdpSocket::SetMtuDiscover(bool discover) [member function]
@@ -2572,6 +2715,8 @@
     return
 
 def register_Ns3Ipv4_methods(root_module, cls):
+    ## ipv4.h: ns3::Ipv4::IF_ANY [variable]
+    cls.add_static_attribute('IF_ANY', 'uint32_t const', is_const=True)
     ## ipv4.h: ns3::Ipv4::Ipv4(ns3::Ipv4 const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::Ipv4 const &', 'arg0')])
     ## ipv4.h: static ns3::TypeId ns3::Ipv4::GetTypeId() [member function]
@@ -2581,81 +2726,16 @@
                    is_static=True)
     ## ipv4.h: ns3::Ipv4::Ipv4() [constructor]
     cls.add_constructor([])
-    ## ipv4.h: void ns3::Ipv4::AddRoutingProtocol(ns3::Ptr<ns3::Ipv4RoutingProtocol> routingProtocol, int16_t priority) [member function]
-    cls.add_method('AddRoutingProtocol', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Ipv4RoutingProtocol >', 'routingProtocol'), param('int16_t', 'priority')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::AddHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
-    cls.add_method('AddHostRouteTo', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'dest'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::AddHostRouteTo(ns3::Ipv4Address dest, uint32_t interface) [member function]
-    cls.add_method('AddHostRouteTo', 
+    ## ipv4.h: void ns3::Ipv4::SetRoutingProtocol(ns3::Ptr<ns3::Ipv4RoutingProtocol> routingProtocol) [member function]
+    cls.add_method('SetRoutingProtocol', 
                    'void', 
-                   [param('ns3::Ipv4Address', 'dest'), param('uint32_t', 'interface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
-    cls.add_method('AddNetworkRouteTo', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, uint32_t interface) [member function]
-    cls.add_method('AddNetworkRouteTo', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('uint32_t', 'interface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::SetDefaultRoute(ns3::Ipv4Address nextHop, uint32_t interface) [member function]
-    cls.add_method('SetDefaultRoute', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   [param('ns3::Ptr< ns3::Ipv4RoutingProtocol >', 'routingProtocol')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: uint32_t ns3::Ipv4::GetNRoutes() [member function]
-    cls.add_method('GetNRoutes', 
-                   'uint32_t', 
-                   [], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: ns3::Ipv4Route ns3::Ipv4::GetRoute(uint32_t i) [member function]
-    cls.add_method('GetRoute', 
-                   'ns3::Ipv4Route', 
-                   [param('uint32_t', 'i')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::RemoveRoute(uint32_t i) [member function]
-    cls.add_method('RemoveRoute', 
-                   'void', 
-                   [param('uint32_t', 'i')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::AddMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface, std::vector<unsigned int, std::allocator<unsigned int> > outputInterfaces) [member function]
-    cls.add_method('AddMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface'), param('std::vector< unsigned int >', 'outputInterfaces')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::RemoveMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface) [member function]
-    cls.add_method('RemoveMulticastRoute', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::SetDefaultMulticastRoute(uint32_t outputInterface) [member function]
-    cls.add_method('SetDefaultMulticastRoute', 
-                   'void', 
-                   [param('uint32_t', 'outputInterface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: uint32_t ns3::Ipv4::GetNMulticastRoutes() const [member function]
-    cls.add_method('GetNMulticastRoutes', 
-                   'uint32_t', 
+    ## ipv4.h: ns3::Ptr<ns3::Ipv4RoutingProtocol> ns3::Ipv4::GetRoutingProtocol() const [member function]
+    cls.add_method('GetRoutingProtocol', 
+                   'ns3::Ptr< ns3::Ipv4RoutingProtocol >', 
                    [], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: ns3::Ipv4MulticastRoute ns3::Ipv4::GetMulticastRoute(uint32_t i) const [member function]
-    cls.add_method('GetMulticastRoute', 
-                   'ns3::Ipv4MulticastRoute', 
-                   [param('uint32_t', 'i')], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::RemoveMulticastRoute(uint32_t i) [member function]
-    cls.add_method('RemoveMulticastRoute', 
-                   'void', 
-                   [param('uint32_t', 'i')], 
-                   is_pure_virtual=True, is_virtual=True)
     ## ipv4.h: uint32_t ns3::Ipv4::AddInterface(ns3::Ptr<ns3::NetDevice> device) [member function]
     cls.add_method('AddInterface', 
                    'uint32_t', 
@@ -2666,36 +2746,26 @@
                    'uint32_t', 
                    [], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: uint32_t ns3::Ipv4::FindInterfaceForAddr(ns3::Ipv4Address addr) const [member function]
-    cls.add_method('FindInterfaceForAddr', 
-                   'uint32_t', 
-                   [param('ns3::Ipv4Address', 'addr')], 
+    ## ipv4.h: int32_t ns3::Ipv4::GetInterfaceForAddress(ns3::Ipv4Address address) const [member function]
+    cls.add_method('GetInterfaceForAddress', 
+                   'int32_t', 
+                   [param('ns3::Ipv4Address', 'address')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: uint32_t ns3::Ipv4::FindInterfaceForAddr(ns3::Ipv4Address addr, ns3::Ipv4Mask mask) const [member function]
-    cls.add_method('FindInterfaceForAddr', 
-                   'uint32_t', 
-                   [param('ns3::Ipv4Address', 'addr'), param('ns3::Ipv4Mask', 'mask')], 
+    ## ipv4.h: int32_t ns3::Ipv4::GetInterfaceForPrefix(ns3::Ipv4Address address, ns3::Ipv4Mask mask) const [member function]
+    cls.add_method('GetInterfaceForPrefix', 
+                   'int32_t', 
+                   [param('ns3::Ipv4Address', 'address'), param('ns3::Ipv4Mask', 'mask')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: int32_t ns3::Ipv4::FindInterfaceForDevice(ns3::Ptr<ns3::NetDevice> nd) const [member function]
-    cls.add_method('FindInterfaceForDevice', 
-                   'int32_t', 
-                   [param('ns3::Ptr< ns3::NetDevice >', 'nd')], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: ns3::Ptr<ns3::NetDevice> ns3::Ipv4::GetNetDevice(uint32_t i) [member function]
+    ## ipv4.h: ns3::Ptr<ns3::NetDevice> ns3::Ipv4::GetNetDevice(uint32_t interface) [member function]
     cls.add_method('GetNetDevice', 
                    'ns3::Ptr< ns3::NetDevice >', 
-                   [param('uint32_t', 'i')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::JoinMulticastGroup(ns3::Ipv4Address origin, ns3::Ipv4Address group) [member function]
-    cls.add_method('JoinMulticastGroup', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::LeaveMulticastGroup(ns3::Ipv4Address origin, ns3::Ipv4Address group) [member function]
-    cls.add_method('LeaveMulticastGroup', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group')], 
-                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4.h: int32_t ns3::Ipv4::GetInterfaceForDevice(ns3::Ptr<const ns3::NetDevice> device) const [member function]
+    cls.add_method('GetInterfaceForDevice', 
+                   'int32_t', 
+                   [param('ns3::Ptr< ns3::NetDevice const >', 'device')], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
     ## ipv4.h: uint32_t ns3::Ipv4::AddAddress(uint32_t interface, ns3::Ipv4InterfaceAddress address) [member function]
     cls.add_method('AddAddress', 
                    'uint32_t', 
@@ -2711,51 +2781,46 @@
                    'ns3::Ipv4InterfaceAddress', 
                    [param('uint32_t', 'interface'), param('uint32_t', 'addressIndex')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::SetMetric(uint32_t i, uint16_t metric) [member function]
+    ## ipv4.h: void ns3::Ipv4::SetMetric(uint32_t interface, uint16_t metric) [member function]
     cls.add_method('SetMetric', 
                    'void', 
-                   [param('uint32_t', 'i'), param('uint16_t', 'metric')], 
+                   [param('uint32_t', 'interface'), param('uint16_t', 'metric')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: uint16_t ns3::Ipv4::GetMetric(uint32_t i) const [member function]
+    ## ipv4.h: uint16_t ns3::Ipv4::GetMetric(uint32_t interface) const [member function]
     cls.add_method('GetMetric', 
                    'uint16_t', 
-                   [param('uint32_t', 'i')], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: ns3::Ipv4Address ns3::Ipv4::GetSourceAddress(ns3::Ipv4Address destination) const [member function]
-    cls.add_method('GetSourceAddress', 
-                   'ns3::Ipv4Address', 
-                   [param('ns3::Ipv4Address', 'destination')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: bool ns3::Ipv4::GetInterfaceForDestination(ns3::Ipv4Address dest, uint32_t & interface) const [member function]
-    cls.add_method('GetInterfaceForDestination', 
-                   'bool', 
-                   [param('ns3::Ipv4Address', 'dest'), param('uint32_t &', 'interface')], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: uint16_t ns3::Ipv4::GetMtu(uint32_t i) const [member function]
+    ## ipv4.h: uint16_t ns3::Ipv4::GetMtu(uint32_t interface) const [member function]
     cls.add_method('GetMtu', 
                    'uint16_t', 
-                   [param('uint32_t', 'i')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: bool ns3::Ipv4::IsUp(uint32_t i) const [member function]
+    ## ipv4.h: bool ns3::Ipv4::IsUp(uint32_t interface) const [member function]
     cls.add_method('IsUp', 
                    'bool', 
-                   [param('uint32_t', 'i')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_const=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::SetUp(uint32_t i) [member function]
+    ## ipv4.h: void ns3::Ipv4::SetUp(uint32_t interface) [member function]
     cls.add_method('SetUp', 
                    'void', 
-                   [param('uint32_t', 'i')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: void ns3::Ipv4::SetDown(uint32_t i) [member function]
+    ## ipv4.h: void ns3::Ipv4::SetDown(uint32_t interface) [member function]
     cls.add_method('SetDown', 
                    'void', 
-                   [param('uint32_t', 'i')], 
+                   [param('uint32_t', 'interface')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: uint32_t ns3::Ipv4::GetInterfaceByAddress(ns3::Ipv4Address addr, ns3::Ipv4Mask mask=ns3::Ipv4Mask(((const char*)"255.255.255.255"))) [member function]
-    cls.add_method('GetInterfaceByAddress', 
-                   'uint32_t', 
-                   [param('ns3::Ipv4Address', 'addr'), param('ns3::Ipv4Mask', 'mask', default_value='ns3::Ipv4Mask(((const char*)"255.255.255.255"))')], 
-                   is_virtual=True)
+    ## ipv4.h: void ns3::Ipv4::SetIpForward(bool forward) [member function]
+    cls.add_method('SetIpForward', 
+                   'void', 
+                   [param('bool', 'forward')], 
+                   is_pure_virtual=True, visibility='private', is_virtual=True)
+    ## ipv4.h: bool ns3::Ipv4::GetIpForward() const [member function]
+    cls.add_method('GetIpForward', 
+                   'bool', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, visibility='private', is_virtual=True)
     return
 
 def register_Ns3Ipv4RawSocketFactory_methods(root_module, cls):
@@ -2771,22 +2836,122 @@
     return
 
 def register_Ns3Ipv4RoutingProtocol_methods(root_module, cls):
-    ## ipv4.h: ns3::Ipv4RoutingProtocol::INTERFACE_ANY [variable]
-    cls.add_static_attribute('INTERFACE_ANY', 'uint32_t const', is_const=True)
-    ## ipv4.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol(ns3::Ipv4RoutingProtocol const & arg0) [copy constructor]
+    ## ipv4-routing-protocol.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol(ns3::Ipv4RoutingProtocol const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::Ipv4RoutingProtocol const &', 'arg0')])
-    ## ipv4.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol() [constructor]
+    ## ipv4-routing-protocol.h: ns3::Ipv4RoutingProtocol::Ipv4RoutingProtocol() [constructor]
+    cls.add_constructor([])
+    ## ipv4-routing-protocol.h: static ns3::TypeId ns3::Ipv4RoutingProtocol::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## ipv4-routing-protocol.h: ns3::Ptr<ns3::Ipv4Route> ns3::Ipv4RoutingProtocol::RouteOutput(ns3::Ipv4Header const & header, uint32_t oif, ns3::Socket::SocketErrno & sockerr) [member function]
+    cls.add_method('RouteOutput', 
+                   'ns3::Ptr< ns3::Ipv4Route >', 
+                   [param('ns3::Ipv4Header const &', 'header'), param('uint32_t', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-routing-protocol.h: bool ns3::Ipv4RoutingProtocol::RouteInput(ns3::Ptr<ns3::Packet const> p, ns3::Ipv4Header const & header, ns3::Ptr<const ns3::NetDevice> idev, ns3::Callback<void,ns3::Ptr<ns3::Ipv4Route>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback<void,ns3::Ptr<ns3::Ipv4MulticastRoute>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function]
+    cls.add_method('RouteInput', 
+                   'bool', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv4Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], 
+                   is_pure_virtual=True, is_virtual=True)
+    return
+
+def register_Ns3Ipv4StaticRouting_methods(root_module, cls):
+    ## ipv4-static-routing.h: ns3::Ipv4StaticRouting::Ipv4StaticRouting(ns3::Ipv4StaticRouting const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4StaticRouting const &', 'arg0')])
+    ## ipv4-static-routing.h: ns3::Ipv4StaticRouting::Ipv4StaticRouting() [constructor]
     cls.add_constructor([])
-    ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestRoute(uint32_t interface, ns3::Ipv4Header const & ipHeader, ns3::Ptr<ns3::Packet> packet, ns3::Callback<void,bool,const ns3::Ipv4Route&,ns3::Ptr<ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function]
-    cls.add_method('RequestRoute', 
-                   'bool', 
-                   [param('uint32_t', 'interface'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], 
+    ## ipv4-static-routing.h: static ns3::TypeId ns3::Ipv4StaticRouting::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::AddHostRouteTo(ns3::Ipv4Address dest, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('AddHostRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'dest'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::AddHostRouteTo(ns3::Ipv4Address dest, uint32_t interface) [member function]
+    cls.add_method('AddHostRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'dest'), param('uint32_t', 'interface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('AddNetworkRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::AddNetworkRouteTo(ns3::Ipv4Address network, ns3::Ipv4Mask networkMask, uint32_t interface) [member function]
+    cls.add_method('AddNetworkRouteTo', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'network'), param('ns3::Ipv4Mask', 'networkMask'), param('uint32_t', 'interface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::SetDefaultRoute(ns3::Ipv4Address nextHop, uint32_t interface) [member function]
+    cls.add_method('SetDefaultRoute', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'nextHop'), param('uint32_t', 'interface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: uint32_t ns3::Ipv4StaticRouting::GetNRoutes() [member function]
+    cls.add_method('GetNRoutes', 
+                   'uint32_t', 
+                   [], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: ns3::Ipv4RoutingTableEntry ns3::Ipv4StaticRouting::GetDefaultRoute() [member function]
+    cls.add_method('GetDefaultRoute', 
+                   'ns3::Ipv4RoutingTableEntry', 
+                   [], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: ns3::Ipv4RoutingTableEntry ns3::Ipv4StaticRouting::GetRoute(uint32_t i) [member function]
+    cls.add_method('GetRoute', 
+                   'ns3::Ipv4RoutingTableEntry', 
+                   [param('uint32_t', 'i')], 
                    is_pure_virtual=True, is_virtual=True)
-    ## ipv4.h: bool ns3::Ipv4RoutingProtocol::RequestInterface(ns3::Ipv4Address destination, uint32_t & interface) [member function]
-    cls.add_method('RequestInterface', 
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::RemoveRoute(uint32_t i) [member function]
+    cls.add_method('RemoveRoute', 
+                   'void', 
+                   [param('uint32_t', 'i')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::AddMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface, std::vector<unsigned int, std::allocator<unsigned int> > outputInterfaces) [member function]
+    cls.add_method('AddMulticastRoute', 
+                   'void', 
+                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface'), param('std::vector< unsigned int >', 'outputInterfaces')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface) [member function]
+    cls.add_method('SetDefaultMulticastRoute', 
+                   'void', 
+                   [param('uint32_t', 'outputInterface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: uint32_t ns3::Ipv4StaticRouting::GetNMulticastRoutes() const [member function]
+    cls.add_method('GetNMulticastRoutes', 
+                   'uint32_t', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    ## ipv4-static-routing.h: ns3::Ipv4MulticastRoutingTableEntry ns3::Ipv4StaticRouting::GetMulticastRoute(uint32_t i) const [member function]
+    cls.add_method('GetMulticastRoute', 
+                   'ns3::Ipv4MulticastRoutingTableEntry', 
+                   [param('uint32_t', 'i')], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    ## ipv4-static-routing.h: bool ns3::Ipv4StaticRouting::RemoveMulticastRoute(ns3::Ipv4Address origin, ns3::Ipv4Address group, uint32_t inputInterface) [member function]
+    cls.add_method('RemoveMulticastRoute', 
                    'bool', 
-                   [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'interface')], 
+                   [param('ns3::Ipv4Address', 'origin'), param('ns3::Ipv4Address', 'group'), param('uint32_t', 'inputInterface')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index) [member function]
+    cls.add_method('RemoveMulticastRoute', 
+                   'void', 
+                   [param('uint32_t', 'index')], 
                    is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: void ns3::Ipv4StaticRouting::SetNode(ns3::Ptr<ns3::Node> node) [member function]
+    cls.add_method('SetNode', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Node >', 'node')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-static-routing.h: ns3::Ptr<ns3::Node> ns3::Ipv4StaticRouting::GetNode() const [member function]
+    cls.add_method('GetNode', 
+                   'ns3::Ptr< ns3::Node >', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
     return
 
 def register_Ns3NetDevice_methods(root_module, cls):
@@ -3177,6 +3342,33 @@
                    visibility='protected', is_virtual=True)
     return
 
+def register_Ns3Ipv4ListRouting_methods(root_module, cls):
+    ## ipv4-list-routing.h: ns3::Ipv4ListRouting::Ipv4ListRouting(ns3::Ipv4ListRouting const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Ipv4ListRouting const &', 'arg0')])
+    ## ipv4-list-routing.h: ns3::Ipv4ListRouting::Ipv4ListRouting() [constructor]
+    cls.add_constructor([])
+    ## ipv4-list-routing.h: static ns3::TypeId ns3::Ipv4ListRouting::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## ipv4-list-routing.h: void ns3::Ipv4ListRouting::AddRoutingProtocol(ns3::Ptr<ns3::Ipv4RoutingProtocol> routingProtocol, int16_t priority) [member function]
+    cls.add_method('AddRoutingProtocol', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Ipv4RoutingProtocol >', 'routingProtocol'), param('int16_t', 'priority')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## ipv4-list-routing.h: uint32_t ns3::Ipv4ListRouting::GetNRoutingProtocols() const [member function]
+    cls.add_method('GetNRoutingProtocols', 
+                   'uint32_t', 
+                   [], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    ## ipv4-list-routing.h: ns3::Ptr<ns3::Ipv4RoutingProtocol> ns3::Ipv4ListRouting::GetRoutingProtocol(uint32_t index, int16_t & priority) const [member function]
+    cls.add_method('GetRoutingProtocol', 
+                   'ns3::Ptr< ns3::Ipv4RoutingProtocol >', 
+                   [param('uint32_t', 'index'), param('int16_t &', 'priority')], 
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    return
+
 def register_functions(root_module):
     module = root_module
     ## address.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::MakeAddressChecker() [free function]
@@ -3237,6 +3429,7 @@
                         [param('ns3::Buffer::Iterator &', 'i'), param('ns3::Mac48Address', 'ad')])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -3247,6 +3440,13 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    ## address-utils.h: extern bool ns3::addressUtils::IsMulticast(ns3::Address const & ad) [free function]
+    module.add_function('IsMulticast', 
+                        'bool', 
+                        [param('ns3::Address const &', 'ad')])
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_olsr.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_olsr.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -24,6 +24,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -44,6 +50,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -91,6 +101,15 @@
     module.add_class('TwoHopNeighborTuple')
     module.add_container('std::vector< ns3::olsr::MessageHeader::Hello::LinkMessage >', 'ns3::olsr::MessageHeader::Hello::LinkMessage', container_type='vector')
     module.add_container('std::vector< ns3::olsr::MessageHeader::Hna::Association >', 'ns3::olsr::MessageHeader::Hna::Association', container_type='vector')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::DuplicateTuple, std::allocator< ns3::olsr::DuplicateTuple > >', 'ns3::olsr::DuplicateSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::TopologyTuple, std::allocator< ns3::olsr::TopologyTuple > >', 'ns3::olsr::TopologySet')
+    typehandlers.add_type_alias('std::set< ns3::Ipv4Address, std::less< ns3::Ipv4Address >, std::allocator< ns3::Ipv4Address > >', 'ns3::olsr::MprSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::MprSelectorTuple, std::allocator< ns3::olsr::MprSelectorTuple > >', 'ns3::olsr::MprSelectorSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::MessageHeader, std::allocator< ns3::olsr::MessageHeader > >', 'ns3::olsr::MessageList')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::IfaceAssocTuple, std::allocator< ns3::olsr::IfaceAssocTuple > >', 'ns3::olsr::IfaceAssocSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::NeighborTuple, std::allocator< ns3::olsr::NeighborTuple > >', 'ns3::olsr::NeighborSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::TwoHopNeighborTuple, std::allocator< ns3::olsr::TwoHopNeighborTuple > >', 'ns3::olsr::TwoHopNeighborSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::LinkTuple, std::allocator< ns3::olsr::LinkTuple > >', 'ns3::olsr::LinkSet')
 
 def register_methods(root_module):
     register_Ns3OlsrState_methods(root_module, root_module['ns3::OlsrState'])
@@ -740,15 +759,15 @@
     cls.add_method('SetMainInterface', 
                    'void', 
                    [param('uint32_t', 'interface')])
-    ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RequestRoute(uint32_t ifIndex, ns3::Ipv4Header const & ipHeader, ns3::Ptr<ns3::Packet> packet, ns3::Callback<void,bool,const ns3::Ipv4Route&,ns3::Ptr<ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> routeReply) [member function]
-    cls.add_method('RequestRoute', 
-                   'bool', 
-                   [param('uint32_t', 'ifIndex'), param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet >', 'packet'), param('ns3::Callback< void, bool, ns3::Ipv4Route const &, ns3::Ptr< ns3::Packet >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'routeReply')], 
+    ## olsr-routing-protocol.h: ns3::Ptr<ns3::Ipv4Route> ns3::olsr::RoutingProtocol::RouteOutput(ns3::Ipv4Header const & header, uint32_t oif, ns3::Socket::SocketErrno & sockerr) [member function]
+    cls.add_method('RouteOutput', 
+                   'ns3::Ptr< ns3::Ipv4Route >', 
+                   [param('ns3::Ipv4Header const &', 'header'), param('uint32_t', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], 
                    visibility='private', is_virtual=True)
-    ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RequestInterface(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function]
-    cls.add_method('RequestInterface', 
+    ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RouteInput(ns3::Ptr<ns3::Packet const> p, ns3::Ipv4Header const & header, ns3::Ptr<const ns3::NetDevice> idev, ns3::Callback<void,ns3::Ptr<ns3::Ipv4Route>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback<void,ns3::Ptr<ns3::Ipv4MulticastRoute>,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback<void,ns3::Ptr<const ns3::Packet>,const ns3::Ipv4Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function]
+    cls.add_method('RouteInput', 
                    'bool', 
-                   [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'ifIndex')], 
+                   [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv4Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::Ipv4MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv4Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], 
                    visibility='private', is_virtual=True)
     ## olsr-routing-protocol.h: void ns3::olsr::RoutingProtocol::DoDispose() [member function]
     cls.add_method('DoDispose', 
@@ -808,6 +827,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -818,6 +838,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_onoff.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_onoff.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -18,6 +18,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -38,6 +44,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -85,6 +95,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -95,6 +106,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_packet_sink.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_packet_sink.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -18,6 +18,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -38,6 +44,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -81,6 +91,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -91,6 +102,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_point_to_point.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_point_to_point.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -22,6 +22,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -42,6 +48,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -301,6 +311,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -311,6 +322,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_simulator.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_simulator.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -61,6 +61,10 @@
     module.add_class('RealtimeSimulatorImpl', parent=root_module['ns3::SimulatorImpl'])
     ## realtime-simulator-impl.h: ns3::RealtimeSimulatorImpl::SynchronizationMode [enumeration]
     module.add_enum('SynchronizationMode', ['SYNC_BEST_EFFORT', 'SYNC_HARD_LIMIT'], outer_class=root_module['ns3::RealtimeSimulatorImpl'])
+    typehandlers.add_type_alias('ns3::TimeUnit< 2 >', 'ns3::TimeSquare')
+    typehandlers.add_type_alias('ns3::TimeUnit< - 1 >', 'ns3::TimeInvert')
+    typehandlers.add_type_alias('ns3::TimeUnit< 0 >', 'ns3::Scalar')
+    typehandlers.add_type_alias('ns3::TimeUnit< 1 >', 'ns3::Time')
     
     ## Register a nested module for the namespace Config
     
@@ -74,6 +78,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -96,6 +106,10 @@
     ## nstime.h: ns3::TimeStepPrecision::precision_t [enumeration]
     module.add_enum('precision_t', ['S', 'MS', 'US', 'NS', 'PS', 'FS'])
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -1530,6 +1544,7 @@
                         [param('uint64_t', 'ts')])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -1548,6 +1563,9 @@
                         [param('ns3::TimeStepPrecision::precision_t', 'precision')])
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_stats.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_stats.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -25,6 +25,8 @@
     module.add_class('CounterCalculator', template_parameters=['unsigned int'], parent=root_module['ns3::DataCalculator'])
     ## packet-data-calculators.h: ns3::PacketCounterCalculator [class]
     module.add_class('PacketCounterCalculator', parent=root_module['ns3::CounterCalculator< unsigned int >'])
+    typehandlers.add_type_alias('std::list< ns3::Ptr< ns3::DataCalculator >, std::allocator< ns3::Ptr< ns3::DataCalculator > > >', 'ns3::DataCalculatorList')
+    typehandlers.add_type_alias('std::list< std::pair< std::string, std::string >, std::allocator< std::pair< std::string, std::string > > >', 'ns3::MetadataList')
     
     ## Register a nested module for the namespace Config
     
@@ -38,6 +40,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -58,6 +66,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -419,6 +431,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -429,6 +442,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_tap_bridge.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_tap_bridge.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -20,6 +20,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -40,6 +46,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -217,6 +227,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -227,6 +238,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_udp_echo.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_udp_echo.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -20,6 +20,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -40,6 +46,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -115,6 +125,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -125,6 +136,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_v4ping.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_v4ping.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -18,6 +18,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -38,6 +44,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -81,6 +91,7 @@
     module = root_module
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -91,6 +102,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3_module_wifi.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3_module_wifi.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 def register_types(module):
     root_module = module.get_root()
@@ -135,6 +135,7 @@
     module.add_class('YansWifiChannel', parent=root_module['ns3::WifiChannel'])
     ## aarf-wifi-manager.h: ns3::AarfWifiManager [class]
     module.add_class('AarfWifiManager', parent=root_module['ns3::ArfWifiManager'])
+    typehandlers.add_type_alias('std::vector< ns3::ThresholdsItem, std::allocator< ns3::ThresholdsItem > >', 'ns3::Thresholds')
     
     ## Register a nested module for the namespace Config
     
@@ -148,6 +149,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -168,6 +175,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -4181,6 +4192,7 @@
                         [param('uint8_t', 'tid')])
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -4191,6 +4203,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/ns3modulegen_generated.py	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/ns3modulegen_generated.py	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,4 @@
-from pybindgen import Module, FileCodeSink, param, retval, cppclass
+from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers
 
 
 import pybindgen.settings
@@ -288,6 +288,12 @@
     register_types_ns3_TimeStepPrecision(nested_module)
     
     
+    ## Register a nested module for the namespace addressUtils
+    
+    nested_module = module.add_cpp_namespace('addressUtils')
+    register_types_ns3_addressUtils(nested_module)
+    
+    
     ## Register a nested module for the namespace internal
     
     nested_module = module.add_cpp_namespace('internal')
@@ -309,6 +315,10 @@
     root_module = module.get_root()
     
 
+def register_types_ns3_addressUtils(module):
+    root_module = module.get_root()
+    
+
 def register_types_ns3_internal(module):
     root_module = module.get_root()
     
@@ -786,6 +796,7 @@
     root_module.end_section('ns3_module_helper')
     register_functions_ns3_Config(module.get_submodule('Config'), root_module)
     register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module)
+    register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module)
     register_functions_ns3_internal(module.get_submodule('internal'), root_module)
     register_functions_ns3_olsr(module.get_submodule('olsr'), root_module)
     return
@@ -796,6 +807,9 @@
 def register_functions_ns3_TimeStepPrecision(module, root_module):
     return
 
+def register_functions_ns3_addressUtils(module, root_module):
+    return
+
 def register_functions_ns3_internal(module, root_module):
     return
 
--- a/bindings/python/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/bindings/python/wscript	Sat May 30 17:37:38 2009 +0100
@@ -15,7 +15,7 @@
 import Utils
 
 ## https://launchpad.net/pybindgen/
-REQUIRED_PYBINDGEN_VERSION = (0, 10, 0, 630)
+REQUIRED_PYBINDGEN_VERSION = (0, 10, 0, 640)
 REQUIRED_PYGCCXML_VERSION = (0, 9, 5)
 
 
--- a/doc/manual/attributes.texi	Sat May 30 17:36:50 2009 +0100
+++ b/doc/manual/attributes.texi	Sat May 30 17:37:38 2009 +0100
@@ -207,6 +207,8 @@
 In the ns-3 attribute system, these value definitions and accessor
 functions are moved into the TypeId class; e.g.:  
 @verbatim
+NS_OBJECT_ENSURE_REGISTERED (DropTailQueue);
+
 TypeId DropTailQueue::GetTypeId (void) 
 {
   static TypeId tid = TypeId ("ns3::DropTailQueue")
@@ -239,6 +241,11 @@
 section, we will provide an example script that shows how users
 may manipulate these values.
 
+Note that initialization of the attribute relies on the macro
+NS_OBJECT_ENSURE_REGISTERED (DropTailQueue) being called; if you leave
+this out of your new class implementation, your attributes will not be 
+initialized corretly.
+
 @subsection Basic usage
 
 Let's look at how a user script might access these values.  
--- a/examples/csma-multicast.cc	Sat May 30 17:36:50 2009 +0100
+++ b/examples/csma-multicast.cc	Sat May 30 17:37:38 2009 +0100
@@ -105,7 +105,7 @@
   // 2) Set up a default multicast route on the sender n0 
   // 3) Have node n4 join the multicast group
   // We have a helper that can help us with static multicast
-  StaticMulticastRouteHelper multicast;
+  Ipv4StaticRoutingHelper multicast;
 
   // 1) Configure a (static) multicast route on node n2 (multicastRouter)
   Ptr<Node> multicastRouter = c.Get (2);  // The node in question
@@ -121,10 +121,6 @@
   Ptr<NetDevice> senderIf = nd0.Get(0);
   multicast.SetDefaultMulticastRoute (sender, senderIf);
 
-  // 3) Have node n4 join the multicast group
-  Ptr<Node> receiver = c.Get (4);
-  multicast.JoinMulticastGroup (receiver, multicastSource, multicastGroup);
-  
   //
   // Create an OnOff application to send UDP datagrams from node zero to the
   // multicast group (node four will be listening).
--- a/examples/emu-ping.cc	Sat May 30 17:36:50 2009 +0100
+++ b/examples/emu-ping.cc	Sat May 30 17:37:38 2009 +0100
@@ -55,7 +55,6 @@
 #include "ns3/core-module.h"
 #include "ns3/simulator-module.h"
 #include "ns3/node-module.h"
-#include "ns3/internet-stack-module.h"
 #include "ns3/emu-module.h"
 #include "ns3/v4ping-module.h"
 #include "ns3/helper-module.h"
@@ -149,7 +148,8 @@
   // of ARP, IPv4, ICMP, UDP and TCP.
   //
   NS_LOG_INFO ("Add Internet Stack");
-  AddInternetStack (node);
+  InternetStackHelper internetStackHelper;
+  internetStackHelper.Install (node);
 
   NS_LOG_INFO ("Create IPv4 Interface");
   Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
@@ -175,7 +175,9 @@
   Ipv4Address gateway ("1.2.3.4");
   NS_ABORT_MSG_IF (gateway == "1.2.3.4", "You must change the gateway IP address before running this example");
 
-  ipv4->SetDefaultRoute (gateway, interface);
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  Ptr<Ipv4StaticRouting> staticRouting = ipv4RoutingHelper.GetStaticRouting (ipv4);
+  staticRouting->SetDefaultRoute (gateway, interface);
 
   //
   // Create the ping application.  This application knows how to send
--- a/examples/static-routing-slash32.cc	Sat May 30 17:36:50 2009 +0100
+++ b/examples/static-routing-slash32.cc	Sat May 30 17:37:38 2009 +0100
@@ -97,12 +97,14 @@
   ipv4C->SetMetric (ifIndexC, 1);
   ipv4C->SetUp (ifIndexC);
  
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
   // Create static routes from A to C
+  Ptr<Ipv4StaticRouting> staticRoutingA = ipv4RoutingHelper.GetStaticRouting (ipv4A);
   // The ifIndex for this outbound route is 1; the first p2p link added
-  ipv4A->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.2"), 1);
+  staticRoutingA->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.2"), 1);
+  Ptr<Ipv4StaticRouting> staticRoutingB = ipv4RoutingHelper.GetStaticRouting (ipv4B);
   // The ifIndex we want on node B is 2; 0 corresponds to loopback, and 1 to the first point to point link
-  ipv4B->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"), 2);
-
+  staticRoutingB->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"), 2);
   // Create the OnOff application to send UDP datagrams of size
   // 210 bytes at a rate of 448 Kb/s
   uint16_t port = 9;   // Discard port (RFC 863)
--- a/examples/tcp-nsc-lfn.cc	Sat May 30 17:36:50 2009 +0100
+++ b/examples/tcp-nsc-lfn.cc	Sat May 30 17:37:38 2009 +0100
@@ -91,7 +91,7 @@
   InternetStackHelper internet;
   // The next statement switches the nodes to 'NSC'-Mode.
   // It disables the native ns-3 TCP model and loads the NSC library.
-  internet.SetNscStack (nscStack);
+  internet.SetTcp ("ns3::NscTcpL4Protocol","Library",StringValue(nscStack));
   internet.Install (n);
 
   if (tcpCong != "cubic") // make sure we only fail if both --nscstack and --TCP_CONGESTION are used
--- a/examples/tcp-nsc-zoo.cc	Sat May 30 17:36:50 2009 +0100
+++ b/examples/tcp-nsc-zoo.cc	Sat May 30 17:37:38 2009 +0100
@@ -69,7 +69,7 @@
 
   InternetStackHelper internetStack;
 
-  internetStack.SetNscStack ("liblinux2.6.26.so");
+  internetStack.SetTcp ("ns3::NscTcpL4Protocol","Library",StringValue("liblinux2.6.26.so"));
   // this switches nodes 0 and 1 to NSCs Linux 2.6.26 stack.
   internetStack.Install (n.Get(0));
   internetStack.Install (n.Get(1));
@@ -87,7 +87,7 @@
     {
       // the next statement doesn't change anything for the nodes 0, 1, and 2; since they
       // already have a stack assigned.
-      internetStack.SetNscStack ("liblinux2.6.18.so");
+      internetStack.SetTcp ("ns3::NscTcpL4Protocol","Library",StringValue("liblinux2.6.18.so"));
       // this switches node 3 to NSCs Linux 2.6.18 stack.
       internetStack.Install (n.Get(3));
       // and then agains disables sack/timestamps/wscale on node 3.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/wifi-clear-channel-cmu.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,229 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 The Boeing Company
+ *
+ * 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: Guangyu Pei <guangyu.pei@boeing.com>
+ */
+
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/contrib-module.h"
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+
+NS_LOG_COMPONENT_DEFINE ("Main");
+
+using namespace ns3;
+
+class Experiment
+{
+public:
+  Experiment ();
+  Experiment (std::string name);
+  uint32_t Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel);
+private:
+  void ReceivePacket (Ptr<Socket> socket);
+  void SetPosition (Ptr<Node> node, Vector position);
+  Vector GetPosition (Ptr<Node> node);
+  Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
+  void GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, 
+                             uint32_t pktCount, Time pktInterval );
+
+  uint32_t m_pktsTotal;
+  Gnuplot2dDataset m_output;
+};
+
+Experiment::Experiment ()
+{}
+
+Experiment::Experiment (std::string name)
+  : m_output (name)
+{
+  m_output.SetStyle (Gnuplot2dDataset::LINES);
+}
+
+void
+Experiment::SetPosition (Ptr<Node> node, Vector position)
+{
+  Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+  mobility->SetPosition (position);
+}
+
+Vector
+Experiment::GetPosition (Ptr<Node> node)
+{
+  Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
+  return mobility->GetPosition ();
+}
+
+void
+Experiment::ReceivePacket (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  while (packet = socket->Recv ())
+    {
+      m_pktsTotal ++;
+    }
+}
+
+Ptr<Socket>
+Experiment::SetupPacketReceive (Ptr<Node> node)
+{
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> sink = Socket::CreateSocket (node, tid);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+  sink->Bind (local);
+  sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
+  return sink;
+}
+
+void
+Experiment::GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, 
+                             uint32_t pktCount, Time pktInterval )
+{
+  if (pktCount > 0)
+    {
+      socket->Send (Create<Packet> (pktSize));
+      Simulator::Schedule (pktInterval, &Experiment::GenerateTraffic, this, 
+                           socket, pktSize,pktCount-1, pktInterval);
+    }
+  else
+    {
+      socket->Close ();
+    }
+}
+
+uint32_t
+Experiment::Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
+                 const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel)
+{
+  m_pktsTotal = 0;
+
+  NodeContainer c;
+  c.Create (2);
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  YansWifiPhyHelper phy = wifiPhy;
+  phy.SetChannel (wifiChannel.Create ());
+
+  NqosWifiMacHelper mac = wifiMac;
+  NetDeviceContainer devices = wifi.Install (phy, mac, c);
+
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (c);
+
+  Ipv4AddressHelper ipv4;
+  NS_LOG_INFO ("Assign IP Addresses.");
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer i = ipv4.Assign (devices);
+
+  Ptr<Socket> recvSink = SetupPacketReceive (c.Get (0));
+
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> source = Socket::CreateSocket (c.Get (1), tid);
+  InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), 80);
+  source->Connect (remote);
+  uint32_t packetSize = 1014;
+  uint32_t maxPacketCount = 200;
+  Time interPacketInterval = Seconds (1.);
+  Simulator::Schedule (Seconds (1.0), &Experiment::GenerateTraffic, 
+                       this, source, packetSize, maxPacketCount,interPacketInterval);
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+
+  return m_pktsTotal;
+}
+
+int main (int argc, char *argv[])
+{
+  std::ofstream outfile ("clear-channel.plt");
+  std::vector <std::string> modes;
+
+  modes.push_back ("wifib-1mbs");
+  modes.push_back ("wifib-2mbs");
+  modes.push_back ("wifib-5.5mbs");
+  modes.push_back ("wifib-11mbs");
+  // disable fragmentation
+  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
+  Gnuplot gnuplot = Gnuplot ("clear-channel.eps");
+  
+  for (uint32_t i = 0; i < modes.size(); i++)
+  {
+   std::cout << modes[i] << std::endl;
+   Gnuplot2dDataset dataset (modes[i]);
+
+   for (double rss = -102.0; rss <= -80.0; rss += 0.5)
+   {
+     Experiment experiment;
+     dataset.SetStyle (Gnuplot2dDataset::LINES);
+ 
+     WifiHelper wifi;
+     NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+     Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", 
+                         StringValue (modes[i]));
+     wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
+                                   "DataMode",StringValue(modes[i]),
+                                   "ControlMode",StringValue(modes[i]));
+     wifiMac.SetType ("ns3::AdhocWifiMac");
+ 
+     YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+     YansWifiChannelHelper wifiChannel ;
+     wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+     wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",DoubleValue(rss));
+ 
+ 
+     NS_LOG_DEBUG (modes[i]);
+     experiment = Experiment (modes[i]);
+     wifiPhy.Set ("Standard", StringValue ("802.11b") );
+     wifiPhy.Set ("EnergyDetectionThreshold", DoubleValue (-110.0) );
+     wifiPhy.Set ("CcaMode1Threshold", DoubleValue (-110.0) );
+     wifiPhy.Set ("TxPowerStart", DoubleValue (15.0) );
+     wifiPhy.Set ("RxGain", DoubleValue (0) ); 
+     wifiPhy.Set ("RxNoiseFigure", DoubleValue (7) ); 
+     uint32_t pktsRecvd = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel);
+     dataset.Add (rss, pktsRecvd);
+   }
+
+   gnuplot.AddDataset (dataset);
+  }
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("RSS(dBm)", "Number of packets received");
+  gnuplot.SetExtra  ("set xrange [-102:-83]");
+  gnuplot.GenerateOutput (outfile);
+  outfile.close ();
+
+  return 0;
+}
--- a/examples/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/examples/wscript	Sat May 30 17:37:38 2009 +0100
@@ -120,6 +120,10 @@
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'wifi-adhoc.cc'
 
+    obj = bld.create_ns3_program('wifi-clear-channel-cmu',
+                                 ['core', 'simulator', 'mobility', 'wifi'])
+    obj.source = 'wifi-clear-channel-cmu.cc'
+
     obj = bld.create_ns3_program('wifi-ap',
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'wifi-ap.cc'
--- a/samples/main-propagation-loss.cc	Sat May 30 17:36:50 2009 +0100
+++ b/samples/main-propagation-loss.cc	Sat May 30 17:37:38 2009 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2007 INRIA
+ * 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
@@ -15,45 +15,298 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Author: Timo Bingmann <timo.bingmann@student.kit.edu>
  */
+
 #include "ns3/propagation-loss-model.h"
+#include "ns3/jakes-propagation-loss-model.h"
 #include "ns3/constant-position-mobility-model.h"
+
 #include "ns3/config.h"
 #include "ns3/string.h"
+#include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/gnuplot.h"
+#include "ns3/simulator.h"
+
+#include <map>
 
 using namespace ns3;
 
-static void
-PrintOne (double minTxpower, double maxTxpower, double stepTxpower, double min, double max, double step)
+/// 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
+static double dround(double number, double precision)
+{
+  number /= precision;
+  if (number >= 0)
+    {
+      number = floor(number + 0.5);
+    }
+  else
+    {
+      number = ceil(number - 0.5);
+    }
+  number *= precision;
+  return number;
+}
+
+static Gnuplot
+TestDeterministic (Ptr<PropagationLossModel> model)
+{
+  Ptr<ConstantPositionMobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
+  Ptr<ConstantPositionMobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
+
+  Gnuplot plot;
+
+  plot.AppendExtra("set xlabel 'Distance'");
+  plot.AppendExtra("set ylabel 'rxPower (dBm)'");
+  plot.AppendExtra("set key top right");
+
+  double txPowerDbm = +20; // dBm
+
+  Gnuplot2dDataset dataset;
+
+  dataset.SetStyle(Gnuplot2dDataset::LINES);
+
+  {
+    a->SetPosition (Vector (0.0, 0.0, 0.0));
+
+    for (double distance = 0.0; distance < 2500.0; distance += 10.0)
+      {
+        b->SetPosition (Vector (distance, 0.0, 0.0));
+
+        // CalcRxPower() returns dBm.
+        double rxPowerDbm = model->CalcRxPower (txPowerDbm, a, b);
+
+        dataset.Add(distance, rxPowerDbm);
+
+        Simulator::Stop (Seconds (1.0));
+        Simulator::Run ();
+      }
+  }
+
+  std::ostringstream os;
+  os << "txPower " << txPowerDbm << "dBm";
+  dataset.SetTitle(os.str());
+
+  plot.AddDataset(dataset);
+
+  plot.AddDataset( Gnuplot2dFunction("-94 dBm CSThreshold", "-94.0") );
+
+  return plot;
+}
+
+static Gnuplot
+TestProbabilistic (Ptr<PropagationLossModel> model, unsigned int samples = 100000)
 {
   Ptr<ConstantPositionMobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
   Ptr<ConstantPositionMobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
-  Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
+
+  Gnuplot plot;
+
+  plot.AppendExtra("set xlabel 'Distance'");
+  plot.AppendExtra("set ylabel 'rxPower (dBm)'");
+  plot.AppendExtra("set zlabel 'Probability' offset 0,+10");
+  plot.AppendExtra("set view 50, 120, 1.0, 1.0");
+  plot.AppendExtra("set key top right");
+
+  plot.AppendExtra("set ticslevel 0");
+  plot.AppendExtra("set xtics offset -0.5,0");
+  plot.AppendExtra("set ytics offset 0,-0.5");
+  plot.AppendExtra("set xrange [100:]");
+
+  double txPowerDbm = +20; // dBm
+
+  Gnuplot3dDataset dataset;
+
+  dataset.SetStyle("with linespoints");
+  dataset.SetExtra("pointtype 3 pointsize 0.5");
+  
+  typedef std::map<double, unsigned int> rxPowerMapType;
 
-  Ptr<PropagationLossModel> model = log;
+  // Take given number of samples from CalcRxPower() and show probability
+  // density for discrete distances.
+  {
+    a->SetPosition (Vector (0.0, 0.0, 0.0));
+
+    for (double distance = 100.0; distance < 2500.0; distance += 100.0)
+      {
+        b->SetPosition (Vector (distance, 0.0, 0.0));
+
+        rxPowerMapType rxPowerMap;
+
+        for (unsigned int samp = 0; samp < samples; ++samp)
+          {
+            // CalcRxPower() returns dBm.
+            double rxPowerDbm = model->CalcRxPower (txPowerDbm, a, b);
+            rxPowerDbm = dround(rxPowerDbm, 1.0);
+
+            rxPowerMap[ rxPowerDbm ] ++;
+
+            Simulator::Stop (Seconds (0.01));
+            Simulator::Run ();
+          }
+
+        for (rxPowerMapType::const_iterator i = rxPowerMap.begin();
+             i != rxPowerMap.end(); ++i)
+          {
+            dataset.Add(distance, i->first, (double)i->second / (double)samples);
+          }
+        dataset.AddEmptyLine();
+      }
+  }
 
-  a->SetPosition (Vector (0.0, 0.0, 0.0));
-  for (double x = min; x < max; x+= step)
-    {
-      b->SetPosition (Vector (x, 0.0, 0.0));
-      std::cout << x << " ";
-      for (double txpower = minTxpower; txpower < maxTxpower; txpower += stepTxpower)
-        {
-          double rxPowerDbm = model->CalcRxPower (txpower, a, b);
-          std::cout << rxPowerDbm << " ";
-        }
-      std::cout << std::endl;
-    }
+  std::ostringstream os;
+  os << "txPower " << txPowerDbm << "dBm";
+  dataset.SetTitle(os.str());
+
+  plot.AddDataset(dataset);
+
+  return plot;
+}
+
+static Gnuplot
+TestDeterministicByTime (Ptr<PropagationLossModel> model,
+                         Time timeStep = Seconds(0.001),
+                         Time timeTotal = Seconds(1.0),
+                         double distance = 100.0)
+{
+  Ptr<ConstantPositionMobilityModel> a = CreateObject<ConstantPositionMobilityModel> ();
+  Ptr<ConstantPositionMobilityModel> b = CreateObject<ConstantPositionMobilityModel> ();
+
+  Gnuplot plot;
+
+  plot.AppendExtra("set xlabel 'Time (s)'");
+  plot.AppendExtra("set ylabel 'rxPower (dBm)'");
+  plot.AppendExtra("set key center right");
+
+  double txPowerDbm = +20; // dBm
+
+  Gnuplot2dDataset dataset;
+
+  dataset.SetStyle(Gnuplot2dDataset::LINES);
+
+  {
+    a->SetPosition (Vector (0.0, 0.0, 0.0));
+    b->SetPosition (Vector (distance, 0.0, 0.0));
+
+    Time start = Simulator::Now();
+    while( Simulator::Now() < start + timeTotal )
+      {
+        // CalcRxPower() returns dBm.
+        double rxPowerDbm = model->CalcRxPower (txPowerDbm, a, b);
+
+        Time elapsed = Simulator::Now() - start;
+        dataset.Add(elapsed.GetSeconds(), rxPowerDbm);
+
+        Simulator::Stop (timeStep);
+        Simulator::Run ();
+      }
+  }
+
+  std::ostringstream os;
+  os << "txPower " << txPowerDbm << "dBm";
+  dataset.SetTitle(os.str());
+
+  plot.AddDataset(dataset);
+
+  plot.AddDataset( Gnuplot2dFunction("-94 dBm CSThreshold", "-94.0") );
+
+  return plot;
 }
 
 int main (int argc, char *argv[])
 {
+  GnuplotCollection gnuplots("main-propagation-loss.pdf");
 
-  Config::SetDefault ("ns3::LogDistancePropagationLossModel::ReferenceDistance", StringValue ("1.0"));
-  Config::SetDefault ("ns3::LogDistancePropagationLossModel::Exponent", StringValue ("4"));
+  {
+    Ptr<FriisPropagationLossModel> friis = CreateObject<FriisPropagationLossModel> ();
+
+    Gnuplot plot = TestDeterministic(friis);
+    plot.SetTitle("ns3::FriisPropagationLossModel (Default Parameters)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
+    log->SetAttribute("Exponent", DoubleValue (2.5));
+
+    Gnuplot plot = TestDeterministic(log);
+    plot.SetTitle("ns3::LogDistancePropagationLossModel (Exponent = 2.5)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<RandomPropagationLossModel> random = CreateObject<RandomPropagationLossModel> ();
+    random->SetAttribute("Variable", RandomVariableValue(ExponentialVariable(50.0)));
+
+    Gnuplot plot = TestDeterministic(random);
+    plot.SetTitle("ns3::RandomPropagationLossModel with Exponential Distribution");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
+
+    // doppler frequency shift for 5.15 GHz at 100 km/h
+    jakes->SetAttribute("DopplerFreq", DoubleValue(477.9));
+
+    Gnuplot plot = TestDeterministicByTime (jakes, Seconds(0.001), Seconds(1.0));
+    plot.SetTitle("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 1 millisec resolution)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<JakesPropagationLossModel> jakes = CreateObject<JakesPropagationLossModel> ();
+
+    // doppler frequency shift for 5.15 GHz at 100 km/h
+    jakes->SetAttribute("DopplerFreq", DoubleValue(477.9));
 
-  PrintOne (-10, 20, 5, 0, 10000, 2);
+    Gnuplot plot = TestDeterministicByTime (jakes, Seconds(0.0001), Seconds(0.1));
+    plot.SetTitle("ns3::JakesPropagationLossModel (with 477.9 Hz shift and 0.1 millisec resolution)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<ThreeLogDistancePropagationLossModel> log3 = CreateObject<ThreeLogDistancePropagationLossModel> ();
+
+    Gnuplot plot = TestDeterministic(log3);
+    plot.SetTitle("ns3::ThreeLogDistancePropagationLossModel (Defaults)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<ThreeLogDistancePropagationLossModel> log3 = CreateObject<ThreeLogDistancePropagationLossModel> ();
+    // more prominent example values:
+    log3->SetAttribute("Exponent0", DoubleValue(1.0));
+    log3->SetAttribute("Exponent1", DoubleValue(3.0));
+    log3->SetAttribute("Exponent2", DoubleValue(10.0));
+
+    Gnuplot plot = TestDeterministic(log3);
+    plot.SetTitle("ns3::ThreeLogDistancePropagationLossModel (Exponents 1.0, 3.0 and 10.0)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<NakagamiPropagationLossModel> nak = CreateObject<NakagamiPropagationLossModel> ();
+
+    Gnuplot plot = TestProbabilistic(nak);
+    plot.SetTitle("ns3::NakagamiPropagationLossModel (Default Parameters)");
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Ptr<ThreeLogDistancePropagationLossModel> log3 = CreateObject<ThreeLogDistancePropagationLossModel> ();
+
+    Ptr<NakagamiPropagationLossModel> nak = CreateObject<NakagamiPropagationLossModel> ();
+    log3->SetNext(nak);
+
+    Gnuplot plot = TestProbabilistic(log3);
+    plot.SetTitle("ns3::ThreeLogDistancePropagationLossModel and ns3::NakagamiPropagationLossModel (Default Parameters)");
+    gnuplots.AddPlot(plot);
+  }
+
+  gnuplots.GenerateOutput(std::cout);
 
   return 0;
 }
--- a/src/applications/packet-sink/packet-sink.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/applications/packet-sink/packet-sink.cc	Sat May 30 17:37:38 2009 +0100
@@ -18,10 +18,12 @@
  * Author:  Tom Henderson (tomhend@u.washington.edu)
  */
 #include "ns3/address.h"
+#include "ns3/address-utils.h"
 #include "ns3/log.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/node.h"
 #include "ns3/socket.h"
+#include "ns3/udp-socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
@@ -88,6 +90,19 @@
       m_socket = Socket::CreateSocket (GetNode(), m_tid);
       m_socket->Bind (m_local);
       m_socket->Listen ();
+      if (addressUtils::IsMulticast (m_local))
+        {
+          Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket);
+          if (udpSocket)
+            {
+              // equivalent to setsockopt (MCAST_JOIN_GROUP)
+              udpSocket->MulticastJoinGroup (0, m_local);
+            }
+          else
+            {
+              NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket");
+            }
+        }
     }
 
   m_socket->SetRecvCallback (MakeCallback(&PacketSink::HandleRead, this));
--- a/src/applications/udp-echo/udp-echo-server.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/applications/udp-echo/udp-echo-server.cc	Sat May 30 17:37:38 2009 +0100
@@ -18,9 +18,11 @@
 
 #include "ns3/log.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/address-utils.h"
 #include "ns3/nstime.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/socket.h"
+#include "ns3/udp-socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
@@ -76,6 +78,19 @@
       m_socket = Socket::CreateSocket (GetNode(), tid);
       InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port);
       m_socket->Bind (local);
+      if (addressUtils::IsMulticast (m_local))
+        {
+          Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socket);
+          if (udpSocket)
+            {
+              // equivalent to setsockopt (MCAST_JOIN_GROUP)
+              udpSocket->MulticastJoinGroup (0, m_local);
+            }
+          else
+            {
+              NS_FATAL_ERROR ("Error: joining multicast on a non-UDP socket");
+            }
+        }
     }
 
   m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this));
--- a/src/core/object.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/core/object.cc	Sat May 30 17:37:38 2009 +0100
@@ -160,6 +160,24 @@
   other->m_next = next;
   NS_ASSERT (CheckLoose ());
   NS_ASSERT (o->CheckLoose ());
+  // call NotifyNewAggregate in the listed chain
+  Object *currentObject = this;
+  do 
+    {
+      // the NotifyNewAggregate of the current object implementation
+      // should be called on the next object in the linked chain
+      currentObject->NotifyNewAggregate ();
+      currentObject = currentObject->m_next;
+    } while (currentObject != this);
+}
+/**
+ * This function must be implemented in the stack that needs to notify
+ * other stacks connected to the node of their presence in the node.
+ */
+void
+Object::NotifyNewAggregate ()
+{
+
 }
 
 Object::AggregateIterator 
--- a/src/core/object.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/core/object.h	Sat May 30 17:37:38 2009 +0100
@@ -160,6 +160,13 @@
   AggregateIterator GetAggregateIterator (void) const;
 
 protected:
+ /**
+  * This function is called by the AggregateObject on all the objects connected in the listed chain.
+  * This way the new object aggregated will be used if needed by the NotifyNewAggregate corresponding
+  * to each object connected in the listed chain. It should be implemented by objects needing an
+  * additional/special behavior when aggregated to another object.
+  */
+  virtual void NotifyNewAggregate ();
   /**
    * This method is called by Object::Dispose or by the object's 
    * destructor, whichever comes first.
--- a/src/devices/emu/emu-net-device.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/emu/emu-net-device.cc	Sat May 30 17:37:38 2009 +0100
@@ -173,7 +173,9 @@
   m_sock (-1),
   m_readThread (0),
   m_ifIndex (std::numeric_limits<uint32_t>::max ()),  // absurdly large value
-  m_sll_ifindex (-1)
+  m_sll_ifindex (-1),
+  m_isBroadcast (true),
+  m_isMulticast (false)
 {
   NS_LOG_FUNCTION (this);
   Start (m_tStart);
@@ -293,7 +295,19 @@
     {
       NS_FATAL_ERROR ("EmuNetDevice::StartDevice(): " << m_deviceName << " is not in promiscuous mode");
     }
-
+  if ((ifr.ifr_flags & IFF_BROADCAST) != IFF_BROADCAST)
+    {
+      // We default m_isBroadcast to true but turn it off here if not
+      // supported, because in the common case, overlying IP code will 
+      // assert during configuration time if this is false, before this
+      // method has a chance to set it during runtime
+      m_isBroadcast = false;
+    }
+  if ((ifr.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST)
+    {
+      // This one is OK to enable at runtime
+      m_isMulticast = true;
+    }
   //
   // Now spin up a read thread to read packets.
   //
@@ -918,7 +932,7 @@
 bool 
 EmuNetDevice::IsBroadcast (void) const
 {
-  return true;
+  return m_isBroadcast;
 }
 
 Address
@@ -930,7 +944,7 @@
 bool 
 EmuNetDevice::IsMulticast (void) const
 {
-  return false;
+  return m_isMulticast;
 }
 
   Address 
--- a/src/devices/emu/emu-net-device.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/emu/emu-net-device.h	Sat May 30 17:37:38 2009 +0100
@@ -453,6 +453,18 @@
   bool m_linkUp;
 
   /**
+   * Flag indicating whether or not the underlying net device supports 
+   * broadcast.
+   */
+  bool m_isBroadcast;
+
+  /**
+   * Flag indicating whether or not the underlying net device supports
+   * multicast.
+   */
+  bool m_isMulticast;
+
+  /**
    * Callback to fire if the link changes state (up or down).
    */
   Callback<void> m_linkChangeCallback;
--- a/src/devices/tap-bridge/tap-bridge.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/tap-bridge/tap-bridge.cc	Sat May 30 17:37:38 2009 +0100
@@ -342,7 +342,7 @@
       Ptr<NetDevice> nd = GetBridgedNetDevice ();
       Ptr<Node> n = nd->GetNode ();
       Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
-      uint32_t index = ipv4->FindInterfaceForDevice (nd);
+      uint32_t index = ipv4->GetInterfaceForDevice (nd);
       if (ipv4->GetNAddresses (index) > 1)
         {
           NS_LOG_WARN ("Underlying bridged NetDevice has multiple IP addresses; using first one.");
--- a/src/devices/wifi/adhoc-wifi-mac.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/adhoc-wifi-mac.cc	Sat May 30 17:37:38 2009 +0100
@@ -98,7 +98,6 @@
 AdhocWifiMac::SetEifsNoDifs (Time eifsNoDifs)
 {
   m_dcfManager->SetEifsNoDifs (eifsNoDifs);
-  m_eifsNoDifs = eifsNoDifs;
 }
 void 
 AdhocWifiMac::SetAckTimeout (Time ackTimeout)
@@ -128,7 +127,7 @@
 Time 
 AdhocWifiMac::GetEifsNoDifs (void) const
 {
-  return m_eifsNoDifs;
+  return m_dcfManager->GetEifsNoDifs ();
 }
 Time 
 AdhocWifiMac::GetAckTimeout (void) const
@@ -241,7 +240,7 @@
 }
 
 void 
-AdhocWifiMac::ForwardUp (Ptr<Packet> packet, WifiMacHeader const *hdr)
+AdhocWifiMac::ForwardUp (Ptr<Packet> packet, const WifiMacHeader *hdr)
 {
   NS_LOG_DEBUG ("received size="<<packet->GetSize ()<<", from="<<hdr->GetAddr2 ());
   m_upCallback (packet, hdr->GetAddr2 (), hdr->GetAddr1 ());
--- a/src/devices/wifi/adhoc-wifi-mac.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/adhoc-wifi-mac.h	Sat May 30 17:37:38 2009 +0100
@@ -83,7 +83,7 @@
   // inherited from Object base class.
   virtual void DoDispose (void);
   /* invoked by the MacLows. */
-  void ForwardUp (Ptr<Packet> packet, WifiMacHeader const*hdr);
+  void ForwardUp (Ptr<Packet> packet, const WifiMacHeader *hdr);
   AdhocWifiMac (const AdhocWifiMac & ctor_arg);
   AdhocWifiMac &operator = (const AdhocWifiMac &o);
   Ptr<DcaTxop> GetDcaTxop(void) const;
@@ -97,7 +97,6 @@
   MacRxMiddle *m_rxMiddle;
   Ptr<MacLow> m_low;
   Ssid m_ssid;
-  Time m_eifsNoDifs;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/dca-txop.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/dca-txop.cc	Sat May 30 17:37:38 2009 +0100
@@ -232,7 +232,7 @@
 }
 
 void 
-DcaTxop::Queue (Ptr<const Packet> packet, WifiMacHeader const &hdr)
+DcaTxop::Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
 {
   NS_LOG_FUNCTION (this << packet << &hdr);
   WifiMacTrailer fcs;
--- a/src/devices/wifi/dca-txop.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/dca-txop.h	Sat May 30 17:37:38 2009 +0100
@@ -67,8 +67,8 @@
 public:
   static TypeId GetTypeId (void);
 
-  typedef Callback <void, WifiMacHeader const&> TxOk;
-  typedef Callback <void, WifiMacHeader const&> TxFailed;
+  typedef Callback <void, const WifiMacHeader&> TxOk;
+  typedef Callback <void, const WifiMacHeader&> TxFailed;
 
   DcaTxop ();
   ~DcaTxop ();
@@ -104,7 +104,7 @@
    * Store the packet in the internal queue until it
    * can be sent safely.
    */
-  void Queue (Ptr<const Packet> packet, WifiMacHeader const &hdr);
+  void Queue (Ptr<const Packet> packet, const WifiMacHeader &hdr);
 
 private:
   class TransmissionListener;
--- a/src/devices/wifi/dcf-manager.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/dcf-manager.cc	Sat May 30 17:37:38 2009 +0100
@@ -261,6 +261,11 @@
 {
   m_eifsNoDifs = eifsNoDifs;
 }
+Time
+DcfManager::GetEifsNoDifs () const
+{
+  return m_eifsNoDifs;
+}
 
 void 
 DcfManager::Add (DcfState *dcf)
--- a/src/devices/wifi/dcf-manager.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/dcf-manager.h	Sat May 30 17:37:38 2009 +0100
@@ -169,6 +169,11 @@
   void SetEifsNoDifs (Time eifsNoDifs);
 
   /**
+   * \return value set previously using SetEifsNoDifs.
+   */
+  Time GetEifsNoDifs () const;
+
+  /**
    * \param dcf a new DcfState.
    *
    * The DcfManager does not take ownership of this pointer so, the callee
--- a/src/devices/wifi/interference-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/interference-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -123,7 +123,7 @@
  ****************************************************************/
 
 InterferenceHelper::InterferenceHelper ()
-  : m_80211a (false),
+  : m_80211_standard (WIFI_PHY_STANDARD_80211a),
     m_errorRateModel (0)
 {}
 InterferenceHelper::~InterferenceHelper ()
@@ -227,12 +227,25 @@
 Time
 InterferenceHelper::CalculateTxDuration (uint32_t size, WifiMode payloadMode, WifiPreamble preamble) const
 {
-  NS_ASSERT (m_80211a);
   uint64_t delay = 0;
-  delay += m_plcpLongPreambleDelayUs;
-  // symbol duration is 4us
-  delay += 4;
-  delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+  switch (m_80211_standard) 
+  {
+    case WIFI_PHY_STANDARD_80211a:
+    case WIFI_PHY_STANDARD_holland:
+      delay += m_plcpLongPreambleDelayUs;
+      // symbol duration is 4us
+      delay += 4;
+      delay += lrint (ceil ((size * 8.0 + 16.0 + 6.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+      break;
+    case WIFI_PHY_STANDARD_80211b:
+      delay += m_plcpLongPreambleDelayUs;
+      delay += lrint (ceil ((size * 8.0 + 48.0) / payloadMode.GetDataRate () / 4e-6) * 4);
+      break;
+    default:
+     NS_ASSERT (false);
+     break;
+  }
+
   return MicroSeconds (delay);
 }
 
@@ -240,7 +253,7 @@
 InterferenceHelper::Configure80211aParameters (void)
 {
   NS_LOG_FUNCTION (this);
-  m_80211a = true;
+  m_80211_standard = WIFI_PHY_STANDARD_80211a;
   m_plcpLongPreambleDelayUs = 16;
   m_plcpShortPreambleDelayUs = 16;
   m_longPlcpHeaderMode = WifiPhy::Get6mba ();
@@ -250,6 +263,20 @@
   m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get6mba (), WIFI_PREAMBLE_LONG);
 }
 
+void
+InterferenceHelper::Configure80211bParameters (void)
+{ 
+  NS_LOG_FUNCTION (this);
+  m_80211_standard = WIFI_PHY_STANDARD_80211b;
+  m_plcpLongPreambleDelayUs = 144;
+  m_plcpShortPreambleDelayUs = 144; // fixed preamable for 802.11b
+  m_longPlcpHeaderMode = WifiPhy::Get1mbb ();
+  m_shortPlcpHeaderMode = WifiPhy::Get1mbb ();
+  // PLCP Header: signal 8, service 8, length 16, CRC 16 bits
+  m_plcpHeaderLength = 8 + 8 + 16 + 16;
+  m_maxPacketDuration = CalculateTxDuration (4095, WifiPhy::Get1mbb (), WIFI_PREAMBLE_LONG);
+}
+
 void 
 InterferenceHelper::AppendEvent (Ptr<InterferenceHelper::Event> event)
 {
--- a/src/devices/wifi/interference-helper.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/interference-helper.h	Sat May 30 17:37:38 2009 +0100
@@ -25,6 +25,7 @@
 #include <list>
 #include "wifi-mode.h"
 #include "wifi-preamble.h"
+#include "wifi-phy-standard.h"
 #include "ns3/nstime.h"
 #include "ns3/ref-count-base.h"
 
@@ -69,6 +70,7 @@
   ~InterferenceHelper ();
 
   void Configure80211aParameters (void);
+  void Configure80211bParameters (void);
   void SetNoiseFigure (double value);
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
 
@@ -120,7 +122,7 @@
   Time m_maxPacketDuration;
   double m_noiseFigure; /**< noise figure (linear) */
   Events m_events;
-  bool m_80211a;
+  enum WifiPhyStandard m_80211_standard;
   Ptr<ErrorRateModel> m_errorRateModel;
 };
 
--- a/src/devices/wifi/jakes-propagation-loss-model.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/jakes-propagation-loss-model.cc	Sat May 30 17:37:38 2009 +0100
@@ -127,7 +127,7 @@
 
 NS_OBJECT_ENSURE_REGISTERED (JakesPropagationLossModel);
 
-const double JakesPropagationLossModel::PI = 3.1415;
+const double JakesPropagationLossModel::PI = 3.14159265358979323846;
 
 TypeId
 JakesPropagationLossModel::GetTypeId (void)
--- a/src/devices/wifi/msdu-aggregator.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/msdu-aggregator.cc	Sat May 30 17:37:38 2009 +0100
@@ -59,7 +59,7 @@
      
      padding = (4 - ((hdr.GetLength () + 14) %4 )) % 4;
   
-     if (padding > 0)
+     if (padding > 0 && deserialized < maxSize)
        {
          aggregatedPacket->RemoveAtStart (padding);
          deserialized += padding;
--- a/src/devices/wifi/msdu-standard-aggregator.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/msdu-standard-aggregator.cc	Sat May 30 17:37:38 2009 +0100
@@ -57,19 +57,20 @@
   Ptr<Packet> currentPacket;
   AmsduSubframeHeader currentHdr;
 
-  uint32_t padding = CalculatePadding (packet);
+  uint32_t padding = CalculatePadding (aggregatedPacket);
   uint32_t actualSize = aggregatedPacket->GetSize ();
                           
   if ((14 + packet->GetSize () + actualSize + padding) <= m_maxAmsduLength)
     {
+      if (padding)
+        {
+          aggregatedPacket->AddPaddingAtEnd (padding);
+        }
       currentHdr.SetDestinationAddr (dest);
       currentHdr.SetSourceAddr (src);
       currentHdr.SetLength (packet->GetSize ());
       currentPacket = packet->Copy ();
-      if (padding)
-        {
-          currentPacket->AddPaddingAtEnd (padding);
-        }
+      
       currentPacket->AddHeader (currentHdr);
       aggregatedPacket->AddAtEnd (currentPacket);
       return true;
@@ -80,7 +81,7 @@
 uint32_t
 MsduStandardAggregator::CalculatePadding (Ptr<const Packet> packet)
 {
-  return (4 - ((packet->GetSize() + 14) %4 )) % 4;
+  return (4 - (packet->GetSize() %4 )) % 4;
 }
 
 }  //namespace ns3
--- a/src/devices/wifi/msdu-standard-aggregator.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/msdu-standard-aggregator.h	Sat May 30 17:37:38 2009 +0100
@@ -43,7 +43,8 @@
   virtual bool Aggregate (Ptr<const Packet> packet, Ptr<Packet> aggregatedPacket,
                           Mac48Address src, Mac48Address dest);
 private:
-  /*  Calculates how much padding must be added to the end of packet.
+  /*  Calculates how much padding must be added to the end of aggregated packet,
+      after that a new packet is added.
       Each A-MSDU subframe is padded so that its length is multiple of 4 octects.
    */
   uint32_t CalculatePadding (Ptr<const Packet> packet);
--- a/src/devices/wifi/nqap-wifi-mac.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/nqap-wifi-mac.cc	Sat May 30 17:37:38 2009 +0100
@@ -152,7 +152,6 @@
 {
   NS_LOG_FUNCTION (this << eifsNoDifs);
   m_dcfManager->SetEifsNoDifs (eifsNoDifs);
-  m_eifsNoDifs = eifsNoDifs;
 }
 void 
 NqapWifiMac::SetAckTimeout (Time ackTimeout)
@@ -182,7 +181,7 @@
 Time 
 NqapWifiMac::GetEifsNoDifs (void) const
 {
-  return m_eifsNoDifs;
+  return m_dcfManager->GetEifsNoDifs ();
 }
 Time 
 NqapWifiMac::GetAckTimeout (void) const
--- a/src/devices/wifi/nqap-wifi-mac.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/nqap-wifi-mac.h	Sat May 30 17:37:38 2009 +0100
@@ -129,7 +129,6 @@
   Ptr<MacLow> m_low;
   Ssid m_ssid;
   EventId m_beaconEvent;
-  Time m_eifsNoDifs;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/nqsta-wifi-mac.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/nqsta-wifi-mac.cc	Sat May 30 17:37:38 2009 +0100
@@ -156,7 +156,6 @@
 {
   NS_LOG_FUNCTION (this << eifsNoDifs);
   m_dcfManager->SetEifsNoDifs (eifsNoDifs);
-  m_eifsNoDifs = eifsNoDifs;
 }
 void 
 NqstaWifiMac::SetAckTimeout (Time ackTimeout)
@@ -186,7 +185,7 @@
 Time 
 NqstaWifiMac::GetEifsNoDifs (void) const
 {
-  return m_eifsNoDifs;
+  return m_dcfManager->GetEifsNoDifs ();
 }
 Time 
 NqstaWifiMac::GetAckTimeout (void) const
--- a/src/devices/wifi/nqsta-wifi-mac.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/nqsta-wifi-mac.h	Sat May 30 17:37:38 2009 +0100
@@ -160,7 +160,6 @@
   MacRxMiddle *m_rxMiddle;
   Ptr<MacLow> m_low;
   Ssid m_ssid;
-  Time m_eifsNoDifs;
 
   TracedCallback<Mac48Address> m_assocLogger;
   TracedCallback<Mac48Address> m_deAssocLogger;
--- a/src/devices/wifi/propagation-loss-model.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/propagation-loss-model.cc	Sat May 30 17:37:38 2009 +0100
@@ -107,7 +107,7 @@
 
 NS_OBJECT_ENSURE_REGISTERED (FriisPropagationLossModel);
 
-const double FriisPropagationLossModel::PI = 3.1415;
+const double FriisPropagationLossModel::PI = 3.14159265358979323846;
 
 TypeId 
 FriisPropagationLossModel::GetTypeId (void)
@@ -408,5 +408,139 @@
   return txPowerDbm - pathLossDb;
 }
 
+// ------------------------------------------------------------------------- //
+
+NS_OBJECT_ENSURE_REGISTERED (NakagamiPropagationLossModel);
+
+TypeId
+NakagamiPropagationLossModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::NakagamiPropagationLossModel")
+    .SetParent<PropagationLossModel> ()
+    .AddConstructor<NakagamiPropagationLossModel> ()
+    .AddAttribute ("Distance1",
+                   "Beginning of the second distance field. Default is 80m.",
+                   DoubleValue (80.0),
+                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance1),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Distance2",
+                   "Beginning of the third distance field. Default is 200m.",
+                   DoubleValue (200.0),
+                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance2),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("m0",
+                   "m0 for distances smaller than Distance1. Default is 1.5.",
+                   DoubleValue (1.5),
+                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m0),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("m1",
+                   "m1 for distances smaller than Distance2. Default is 0.75.",
+                   DoubleValue (0.75),
+                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m1),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("m2",
+                   "m2 for distances greater than Distance2. Default is 0.75.",
+                   DoubleValue (0.75),
+                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m2),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+                   
+}
+
+NakagamiPropagationLossModel::NakagamiPropagationLossModel ()
+{}
+
+double 
+NakagamiPropagationLossModel::DoCalcRxPower (double txPowerDbm,
+                                             Ptr<MobilityModel> a,
+                                             Ptr<MobilityModel> b) const
+{
+  // select m parameter
+
+  double distance = a->GetDistanceFrom (b);
+  NS_ASSERT(distance >= 0);
+
+  double m;
+  if (distance < m_distance1)
+    {
+      m = m_m0;
+    }
+  else if (distance < m_distance2)
+    {
+      m = m_m1;
+    }
+  else
+    {
+      m = m_m2;
+    }
+  
+  // the current power unit is dBm, but Watt is put into the Nakagami /
+  // Rayleigh distribution.
+  double powerW = pow(10, (txPowerDbm - 30) / 10);
+
+  double resultPowerW;
+
+  // switch between Erlang- and Gamma distributions: this is only for
+  // speed. (Gamma is equal to Erlang for any positive integer m.)
+  unsigned int int_m = static_cast<unsigned int>(floor(m));
+
+  if (int_m == m)
+    {
+      resultPowerW = m_erlangRandomVariable.GetValue(int_m, powerW / m);
+    }
+  else
+    {
+      resultPowerW = m_gammaRandomVariable.GetValue(m, powerW / m);
+    }
+
+  double resultPowerDbm = 10 * log10(resultPowerW) + 30;
+
+  NS_LOG_DEBUG ("Nakagami distance=" << distance << "m, " <<
+                "power=" << powerW <<"W, " <<
+                "resultPower=" << resultPowerW << "W=" << resultPowerDbm << "dBm");
+
+  return resultPowerDbm;
+}
+
+// ------------------------------------------------------------------------- //
+
+NS_OBJECT_ENSURE_REGISTERED (FixedRssLossModel);
+
+TypeId 
+FixedRssLossModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::FixedRssLossModel")
+    .SetParent<PropagationLossModel> ()
+    .AddConstructor<FixedRssLossModel> ()
+    .AddAttribute ("Rss", "The fixed receiver Rss.",
+                   DoubleValue (-150.0),
+                   MakeDoubleAccessor (&FixedRssLossModel::m_rss),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+}
+FixedRssLossModel::FixedRssLossModel ()
+  : PropagationLossModel ()
+{}
+
+FixedRssLossModel::~FixedRssLossModel ()
+{}
+
+void 
+FixedRssLossModel::SetRss (double rss)
+{
+  m_rss = rss;
+}
+
+double 
+FixedRssLossModel::DoCalcRxPower (double txPowerDbm,
+                                           Ptr<MobilityModel> a,
+                                           Ptr<MobilityModel> b) const
+{
+  return m_rss;
+}
+
+// ------------------------------------------------------------------------- //
 
 } // namespace ns3
--- a/src/devices/wifi/propagation-loss-model.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/propagation-loss-model.h	Sat May 30 17:37:38 2009 +0100
@@ -17,6 +17,7 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  * Contributions: Timo Bingmann <timo.bingmann@student.kit.edu>
+ * Contributions: Gary Pei <guangyu.pei@boeing.com> for fixed RSS
  */
 
 #ifndef PROPAGATION_LOSS_MODEL_H
@@ -296,6 +297,79 @@
   double m_referenceLoss;
 };
 
+/**
+ * \brief Nakagami-m fast fading propagation loss model.
+ *
+ * The Nakagami-m distribution is applied to the power level. The probability
+ * density function is defined as
+ * \f[ p(x; m, \omega) = \frac{2 m^m}{\Gamma(m) \omega^m} x^{2m - 1} e^{-\frac{m}{\omega} x^2} = 2 x \cdot p_{\text{Gamma}}(x^2, m, \frac{m}{\omega}) \f]
+ * with \f$ m \f$ the fading depth parameter and \f$ \omega \f$ the average received power.
+ *
+ * It is implemented by either a ns3::GammaVariable or a ns3::ErlangVariable
+ * random variable.
+ *
+ * Like in ns3::ThreeLogDistancePropagationLossModel, the m parameter is varied
+ * over three distance fields:
+ * \f[ \underbrace{0 \cdots\cdots}_{m_0} \underbrace{d_1 \cdots\cdots}_{m_1} \underbrace{d_2 \cdots\cdots}_{m_2} \infty \f]
+ *
+ * For m = 1 the Nakagami-m distribution equals the Rayleigh distribution. Thus
+ * this model also implements Rayleigh distribution based fast fading.
+ */
+
+class NakagamiPropagationLossModel : public PropagationLossModel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  NakagamiPropagationLossModel ();
+
+  // Parameters are all accessible via attributes.
+
+private:
+  NakagamiPropagationLossModel (const NakagamiPropagationLossModel& o);
+  NakagamiPropagationLossModel& operator= (const NakagamiPropagationLossModel& o);
+
+  virtual double DoCalcRxPower (double txPowerDbm,
+                                Ptr<MobilityModel> a,
+                                Ptr<MobilityModel> b) const;
+
+  double m_distance1;
+  double m_distance2;
+
+  double m_m0;
+  double m_m1;
+  double m_m2;
+
+  ErlangVariable        m_erlangRandomVariable;
+  GammaVariable         m_gammaRandomVariable;
+};
+
+/**
+ * \brief The propagation loss is fixed. The user can set received power level.
+ */ 
+class FixedRssLossModel : public PropagationLossModel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  FixedRssLossModel ();
+  virtual ~FixedRssLossModel ();
+  /**
+   * \param RSS (dBm) the received signal strength
+   *
+   * Set the RSS.
+   */
+  void SetRss (double rss);
+
+private:
+  FixedRssLossModel (const FixedRssLossModel &o);
+  FixedRssLossModel & operator = (const FixedRssLossModel &o);
+  virtual double DoCalcRxPower (double txPowerDbm,
+                                Ptr<MobilityModel> a,
+                                Ptr<MobilityModel> b) const;
+  double m_rss;
+};
+
 } // namespace ns3
 
 #endif /* PROPAGATION_LOSS_MODEL_H */
--- a/src/devices/wifi/qap-wifi-mac.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/qap-wifi-mac.cc	Sat May 30 17:37:38 2009 +0100
@@ -188,7 +188,6 @@
 {
   NS_LOG_FUNCTION (this << eifsNoDifs);
   m_dcfManager->SetEifsNoDifs (eifsNoDifs);
-  m_eifsNoDifs = eifsNoDifs;
 }
 
 void 
@@ -224,7 +223,7 @@
 Time 
 QapWifiMac::GetEifsNoDifs (void) const
 {
-  return m_eifsNoDifs;
+  return m_dcfManager->GetEifsNoDifs ();
 }
 
 Time 
--- a/src/devices/wifi/qap-wifi-mac.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/qap-wifi-mac.h	Sat May 30 17:37:38 2009 +0100
@@ -88,7 +88,7 @@
 
 private:
   virtual void DoDispose (void);
-  void Receive (Ptr<Packet> packet, WifiMacHeader const *hdr);
+  void Receive (Ptr<Packet> packet, WifiMacHeader const*hdr);
   void ForwardUp (Ptr<Packet> packet, Mac48Address from, Mac48Address to);
   void ForwardDown (Ptr<const Packet> packet, Mac48Address from, Mac48Address to);
   /* Next function is invoked only when ap relies a frame. */
@@ -139,7 +139,6 @@
   Ssid m_ssid;
   EventId m_beaconEvent;
   Time m_beaconInterval;
-  Time m_eifsNoDifs;
 };
 
 }  //namespace ns3
--- a/src/devices/wifi/qsta-wifi-mac.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.cc	Sat May 30 17:37:38 2009 +0100
@@ -164,7 +164,6 @@
 {
   NS_LOG_FUNCTION (this << eifsNoDifs);
   m_dcfManager->SetEifsNoDifs (eifsNoDifs);
-  m_eifsNoDifs = eifsNoDifs;
 }
 
 void
@@ -200,7 +199,7 @@
 Time 
 QstaWifiMac::GetEifsNoDifs (void) const
 {
-  return m_eifsNoDifs;
+  return m_dcfManager->GetEifsNoDifs ();
 }
 
 Time
--- a/src/devices/wifi/qsta-wifi-mac.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/qsta-wifi-mac.h	Sat May 30 17:37:38 2009 +0100
@@ -163,7 +163,6 @@
   EventId m_beaconWatchdog;
   
   uint32_t m_maxMissedBeacons;
-  Time m_eifsNoDifs;
 };
 
 }  //namespace ns3
--- a/src/devices/wifi/wifi-mac-queue.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-mac-queue.cc	Sat May 30 17:37:38 2009 +0100
@@ -32,7 +32,7 @@
 NS_OBJECT_ENSURE_REGISTERED (WifiMacQueue);
 
 WifiMacQueue::Item::Item (Ptr<const Packet> packet, 
-                          WifiMacHeader const &hdr, 
+                          const WifiMacHeader &hdr, 
                           Time tstamp)
   : packet (packet), hdr (hdr), tstamp (tstamp)
 {}
@@ -89,7 +89,7 @@
 }
 
 void 
-WifiMacQueue::Enqueue (Ptr<const Packet> packet, WifiMacHeader const &hdr)
+WifiMacQueue::Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr)
 {
   Cleanup ();
   if (m_size == m_maxSize) 
--- a/src/devices/wifi/wifi-mac-queue.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-mac-queue.h	Sat May 30 17:37:38 2009 +0100
@@ -60,7 +60,7 @@
   uint32_t GetMaxSize (void) const;
   Time GetMaxDelay (void) const;
 
-  void Enqueue (Ptr<const Packet> packet, WifiMacHeader const &hdr);
+  void Enqueue (Ptr<const Packet> packet, const WifiMacHeader &hdr);
   Ptr<const Packet> Dequeue (WifiMacHeader *hdr);
   Ptr<const Packet> Peek (WifiMacHeader *hdr);
   /**
@@ -109,7 +109,7 @@
   
   struct Item {
     Item (Ptr<const Packet> packet, 
-          WifiMacHeader const &hdr, 
+          const WifiMacHeader &hdr, 
           Time tstamp);
     Ptr<const Packet> packet;
     WifiMacHeader hdr;
--- a/src/devices/wifi/wifi-mode.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-mode.cc	Sat May 30 17:37:38 2009 +0100
@@ -165,7 +165,44 @@
   item->isMandatory = isMandatory;
   return WifiMode (uid);
 }
-
+WifiMode 
+WifiModeFactory::CreateDbpsk (std::string uniqueName,
+			     bool isMandatory,
+			     uint32_t bandwidth,
+			     uint32_t dataRate,
+			     uint32_t phyRate)
+{
+  WifiModeFactory *factory = GetFactory ();
+  uint32_t uid = factory->AllocateUid (uniqueName);
+  WifiModeItem *item = factory->Get (uid);
+  item->uniqueUid = uniqueName;
+  item->bandwidth = bandwidth;
+  item->dataRate = dataRate;
+  item->phyRate = phyRate;
+  item->modulation = WifiMode::DBPSK;
+  item->constellationSize = 2;
+  item->isMandatory = isMandatory;
+  return WifiMode (uid);
+}
+WifiMode 
+WifiModeFactory::CreateDqpsk (std::string uniqueName,
+			     bool isMandatory,
+			     uint32_t bandwidth,
+			     uint32_t dataRate,
+			     uint32_t phyRate)
+{
+  WifiModeFactory *factory = GetFactory ();
+  uint32_t uid = factory->AllocateUid (uniqueName);
+  WifiModeItem *item = factory->Get (uid);
+  item->uniqueUid = uniqueName;
+  item->bandwidth = bandwidth;
+  item->dataRate = dataRate;
+  item->phyRate = phyRate;
+  item->modulation = WifiMode::DQPSK;
+  item->constellationSize = 4;
+  item->isMandatory = isMandatory;
+  return WifiMode (uid);
+}
 bool 
 WifiModeFactory::Search (std::string name, WifiMode *mode)
 {
--- a/src/devices/wifi/wifi-mode.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-mode.h	Sat May 30 17:37:38 2009 +0100
@@ -41,6 +41,8 @@
  public:
   enum ModulationType {
     BPSK,
+    DBPSK,
+    DQPSK,
     QAM
   };
   
@@ -170,6 +172,40 @@
 			     uint32_t phyRate,
 			     uint8_t constellationSize);
 
+  /**
+   * \param uniqueName the name of the associated WifiMode. This name
+   *        must be unique accross _all_ instances.
+   * \param isMandatory true if this WifiMode is mandatory, false otherwise.
+   * \param bandwidth the bandwidth (Hz) of the signal generated when the
+   *        associated WifiMode is used.
+   * \param dataRate the rate (bits/second) at which the user data is transmitted
+   * \param phyRate the rate (bits/second) at which the encoded user data is transmitted
+   *        The phyRate includes FEC so, is typically higher than the dataRate.
+   *
+   * Create a DBPSK WifiMode.
+   */
+  static WifiMode CreateDbpsk (std::string uniqueName,
+			      bool isMandatory,
+			      uint32_t bandwidth,
+			      uint32_t dataRate,
+			      uint32_t phyRate);
+  /**
+   * \param uniqueName the name of the associated WifiMode. This name
+   *        must be unique accross _all_ instances.
+   * \param isMandatory true if this WifiMode is mandatory, false otherwise.
+   * \param bandwidth the bandwidth (Hz) of the signal generated when the
+   *        associated WifiMode is used.
+   * \param dataRate the rate (bits/second) at which the user data is transmitted
+   * \param phyRate the rate (bits/second) at which the encoded user data is transmitted
+   *        The phyRate includes FEC so, is typically higher than the dataRate.
+   *
+   * Create a DQPSK WifiMode.
+   */
+  static WifiMode CreateDqpsk (std::string uniqueName,
+			      bool isMandatory,
+			      uint32_t bandwidth,
+			      uint32_t dataRate,
+			      uint32_t phyRate);
 private:
   friend class WifiMode;  
   friend std::istream & operator >> (std::istream &is, WifiMode &mode);
--- a/src/devices/wifi/wifi-phy-standard.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-phy-standard.h	Sat May 30 17:37:38 2009 +0100
@@ -24,6 +24,7 @@
 
 enum WifiPhyStandard {
   WIFI_PHY_STANDARD_80211a,
+  WIFI_PHY_STANDARD_80211b,
   WIFI_PHY_STANDARD_holland
 };
 
--- a/src/devices/wifi/wifi-phy.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-phy.cc	Sat May 30 17:37:38 2009 +0100
@@ -199,6 +199,43 @@
   m_phyPromiscSnifferTrace (packet);
 }
 
+WifiMode 
+WifiPhy::Get1mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDbpsk ("wifib-1mbs",
+                                                      true,
+                                                      22000000, 1000000, 1000000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get2mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-2mbs",
+                                                      true,
+                                                      22000000, 2000000, 2000000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get5_5mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-5.5mbs",
+                                                      true,
+                                                      22000000, 5500000, 5500000);
+  return mode;
+}
+
+WifiMode 
+WifiPhy::Get11mbb (void)
+{
+  static WifiMode mode = WifiModeFactory::CreateDqpsk ("wifib-11mbs",
+                                                      true,
+                                                      22000000, 11000000, 11000000);
+  return mode;
+}
+
+
 } // namespace ns3
 
 namespace {
@@ -215,6 +252,10 @@
     ns3::WifiPhy::Get36mba ();
     ns3::WifiPhy::Get48mba ();
     ns3::WifiPhy::Get54mba ();
+    ns3::WifiPhy::Get1mbb ();
+    ns3::WifiPhy::Get2mbb ();
+    ns3::WifiPhy::Get5_5mbb ();
+    ns3::WifiPhy::Get11mbb ();
   }
 } g_constructor;
 }
--- a/src/devices/wifi/wifi-phy.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wifi-phy.h	Sat May 30 17:37:38 2009 +0100
@@ -252,6 +252,11 @@
   static WifiMode Get36mba (void);
   static WifiMode Get48mba (void);
   static WifiMode Get54mba (void);
+  static WifiMode Get1mbb (void);
+  static WifiMode Get2mbb (void);
+  static WifiMode Get5_5mbb (void);
+  static WifiMode Get11mbb (void);
+
 
   /**
    * Public method used to fire a PhyTxBegin trace.  Implemented for encapsulation 
--- a/src/devices/wifi/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/wscript	Sat May 30 17:37:38 2009 +0100
@@ -1,5 +1,12 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+def configure(conf): 
+    have_gsl = conf.pkg_check_modules('GSL', 'gsl', mandatory=False)
+    conf.env['ENABLE_GSL'] = have_gsl
+    conf.report_optional_feature("GSL", "GNU Scientific Library (GSL)",
+                                 conf.env['ENABLE_GSL'],
+                                 "GSL not found")
+
 def build(bld):
     obj = bld.create_ns3_module('wifi', ['node'])
     obj.source = [
@@ -100,6 +107,12 @@
         'qos-tag.h',
         ]
 
+    if bld.env['ENABLE_GSL']:
+        obj.uselib = 'GSL GSLCBLAS M'
+        obj.env.append_value('CXXDEFINES', "ENABLE_GSL")
+
     obj = bld.create_ns3_program('wifi-phy-test',
         ['core', 'simulator', 'mobility', 'node', 'wifi'])
     obj.source = 'wifi-phy-test.cc'
+
+
--- a/src/devices/wifi/yans-error-rate-model.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/yans-error-rate-model.cc	Sat May 30 17:37:38 2009 +0100
@@ -27,6 +27,11 @@
 
 NS_OBJECT_ENSURE_REGISTERED (YansErrorRateModel);
 
+#ifndef ENABLE_GSL
+const double YansErrorRateModel::WLAN_SIR_PERFECT = 10.0; 
+const double YansErrorRateModel::WLAN_SIR_IMPOSSIBLE = 0.1; 
+#endif
+
 TypeId 
 YansErrorRateModel::GetTypeId (void)
 {
@@ -263,7 +268,159 @@
                            31  // adFreePlusOne
                            );
     }
+  else if (mode == WifiPhy::Get1mbb ())
+    {
+      return Get80211bDsssDbpskSuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get2mbb ())
+    {
+      return Get80211bDsssDqpskSuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get5_5mbb ())
+    {
+      return Get80211bDsssDqpskCck5_5SuccessRate (snr,nbits);
+    }
+  else if (mode == WifiPhy::Get11mbb ())
+    {
+      return Get80211bDsssDqpskCck11SuccessRate (snr,nbits);
+    }
   return 0;
 }
 
+// 802.11b ber based on "Wireless Network Coexistence: Wireless
+// LAN in the 21st Century" by Robert Morrow page 187
+double 
+YansErrorRateModel::DqpskFunction (double x) const
+{
+  return ((sqrt (2.0) + 1.0) / sqrt (8.0*3.1415926*sqrt (2.0)))
+         *(1.0/sqrt (x))
+         *exp ( - (2.0 - sqrt (2.0)) * x) ;
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDbpskSuccessRate (double sinr, uint32_t nbits) const
+{
+  double EbN0 = sinr * 22000000.0 / 1000000.0; // 1 bit per symbol with 1 MSPS
+  double ber = 0.5 * exp (-EbN0);
+  return pow ((1.0 - ber), nbits);
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskSuccessRate (double sinr,uint32_t nbits) const
+{
+  double EbN0 = sinr * 22000000.0 / 1000000.0 / 2.0; // 2 bits per symbol, 1 MSPS
+  double ber = DqpskFunction (EbN0);
+  return pow ((1.0 - ber), nbits);
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskCck5_5SuccessRate (double sinr,uint32_t nbits) const
+{
+#ifdef ENABLE_GSL
+  // symbol error probability
+  double EbN0 = sinr * 22000000.0 / 1375000.0 / 4.0;
+  double sep = SymbolErrorProb16Cck (4.0*EbN0/2.0);
+  return pow (1.0-sep,nbits/4.0);
+#else
+  NS_LOG_WARN ("Running a 802.11b CCK Matlab model less accurate than GSL model"); 
+  // The matlab model
+  double ber; 
+  if (sinr > WLAN_SIR_PERFECT)
+    {
+       ber = 0.0 ;
+    }
+  else if (sinr < WLAN_SIR_IMPOSSIBLE)
+    {
+       ber = 0.5;
+    }
+  else
+    { // fitprops.coeff from matlab berfit
+       double a1 =  5.3681634344056195e-001;
+       double a2 =  3.3092430025608586e-003;
+       double a3 =  4.1654372361004000e-001;
+       double a4 =  1.0288981434358866e+000;
+       ber = a1 * exp (-(pow ((sinr-a2)/a3,a4)));
+     }
+  return pow ((1.0 - ber), nbits);
+#endif
+}
+
+double 
+YansErrorRateModel::Get80211bDsssDqpskCck11SuccessRate (double sinr,uint32_t nbits) const
+{
+#ifdef ENABLE_GSL
+ // symbol error probability
+  double EbN0 = sinr * 22000000.0 / 1375000.0 / 8.0;
+  double sep = SymbolErrorProb256Cck (8.0*EbN0/2.0);
+  return pow (1.0-sep,nbits/8.0);
+#else
+  NS_LOG_WARN ("Running a 802.11b CCK Matlab model less accurate than GSL model"); 
+  // The matlab model
+  double ber; 
+  if (sinr > WLAN_SIR_PERFECT)
+    {
+       ber = 0.0 ;
+    }
+  else if (sinr < WLAN_SIR_IMPOSSIBLE)
+    {
+       ber = 0.5;
+    }
+  else
+    { // fitprops.coeff from matlab berfit
+       double a1 =  7.9056742265333456e-003;
+       double a2 = -1.8397449399176360e-001;
+       double a3 =  1.0740689468707241e+000;
+       double a4 =  1.0523316904502553e+000;
+       double a5 =  3.0552298746496687e-001;
+       double a6 =  2.2032715128698435e+000;
+       ber =  (a1*sinr*sinr+a2*sinr+a3)/(sinr*sinr*sinr+a4*sinr*sinr+a5*sinr+a6);
+     }
+  return pow ((1.0 - ber), nbits);
+#endif
+}
+
+#ifdef ENABLE_GSL
+double 
+IntegralFunction (double x, void *params)
+{
+  double beta = ((FunctionParameters *) params)->beta;
+  double n = ((FunctionParameters *) params)->n;
+  double IntegralFunction = pow (2*gsl_cdf_ugaussian_P (x+ beta) - 1, n-1) 
+                            * exp (-x*x/2.0) / sqrt (2.0 * M_PI);
+  return IntegralFunction;
+}
+
+double 
+YansErrorRateModel::SymbolErrorProb16Cck (double e2) const
+{
+  double sep;
+  double error;
+ 
+  FunctionParameters params;
+  params.beta = sqrt (2.0*e2);
+  params.n = 8.0;
+
+  gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000); 
+ 
+  gsl_function F;
+  F.function = &IntegralFunction;
+  F.params = &params;
+
+  gsl_integration_qagiu (&F,-params.beta, 0, 1e-7, 1000, w, &sep, &error);
+  gsl_integration_workspace_free (w);
+  if (error == 0.0) 
+    {
+       sep = 1.0;
+    }
+
+  return 1.0 - sep;
+}
+
+double YansErrorRateModel::SymbolErrorProb256Cck (double e1) const
+{
+  return 1.0 - pow (1.0 - SymbolErrorProb16Cck (e1/2.0), 2.0);
+}
+
+#endif
+
 } // namespace ns3
--- a/src/devices/wifi/yans-error-rate-model.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/yans-error-rate-model.h	Sat May 30 17:37:38 2009 +0100
@@ -21,11 +21,51 @@
 #define YANS_ERROR_RATE_MODEL_H
 
 #include <stdint.h>
+#ifdef ENABLE_GSL
+#include <gsl/gsl_math.h>
+#include <gsl/gsl_integration.h>
+#include <gsl/gsl_cdf.h>
+#include <gsl/gsl_sf_bessel.h>
+#endif
 #include "wifi-mode.h"
 #include "error-rate-model.h"
 
 namespace ns3 {
 
+#ifdef ENABLE_GSL
+typedef struct FunctionParameterType
+{
+ double beta;
+ double n;
+} FunctionParameters;
+
+double IntegralFunction (double x, void *params);
+#endif
+
+/**
+ * \brief Model the error rate for different modulations.
+ *
+ * A packet of interest (e.g., a packet can potentially be received by the MAC) 
+ * is divided into chunks. Each chunk is related to an start/end receiving event. 
+ * For each chunk, it calculates the ratio (SINR) between received power of packet 
+ * of interest and summation of noise and interfering power of all the other incoming 
+ * packets. Then, it will calculate the success rate of the chunk based on 
+ * BER of the modulation. The success reception rate of the packet is derived from 
+ * the success rate of all chunks.
+ *
+ * The 802.11b modulations:
+ *    - 1 Mbps mode is based on DBPSK. BER is from equation 5.2-69 from John G. Proakis
+ *      Digitial Communications, 2001 edition
+ *    - 2 Mbps model is based on DQPSK. Equation 8 from "Tight bounds and accurate 
+ *      approximations for dqpsk transmission bit error rate", G. Ferrari and G.E. Corazza 
+ *      ELECTRONICS LETTERS, 40(20):1284-1285, September 2004
+ *    - 5.5 Mbps and 11 Mbps are based on equations (18) and (17) from "Properties and 
+ *      performance of the ieee 802.11b complementarycode-key signal sets", 
+ *      Michael B. Pursley and Thomas C. Royster. IEEE TRANSACTIONS ON COMMUNICATIONS, 
+ *      57(2):440-449, February 2009.
+ *    - More detailed description and validation can be found in 
+ *      http://www.nsnam.org/~pei/80211b.pdf
+ */
 class YansErrorRateModel : public ErrorRateModel
 {
 public:
@@ -52,6 +92,19 @@
                        uint32_t phyRate,
                        uint32_t m, uint32_t dfree,
                        uint32_t adFree, uint32_t adFreePlusOne) const;
+  double DqpskFunction (double x) const;
+  double Get80211bDsssDbpskSuccessRate (double sinr, uint32_t nbits) const;
+  double Get80211bDsssDqpskSuccessRate (double sinr,uint32_t nbits) const;
+  double Get80211bDsssDqpskCck5_5SuccessRate (double sinr,uint32_t nbits) const;
+  double Get80211bDsssDqpskCck11SuccessRate (double sinr,uint32_t nbits) const;
+#ifdef ENABLE_GSL
+  double SymbolErrorProb16Cck (double e2) const; /// equation (18) in Pursley's paper
+  double SymbolErrorProb256Cck (double e1) const; /// equation (17) in Pursley's paper
+#else
+private:
+  static const double WLAN_SIR_PERFECT;
+  static const double WLAN_SIR_IMPOSSIBLE;
+#endif
 };
 
 
--- a/src/devices/wifi/yans-wifi-phy.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/yans-wifi-phy.cc	Sat May 30 17:37:38 2009 +0100
@@ -110,6 +110,7 @@
                    EnumValue (WIFI_PHY_STANDARD_80211a),
                    MakeEnumAccessor (&YansWifiPhy::SetStandard),
                    MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
+                                    WIFI_PHY_STANDARD_80211b, "802.11b",
                                     WIFI_PHY_STANDARD_holland, "holland"))
     .AddAttribute ("State", "The state of the PHY layer",
                    PointerValue (),
@@ -150,6 +151,9 @@
   case WIFI_PHY_STANDARD_80211a:
     Configure80211a ();
     break;
+  case WIFI_PHY_STANDARD_80211b:
+    Configure80211b ();
+    break;
   case WIFI_PHY_STANDARD_holland:
     ConfigureHolland ();
     break;
@@ -440,6 +444,18 @@
   m_modes.push_back (WifiPhy::Get54mba ());
 }
 
+
+void
+YansWifiPhy::Configure80211b (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_interference.Configure80211bParameters ();
+  m_modes.push_back (WifiPhy::Get1mbb ());
+  m_modes.push_back (WifiPhy::Get2mbb ());
+  m_modes.push_back (WifiPhy::Get5_5mbb ());
+  m_modes.push_back (WifiPhy::Get11mbb ());
+}
+
 void
 YansWifiPhy::ConfigureHolland (void)
 {
--- a/src/devices/wifi/yans-wifi-phy.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/devices/wifi/yans-wifi-phy.h	Sat May 30 17:37:38 2009 +0100
@@ -124,6 +124,7 @@
   YansWifiPhy (const YansWifiPhy &o);
   virtual void DoDispose (void);
   void Configure80211a (void);
+  void Configure80211b (void);
   void ConfigureHolland (void);
   double GetEdThresholdW (void) const;
   double DbmToW (double dbm) const;
--- a/src/helper/internet-stack-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/internet-stack-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -16,6 +16,136 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Author: Faker Moatamri <faker.moatamri@sophia.inria.fr>
+ */
+
+/**
+ * \ingroup internetStack
+ * \defgroup internetStackModel Internet Stack Model
+ *
+ * \section internetStackTracingModel Tracing in the Internet Stack
+ *
+ * The internet stack provides a number of trace sources in its various
+ * protocol implementations.  These trace sources can be hooked using your own 
+ * custom trace code, or you can use our helper functions in some cases to 
+ * arrange for tracing to be enabled.
+ *
+ * \subsection internetStackArpTracingModel Tracing in ARP
+ *
+ * ARP provides two trace hooks, one in the cache, and one in the layer three
+ * protocol.  The trace accessor in the cache is given the name "Drop."  When
+ * a packet is transmitted over an interface that requires ARP, it is first
+ * queued for transmission in the ARP cache until the required MAC address is
+ * resolved.  There are a number of retries that may be done trying to get the 
+ * address, and if the maximum retry count is exceeded the packet in question 
+ * is dropped by ARP.  The single trace hook in the ARP cache is called,
+ *
+ * - If an outbound packet is placed in the ARP cache pending address resolution
+ *   and no resolution can be made within the maximum retry count, the outbound 
+ *   packet is dropped and this trace is fired;
+ *
+ * A second trace hook lives in the ARP L3 protocol (also named "Drop") and may 
+ * be called for a  number of reasons.
+ *
+ * - If an ARP reply is received for an entry that is not waiting for a reply,
+ *   the ARP reply packet is dropped and this trace is fired;
+ * - If an ARP reply is received for a non-existant entry, the ARP reply packet 
+ *   is dropped and this trace is fired;
+ * - If an ARP cache entry is in the DEAD state (has timed out) and an ARP reply
+ *   packet is received, the reply packet is dropped and this trace is fired.
+ * - Each ARP cache entry has a queue of pending packets.  If the size of the
+ *   queue is exceeded, the outbound packet is dropped and this trace is fired.
+ *
+ * \subsection internetStackIpv4TracingModel Tracing in IPv4
+ *
+ * The IPv4 layer three protocol provides three trace hooks.  These are the 
+ * "Tx" (ns3::Ipv4L3Protocol::m_txTrace), "Rx" (ns3::Ipv4L3Protocol::m_rxTrace) 
+ * and "Drop" (ns3::Ipv4L3Protocol::m_dropTrace) trace sources.
+ *
+ * The "Tx" trace is fired in a number of situations, all of which indicate that
+ * a given packet is about to be sent down to a given ns3::Ipv4Interface.
+ *
+ * - In the case of a packet destined for the broadcast address, the 
+ *   Ipv4InterfaceList is iterated and for every interface that is up and can
+ *   fragment the packet or has a large enough MTU to transmit the packet,
+ *   the trace is hit.  See ns3::Ipv4L3Protocol::Send.
+ *
+ * - In the case of a packet that needs routing, the "Tx" trace may be fired
+ *   just before a packet is sent to the interface appropriate to the default 
+ *   gateway.  See ns3::Ipv4L3Protocol::SendRealOut.
+ *
+ * - Also in the case of a packet that needs routing, the "Tx" trace may be 
+ *   fired just before a packet is sent to the outgoing interface appropriate
+ *   to the discovered route.  See ns3::Ipv4L3Protocol::SendRealOut.
+ *
+ * The "Rx" trace is fired when a packet is passed from the device up to the
+ * ns3::Ipv4L3Protocol::Receive function.
+ *
+ * - In the receive function, the Ipv4InterfaceList is iterated, and if the
+ *   Ipv4Interface corresponding to the receiving device is fount to be in the
+ *   UP state, the trace is fired.
+ *
+ * The "Drop" trace is fired in any case where the packet is dropped (in both
+ * the transmit and receive paths).
+ *
+ * - In the ns3::Ipv4Interface::Receive function, the packet is dropped and the
+ *   drop trace is hit if the interface corresponding to the receiving device
+ *   is in the DOWN state.
+ *
+ * - Also in the ns3::Ipv4Interface::Receive function, the packet is dropped and
+ *   the drop trace is hit if the checksum is found to be bad.
+ *
+ * - In ns3::Ipv4L3Protocol::Send, an outgoing packet bound for the broadcast
+ *   address is dropped and the "Drop" trace is fired if the "don't fragement"
+ *   bit is set and fragmentation is available and required.
+ *
+ * - Also in ns3::Ipv4L3Protocol::Send, an outgoing packet destined for the 
+ *   broadcast address is dropped and the "Drop" trace is hit if fragmentation
+ *   is not available and is required (MTU < packet size).
+ *
+ * - In the case of a broadcast address, an outgoing packet is cloned for each
+ *   outgoing interface.  If any of the interfaces is in the DOWN state, the 
+ *   "Drop" trace event fires with a reference to the copied packet.
+ *
+ * - In the case of a packet requiring a route, an outgoing packet is dropped
+ *   and the "Drop" trace event fires if no route to the remote host is found.
+ *
+ * - In ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed
+ *   is dropped and the "Drop" trace is fired if the "don't fragement" bit is 
+ *   set and fragmentation is available and required.
+ *
+ * - Also in ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed
+ *   is dropped and the "Drop" trace is hit if fragmentation is not available 
+ *   and is required (MTU < packet size).
+ *
+ * - An outgoing packet being routed is dropped and the "Drop" trace event fires
+ *   if the required Ipv4Interface is in the DOWN state.
+ *
+ * - If a packet is being forwarded, and the TTL is exceeded (see
+ *   ns3::Ipv4L3Protocol::DoForward), the packet is dropped and the "Drop" trace 
+ *   event is fired.
+ *
+ * \subsection internetStackNs3TCPTracingModel Tracing in ns-3 TCP
+ *
+ * There is currently one trace source in the ns-3 TCP implementation named
+ * "CongestionWindow" (see ns3::TcpSocketImpl::m_cWnd).  This is set in a number
+ * of places (see file tcp-socket-impl.cc) whenever the value of the congestion
+ * window is changed.
+ *
+ * \subsection internetStackNscTCPTracingModel Tracing in NSC TCP
+ *
+ * There is currently one trace source in the Network Simulation Cradle TCP 
+ * implementation named "CongestionWindow" (see ns3::NscTcpSocketImpl::m_cWnd).
+ * This is set in a number of places (see file nsc-tcp-socket-impl.cc) when 
+ * the value of the cogestion window is initially set.  Note that this is not
+ * instrumented from the underlying TCP implementaion.
+ *
+ * \subsection internetStackNs3UdpTracingModel Tracing in ns-3 UDP
+ *
+ * There is currently one trace source in the ns-3 UDP implementation named
+ * "Drop" (see ns3::UdpSocketImpl::m_dropTrace).  This is set when a packet
+ * is received in ns3::UdpSocketImpl::ForwardUp and the receive buffer cannot
+ * accomodate the encapsulated data.
  */
 
 #include "ns3/assert.h"
@@ -24,10 +154,16 @@
 #include "ns3/names.h"
 #include "ns3/ipv4.h"
 #include "internet-stack-helper.h"
-#include "ns3/internet-stack.h"
 #include "ns3/packet-socket-factory.h"
 #include "ns3/config.h"
 #include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/node.h"
+#include "ns3/core-config.h"
+#include "ns3/ipv4-list-routing-impl.h"
+#include "ns3/ipv4-static-routing-impl.h"
 #include <limits>
 
 namespace ns3 {
@@ -35,8 +171,9 @@
 std::vector<InternetStackHelper::Trace> InternetStackHelper::m_traces;
 std::string InternetStackHelper::m_pcapBaseFilename;
 
-InternetStackHelper::InternetStackHelper() : m_nscLibrary("")
+InternetStackHelper::InternetStackHelper ()
 {
+  SetTcp ("ns3::TcpL4Protocol");
 }
 
 void
@@ -55,9 +192,16 @@
 }
 
 void
-InternetStackHelper::SetNscStack(const std::string soname)
+InternetStackHelper::SetTcp (const std::string tid)
 {
-  m_nscLibrary = soname;
+  m_tcpFactory.SetTypeId (tid);
+}
+
+void 
+InternetStackHelper::SetTcp (std::string tid, std::string n0, const AttributeValue &v0)
+{
+  m_tcpFactory.SetTypeId (tid);
+  m_tcpFactory.Set (n0,v0);
 }
 
 void 
@@ -69,6 +213,15 @@
     }
 }
 
+static void
+CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId)
+{
+  ObjectFactory factory;
+  factory.SetTypeId(typeId);
+  Ptr<Object> protocol = factory.Create <Object> ();
+  node->AggregateObject (protocol);
+}
+
 void
 InternetStackHelper::Install (Ptr<Node> node) const
 {
@@ -79,17 +232,22 @@
       return;
     }
 
-  if (m_nscLibrary != "")
-    {
-      AddNscInternetStack (node, m_nscLibrary);
-    }
-  else
-    {
-      AddInternetStack (node);
-    }
-
+  CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
+  CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
+  CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
+  CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
+  node->AggregateObject (m_tcpFactory.Create<Object> ());
   Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
   node->AggregateObject (factory);
+  // Set routing
+  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+  // XXX cut this over to use of TypeIds and factories
+  Ptr<Ipv4ListRoutingImpl> ipv4RoutingImpl = CreateObject<Ipv4ListRoutingImpl> ();
+  Ptr<Ipv4StaticRoutingImpl> ipv4staticRoutingImpl = CreateObject<Ipv4StaticRoutingImpl> ();
+  ipv4staticRoutingImpl->SetNode (node);
+  ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0);
+  ipv4->SetRoutingProtocol (ipv4RoutingImpl);
+  ipv4RoutingImpl->SetNode (node);
 }
 
 void
--- a/src/helper/internet-stack-helper.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/internet-stack-helper.h	Sat May 30 17:37:38 2009 +0100
@@ -25,9 +25,13 @@
 #include "net-device-container.h"
 #include "ns3/pcap-writer.h"
 #include "ns3/packet.h"
+#include "ns3/ptr.h"
+#include "ns3/object-factory.h"
 
 namespace ns3 {
 
+class Node;
+
 /**
  * \brief aggregate IP/TCP/UDP functionality to existing Nodes.
  */
@@ -65,18 +69,32 @@
    */
   void Install (NodeContainer c) const;
 
+ /**
+   * \brief set the Tcp stack which will not need any other parameter.  
+   *
+   * This function sets up the tcp stack to the given TypeId. It should not be 
+   * used for NSC stack setup because the nsc stack needs the Library attribute
+   * to be setup, please use instead the version that requires an attribute
+   * and a value. If you choose to use this function anyways to set nsc stack
+   * the default value for the linux library will be used: "liblinux2.6.26.so".
+   *
+   * \param tid the type id, typically it is set to  "ns3::TcpL4Protocol"
+   */
+  void SetTcp(std::string tid);
+   
   /**
-   * \brief Enable or disable use of the Network Simulation Cradle stack.  
-   *
+   * \brief This function is used to setup the Network Simulation Cradle stack with library value.
+   * 
    * Give the NSC stack a shared library file name to use when creating the 
-   * statck implementation.  By providing a non-empty string as a parameter, you
-   * select the NSC version of the stack.  By providing an empty string, you 
-   * select the ns-3 default version.
-   *
-   * \param soname name of the shared library with the nsc tcp stack
-   * to use, e.g. 'liblinux2.6.26.so'.
+   * stack implementation.  The attr string is actually the attribute name to 
+   * be setup and val is its value. The attribute is the stack implementation 
+   * to be used and the value is the shared library name.
+   * 
+   * \param tid The type id, for the case of nsc it would be "ns3::NscTcpL4Protocol" 
+   * \param attr The attribute name that must be setup, for example "Library"
+   * \param val The attribute value, which will be in fact the shared library name (example:"liblinux2.6.26.so")
    */
-  void SetNscStack(std::string soname);
+  void SetTcp (std::string tid, std::string attr, const AttributeValue &val); 
 
   /**
    * \param os output stream
@@ -113,7 +131,7 @@
   static void EnablePcapAll (std::string filename);
 
 private:
-  std::string m_nscLibrary;
+  ObjectFactory m_tcpFactory;
   static void Cleanup (void);
   static void LogRxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
   static void LogTxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
--- a/src/helper/ipv4-address-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/ipv4-address-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -131,7 +131,7 @@
     Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
     NS_ASSERT_MSG (ipv4, "Ipv4AddressHelper::Allocate(): Bad ipv4");
 
-    int32_t interface = ipv4->FindInterfaceForDevice (device);
+    int32_t interface = ipv4->GetInterfaceForDevice (device);
     if (interface == -1)
       {
         interface = ipv4->AddInterface (device);
--- a/src/helper/ipv4-interface-container.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/ipv4-interface-container.h	Sat May 30 17:37:38 2009 +0100
@@ -41,7 +41,10 @@
   Ipv4Address GetAddress (uint32_t i, uint32_t j = 0) const;
 
   void SetMetric (uint32_t i, uint16_t metric);
-
+  /**
+   * \param ipv4 pointer to Ipv4 object
+   * \param interface interface index of the Ipv4Interface to add to the container
+   */
   void Add (Ptr<Ipv4> ipv4, uint32_t interface);
   void Add (std::string ipv4Name, uint32_t interface);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-static-routing-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,190 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <vector>
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/names.h"
+#include "ns3/node.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/ipv4-list-routing.h"
+#include "ns3/assert.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ipv4-static-routing-helper.h"
+
+NS_LOG_COMPONENT_DEFINE("Ipv4StaticRoutingHelper");
+
+namespace ns3 {
+
+Ptr<Ipv4StaticRouting>
+Ipv4StaticRoutingHelper::GetStaticRouting (Ptr<Ipv4> ipv4) const
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv4RoutingProtocol> ipv4rp = ipv4->GetRoutingProtocol ();
+  NS_ASSERT_MSG (ipv4rp, "No routing protocol associated with Ipv4");
+  if (DynamicCast<Ipv4StaticRouting> (ipv4rp))
+    {
+      NS_LOG_LOGIC ("Static routing found as the main IPv4 routing protocol.");
+      return DynamicCast<Ipv4StaticRouting> (ipv4rp); 
+    } 
+  if (DynamicCast<Ipv4ListRouting> (ipv4rp))
+    {
+      Ptr<Ipv4ListRouting> lrp = DynamicCast<Ipv4ListRouting> (ipv4rp);
+      int16_t priority;
+      for (uint32_t i = 0; i < lrp->GetNRoutingProtocols ();  i++)
+        {
+          NS_LOG_LOGIC ("Searching for static routing in list");
+          Ptr<Ipv4RoutingProtocol> temp = lrp->GetRoutingProtocol (i, priority);
+          if (DynamicCast<Ipv4StaticRouting> (temp))
+            {
+              NS_LOG_LOGIC ("Found static routing in list");
+              return DynamicCast<Ipv4StaticRouting> (temp);
+            }
+        }
+    }
+  NS_LOG_LOGIC ("Static routing not found");
+  return 0;
+}
+
+void  
+Ipv4StaticRoutingHelper::AddMulticastRoute (
+  Ptr<Node> n,
+  Ipv4Address source, 
+  Ipv4Address group,  
+  Ptr<NetDevice> input, 
+  NetDeviceContainer output)
+{
+  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
+
+  // We need to convert the NetDeviceContainer to an array of interface 
+  // numbers
+  std::vector<uint32_t> outputInterfaces;
+  for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i)
+    {
+      Ptr<NetDevice> nd = *i;
+      int32_t interface = ipv4->GetInterfaceForDevice (nd);
+      NS_ASSERT_MSG(interface >= 0, 
+        "Ipv4StaticRoutingHelper::AddMulticastRoute(): "
+        "Expected an interface associated with the device nd");
+      outputInterfaces.push_back(interface);
+    }
+
+  int32_t inputInterface = ipv4->GetInterfaceForDevice (input);
+  NS_ASSERT_MSG(inputInterface >= 0, 
+    "Ipv4StaticRoutingHelper::AddMulticastRoute(): "
+    "Expected an interface associated with the device input");
+  Ipv4StaticRoutingHelper helper;
+  Ptr<Ipv4StaticRouting> ipv4StaticRouting = helper.GetStaticRouting (ipv4);
+  if (!ipv4StaticRouting)
+    {
+  NS_ASSERT_MSG (ipv4StaticRouting, 
+    "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): "
+    "Expected an Ipv4StaticRouting associated with this node");
+    }
+  ipv4StaticRouting->AddMulticastRoute (source, group, inputInterface, outputInterfaces);
+}
+
+void  
+Ipv4StaticRoutingHelper::AddMulticastRoute (
+  Ptr<Node> n,
+  Ipv4Address source, 
+  Ipv4Address group,  
+  std::string inputName, 
+  NetDeviceContainer output)
+{
+  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+void  
+Ipv4StaticRoutingHelper::AddMulticastRoute (
+  std::string nName,
+  Ipv4Address source, 
+  Ipv4Address group,  
+  Ptr<NetDevice> input, 
+  NetDeviceContainer output)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+void  
+Ipv4StaticRoutingHelper::AddMulticastRoute (
+  std::string nName,
+  Ipv4Address source, 
+  Ipv4Address group,  
+  std::string inputName, 
+  NetDeviceContainer output)
+{
+  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
+  Ptr<Node> n = Names::Find<Node> (nName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+void
+Ipv4StaticRoutingHelper::SetDefaultMulticastRoute (
+  Ptr<Node> n, 
+  Ptr<NetDevice> nd)
+{
+  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
+  int32_t interfaceSrc = ipv4->GetInterfaceForDevice (nd);
+  NS_ASSERT_MSG(interfaceSrc >= 0, 
+    "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): "
+    "Expected an interface associated with the device");
+  Ipv4StaticRoutingHelper helper;
+  Ptr<Ipv4StaticRouting> ipv4StaticRouting = helper.GetStaticRouting (ipv4);
+  if (!ipv4StaticRouting)
+    {
+      NS_ASSERT_MSG (ipv4StaticRouting, 
+        "Ipv4StaticRoutingHelper::SetDefaultMulticastRoute(): "
+        "Expected an Ipv4StaticRouting associated with this node");
+    }
+  ipv4StaticRouting->SetDefaultMulticastRoute (interfaceSrc);
+}
+
+void
+Ipv4StaticRoutingHelper::SetDefaultMulticastRoute (
+  Ptr<Node> n, 
+  std::string ndName)
+{
+  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
+  SetDefaultMulticastRoute (n, nd);
+}
+
+void
+Ipv4StaticRoutingHelper::SetDefaultMulticastRoute (
+  std::string nName, 
+  Ptr<NetDevice> nd)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  SetDefaultMulticastRoute (n, nd);
+}
+
+void
+Ipv4StaticRoutingHelper::SetDefaultMulticastRoute (
+  std::string nName, 
+  std::string ndName)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
+  SetDefaultMulticastRoute (n, nd);
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-static-routing-helper.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,63 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IPV4_STATIC_ROUTING_HELPER_H
+#define IPV4_STATIC_ROUTING_HELPER_H
+
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-static-routing.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "node-container.h"
+#include "net-device-container.h"
+
+namespace ns3 {
+
+class Ipv4StaticRoutingHelper
+{
+public:
+  Ptr<Ipv4StaticRouting> GetStaticRouting (Ptr<Ipv4> ipv4) const;
+
+  void AddMulticastRoute (Ptr<Node> n, Ipv4Address source, Ipv4Address group,  
+    Ptr<NetDevice> input, NetDeviceContainer output);
+  void AddMulticastRoute (std::string n, Ipv4Address source, Ipv4Address group,  
+    Ptr<NetDevice> input, NetDeviceContainer output);
+  void AddMulticastRoute (Ptr<Node> n, Ipv4Address source, Ipv4Address group,  
+    std::string inputName, NetDeviceContainer output);
+  void AddMulticastRoute (std::string nName, Ipv4Address source, Ipv4Address group,  
+    std::string inputName, NetDeviceContainer output);
+
+  /**
+   * \brief Add a default route to the static routing protocol to forward
+   *        packets out a particular interface
+   *
+   * Functionally equivalent to:
+   * route add 224.0.0.0 netmask 240.0.0.0 dev nd
+   */
+  void SetDefaultMulticastRoute (Ptr<Node> n, Ptr<NetDevice> nd);
+  void SetDefaultMulticastRoute (Ptr<Node> n, std::string ndName);
+  void SetDefaultMulticastRoute (std::string nName, Ptr<NetDevice> nd);
+  void SetDefaultMulticastRoute (std::string nName, std::string ndName);
+
+};
+
+} // namespace ns3
+
+#endif /* IPV4_STATIC_ROUTING_HELPER_H */
--- a/src/helper/olsr-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/olsr-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -21,6 +21,7 @@
 #include "ns3/olsr-routing-protocol.h"
 #include "ns3/node-list.h"
 #include "ns3/names.h"
+#include "ns3/ipv4-list-routing.h"
 
 namespace ns3 {
 
@@ -72,7 +73,9 @@
   Ptr<olsr::RoutingProtocol> agent = m_agentFactory.Create<olsr::RoutingProtocol> ();
   node->AggregateObject (agent);
   Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-  ipv4->AddRoutingProtocol (agent, 10);
+  Ptr<Ipv4ListRouting> ipv4Routing = DynamicCast<Ipv4ListRouting> (ipv4->GetRoutingProtocol ());
+  NS_ASSERT (ipv4Routing);
+  ipv4Routing->AddRoutingProtocol (agent, 10);
   agent->SetNode (node);
   agent->Start ();
 }
--- a/src/helper/packet-sink-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/packet-sink-helper.cc	Sat May 30 17:37:38 2009 +0100
@@ -38,22 +38,6 @@
   m_factory.Set (name, value);
 }
 
-
-#if 0
-void 
-PacketSinkHelper::SetUdpLocal (Ipv4Address ip, uint16_t port)
-{
-  m_factory.Set ("Protocol", String ("ns3::UdpSocketFactory"));
-  m_factory.Set ("Local", Address (InetSocketAddress (ip, port)));
-}
-void 
-PacketSinkHelper::SetTcpLocal (Ipv4Address ip, uint16_t port)
-{
-  m_factory.Set ("Protocol", String ("ns3::TcpSocketFactory"));
-  m_factory.Set ("Local", Address (InetSocketAddress (ip, port)));
-}
-#endif
-
 ApplicationContainer
 PacketSinkHelper::Install (Ptr<Node> node) const
 {
--- a/src/helper/static-multicast-route-helper.cc	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 University of Washington
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Tom Henderson <tomhend@u.washington.edu>
- */
-
-#include <vector>
-#include "ns3/ptr.h"
-#include "ns3/assert.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4.h"
-#include "ns3/names.h"
-#include "static-multicast-route-helper.h"
-
-namespace ns3 {
-
-StaticMulticastRouteHelper::StaticMulticastRouteHelper ()
-{
-}
-
-void  
-StaticMulticastRouteHelper::AddMulticastRoute (
-  Ptr<Node> n,
-  Ipv4Address source, 
-  Ipv4Address group,  
-  Ptr<NetDevice> input, 
-  NetDeviceContainer output)
-{
-  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
-
-  // We need to convert the NetDeviceContainer to an array of interface
-  std::vector<uint32_t> outputInterfaces;
-  for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i)
-    {
-      Ptr<NetDevice> nd = *i;
-      uint32_t ointerface = ipv4->FindInterfaceForDevice (nd);
-      outputInterfaces.push_back(ointerface);
-    }
-  uint32_t iinterface = ipv4->FindInterfaceForDevice (input);
-  ipv4->AddMulticastRoute (source, group, iinterface, outputInterfaces);
-}
-
-void  
-StaticMulticastRouteHelper::AddMulticastRoute (
-  Ptr<Node> n,
-  Ipv4Address source, 
-  Ipv4Address group,  
-  std::string inputName, 
-  NetDeviceContainer output)
-{
-  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
-  AddMulticastRoute (n, source, group, input, output);
-}
-
-void  
-StaticMulticastRouteHelper::AddMulticastRoute (
-  std::string nName,
-  Ipv4Address source, 
-  Ipv4Address group,  
-  Ptr<NetDevice> input, 
-  NetDeviceContainer output)
-{
-  Ptr<Node> n = Names::Find<Node> (nName);
-  AddMulticastRoute (n, source, group, input, output);
-}
-
-void  
-StaticMulticastRouteHelper::AddMulticastRoute (
-  std::string nName,
-  Ipv4Address source, 
-  Ipv4Address group,  
-  std::string inputName, 
-  NetDeviceContainer output)
-{
-  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
-  Ptr<Node> n = Names::Find<Node> (nName);
-  AddMulticastRoute (n, source, group, input, output);
-}
-
-void
-StaticMulticastRouteHelper::SetDefaultMulticastRoute (
-  Ptr<Node> n, 
-  Ptr<NetDevice> nd)
-{
-  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
-  uint32_t interfaceSrc = ipv4->FindInterfaceForDevice (nd);
-  ipv4->SetDefaultMulticastRoute (interfaceSrc);
-}
-
-void
-StaticMulticastRouteHelper::SetDefaultMulticastRoute (
-  Ptr<Node> n, 
-  std::string ndName)
-{
-  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
-  SetDefaultMulticastRoute (n, nd);
-}
-
-void
-StaticMulticastRouteHelper::SetDefaultMulticastRoute (
-  std::string nName, 
-  Ptr<NetDevice> nd)
-{
-  Ptr<Node> n = Names::Find<Node> (nName);
-  SetDefaultMulticastRoute (n, nd);
-}
-
-void
-StaticMulticastRouteHelper::SetDefaultMulticastRoute (
-  std::string nName, 
-  std::string ndName)
-{
-  Ptr<Node> n = Names::Find<Node> (nName);
-  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
-  SetDefaultMulticastRoute (n, nd);
-}
-
-void
-StaticMulticastRouteHelper::JoinMulticastGroup (
-  Ptr<Node> n, 
-  Ipv4Address source, 
-  Ipv4Address group)
-{
-  Ptr<Ipv4> ipv4 = n->GetObject<Ipv4> ();
-  ipv4->JoinMulticastGroup (source, group);
-}
-
-void
-StaticMulticastRouteHelper::JoinMulticastGroup (
-  std::string nName, 
-  Ipv4Address source, 
-  Ipv4Address group)
-{
-  Ptr<Node> n = Names::Find<Node> (nName);
-  JoinMulticastGroup (n, source, group);
-}
-
-} // namespace ns3
-
--- a/src/helper/static-multicast-route-helper.h	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2008 University of Washington
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Tom Henderson <tomhend@u.washington.edu>
- */
-#ifndef STATIC_MULTICAST_ROUTE_HELPER_H
-#define STATIC_MULTICAST_ROUTE_HELPER_H
-
-#include "ns3/ptr.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/node.h"
-#include "ns3/net-device.h"
-#include "node-container.h"
-#include "net-device-container.h"
-
-namespace ns3 {
-
-class StaticMulticastRouteHelper
-{
-public:
-  StaticMulticastRouteHelper ();
-
-  void AddMulticastRoute (Ptr<Node> n, Ipv4Address source, Ipv4Address group,  
-    Ptr<NetDevice> input, NetDeviceContainer output);
-  void AddMulticastRoute (std::string n, Ipv4Address source, Ipv4Address group,  
-    Ptr<NetDevice> input, NetDeviceContainer output);
-  void AddMulticastRoute (Ptr<Node> n, Ipv4Address source, Ipv4Address group,  
-    std::string inputName, NetDeviceContainer output);
-  void AddMulticastRoute (std::string nName, Ipv4Address source, Ipv4Address group,  
-    std::string inputName, NetDeviceContainer output);
-
-  void SetDefaultMulticastRoute (Ptr<Node> n, Ptr<NetDevice> nd);
-  void SetDefaultMulticastRoute (Ptr<Node> n, std::string ndName);
-  void SetDefaultMulticastRoute (std::string nName, Ptr<NetDevice> nd);
-  void SetDefaultMulticastRoute (std::string nName, std::string ndName);
-
-  void JoinMulticastGroup (Ptr<Node> n, Ipv4Address source, Ipv4Address group);
-  void JoinMulticastGroup (std::string nName, Ipv4Address source, Ipv4Address group);
-};
-
-} // namespace ns3
-
-#endif /* STATIC_MULTICAST_ROUTE_HELPER_H */
--- a/src/helper/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/wscript	Sat May 30 17:37:38 2009 +0100
@@ -7,12 +7,12 @@
         'net-device-container.cc',
         'wifi-helper.cc',
         'olsr-helper.cc',
-        'static-multicast-route-helper.cc',
         'point-to-point-helper.cc',
         'csma-helper.cc',
         'mobility-helper.cc',
         'ns2-mobility-helper.cc',
         'ipv4-address-helper.cc',
+        'ipv4-static-routing-helper.cc',
         'internet-stack-helper.cc',
         'application-container.cc',
         'on-off-helper.cc',
@@ -34,12 +34,12 @@
         'net-device-container.h',
         'wifi-helper.h',
         'olsr-helper.h',
-        'static-multicast-route-helper.h',
         'point-to-point-helper.h',
         'csma-helper.h',
         'mobility-helper.h',
         'ns2-mobility-helper.h',
         'ipv4-address-helper.h',
+        'ipv4-static-routing-helper.h',
         'internet-stack-helper.h',
         'application-container.h',
         'on-off-helper.h',
--- a/src/helper/yans-wifi-helper.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/helper/yans-wifi-helper.h	Sat May 30 17:37:38 2009 +0100
@@ -125,7 +125,7 @@
 };
 
 /**
- * \brief Make it easy to create and manager PHY objects for the yans model.
+ * \brief Make it easy to create and manage PHY objects for the yans model.
  *
  * The yans PHY model is described in "Yet Another Network Simulator", 
  * http://cutebugs.net/files/wns2-yans.pdf
--- a/src/internet-stack/arp-ipv4-interface.cc	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: 
- *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-
-#include "ns3/packet.h"
-#include "ns3/log.h"
-#include "ns3/node.h"
-#include "ns3/net-device.h"
-#include "ns3/address.h"
-#include "ns3/pointer.h"
-
-#include "arp-ipv4-interface.h"
-#include "ipv4-l3-protocol.h"
-#include "arp-l3-protocol.h"
-#include "arp-cache.h"
-
-NS_LOG_COMPONENT_DEFINE ("ArpIpv4Interface");
-
-namespace ns3 {
-
-TypeId 
-ArpIpv4Interface::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::ArpIpv4Interface")
-    .SetParent<Ipv4Interface> ()
-    .AddAttribute ("ArpCache",
-                   "The arp cache for this ipv4 interface",
-                   PointerValue (0),
-                   MakePointerAccessor (&ArpIpv4Interface::m_cache),
-                   MakePointerChecker<ArpIpv4Interface> ())
-    ;
-  return tid;
-}
-
-ArpIpv4Interface::ArpIpv4Interface ()
-  : m_node (0),
-    m_device (0)
-{
-  NS_LOG_FUNCTION (this);
-}
-
-ArpIpv4Interface::~ArpIpv4Interface ()
-{
-  NS_LOG_FUNCTION (this);
-}
-
-void 
-ArpIpv4Interface::DoDispose (void)
-{
-  NS_LOG_FUNCTION (this);
-  m_device = 0;
-  m_cache = 0;
-  Ipv4Interface::DoDispose ();
-}
-
-void 
-ArpIpv4Interface::SetNode (Ptr<Node> node)
-{
-  m_node = node;
-  DoSetup ();
-}
-void 
-ArpIpv4Interface::SetDevice (Ptr<NetDevice> device)
-{
-  m_device = device;
-  DoSetup ();
-}
-
-Ptr<NetDevice> 
-ArpIpv4Interface::GetDevice (void) const
-{
-  return m_device;
-}
-
-void
-ArpIpv4Interface::DoSetup (void)
-{
-  if (m_node == 0 || m_device == 0)
-    {
-      return;
-    }
-  Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
-  m_cache = arp->CreateCache (m_device, this);
-}
-
-void 
-ArpIpv4Interface::SendTo (Ptr<Packet> p, Ipv4Address dest)
-{
-  NS_LOG_FUNCTION (this << p << dest);
-
-  NS_ASSERT (GetDevice () != 0);
-  // XXX multi-address case
-  if (dest == GetAddress (0).GetLocal ())
-    {
-      Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
-        
-      ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, 
-                     GetDevice ()->GetBroadcast (),
-                     GetDevice ()->GetBroadcast (),
-                     NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
-                     );
-      return;
-    }
-  if (m_device->NeedsArp ())
-    {
-      NS_LOG_LOGIC ("Needs ARP");
-      Ptr<ArpL3Protocol> arp = 
-        m_node->GetObject<ArpL3Protocol> ();
-      Address hardwareDestination;
-      bool found;
-      // XXX multi-address case
-      if (dest.IsBroadcast () || 
-          dest.IsSubnetDirectedBroadcast (GetAddress (0).GetMask ()) )
-        {
-          NS_LOG_LOGIC ("IsBroadcast");
-          hardwareDestination = GetDevice ()->GetBroadcast ();
-          found = true;
-        }
-      else if (dest.IsMulticast ())
-        {
-          NS_LOG_LOGIC ("IsMulticast");
-          NS_ASSERT_MSG(GetDevice ()->IsMulticast (),
-            "ArpIpv4Interface::SendTo (): Sending multicast packet over "
-            "non-multicast device");
-
-          hardwareDestination = GetDevice ()->GetMulticast(dest);
-          found = true;
-        }
-      else
-        {
-          NS_LOG_LOGIC ("ARP Lookup");
-          found = arp->Lookup (p, dest, GetDevice (), m_cache, &hardwareDestination);
-        }
-
-      if (found)
-        {
-          NS_LOG_LOGIC ("Address Resolved.  Send.");
-          GetDevice ()->Send (p, hardwareDestination, 
-            Ipv4L3Protocol::PROT_NUMBER);
-        }
-    }
-  else
-    {
-      NS_LOG_LOGIC ("Doesn't need ARP");
-      GetDevice ()->Send (p, GetDevice ()->GetBroadcast (), 
-        Ipv4L3Protocol::PROT_NUMBER);
-    }
-}
-
-}//namespace ns3
--- a/src/internet-stack/arp-ipv4-interface.h	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: 
- *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-#ifndef ARP_IPV4_INTERFACE_H
-#define ARP_IPV4_INTERFACE_H
-
-#include "ipv4-interface.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Node;
-class ArpCache;
-
-/**
- * \ingroup arp
- * \brief an Ipv4 Interface which uses ARP
- *
- * If you need to use ARP on top of a specific NetDevice, you
- * can use this Ipv4Interface subclass to wrap it for the Ipv4 class
- * when calling Ipv4::AggregateObject.
- */
-class ArpIpv4Interface : public Ipv4Interface
-{
-public:
-  static TypeId GetTypeId (void);
-
-  ArpIpv4Interface ();
-  virtual ~ArpIpv4Interface ();
-
-  void SetNode (Ptr<Node> node);
-  void SetDevice (Ptr<NetDevice> device);
-
-  virtual Ptr<NetDevice> GetDevice (void) const;
-
-private:
-  virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
-  virtual void DoDispose (void);
-  void DoSetup (void);
-  Ptr<Node> m_node;
-  Ptr<NetDevice> m_device;
-  Ptr<ArpCache> m_cache;
-};
-
-}//namespace ns3
-
-
-#endif /* ARP_IPV4_INTERFACE_H */
--- a/src/internet-stack/arp-l3-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/arp-l3-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -43,6 +43,7 @@
 {
   static TypeId tid = TypeId ("ns3::ArpL3Protocol")
     .SetParent<Object> ()
+    .AddConstructor<ArpL3Protocol> ()
     .AddAttribute ("CacheList",
                    "The list of ARP caches",
                    ObjectVectorValue (),
@@ -72,6 +73,23 @@
   m_node = node;
 }
 
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the ipv4 stack
+ */
+void
+ArpL3Protocol::NotifyNewAggregate ()
+{
+  Ptr<Node>node = this->GetObject<Node> ();
+  //verify that it's a valid node and that
+  //the node was not set before
+  if (node!= 0 && m_node == 0)
+    {
+      this->SetNode (node);
+    }
+  Object::NotifyNewAggregate ();
+}
+
 void 
 ArpL3Protocol::DoDispose (void)
 {
--- a/src/internet-stack/arp-l3-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/arp-l3-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -78,6 +78,11 @@
 	       Address *hardwareDestination);
 protected:
   virtual void DoDispose (void);
+  /*
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
 private:
   typedef std::list<Ptr<ArpCache> > CacheList;
   Ptr<ArpCache> FindCache (Ptr<NetDevice> device);
--- a/src/internet-stack/icmpv4-l4-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/icmpv4-l4-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -1,4 +1,5 @@
 #include "icmpv4-l4-protocol.h"
+#include "ipv4-raw-socket-factory-impl.h"
 #include "ipv4-interface.h"
 #include "ipv4-l3-protocol.h"
 #include "ns3/assert.h"
@@ -6,6 +7,7 @@
 #include "ns3/node.h"
 #include "ns3/packet.h"
 #include "ns3/boolean.h"
+#include "ns3/ipv4-route.h"
 
 namespace ns3 {
 
@@ -47,6 +49,27 @@
   m_node = node;
 }
 
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the ICMP stack and adding ICMP factory to
+ * IPv4 stack connected to the node
+ */
+void
+Icmpv4L4Protocol::NotifyNewAggregate ()
+{
+  bool is_not_initialized = (m_node == 0);
+  Ptr<Node>node = this->GetObject<Node> ();
+  Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+  if (is_not_initialized && node!= 0 && ipv4 != 0)
+    {
+      this->SetNode (node);
+      ipv4->Insert (this);
+      Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
+      ipv4->AggregateObject (rawFactory);
+    }
+  Object::NotifyNewAggregate ();
+}
+
 uint16_t 
 Icmpv4L4Protocol::GetStaticProtocolNumber (void)
 {
@@ -62,19 +85,27 @@
 Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
 {
   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
-  uint32_t i;
-  if (!ipv4->GetInterfaceForDestination (dest, i))
+  NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0);
+  Ipv4Header header;
+  header.SetDestination (dest);
+  Socket::SocketErrno errno;
+  Ptr<Ipv4Route> route;
+  uint32_t oif = 0; //specify non-zero if bound to a source address
+  route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+  if (route != 0)
+    {
+      NS_LOG_LOGIC ("Route exists");
+     Ipv4Address source = route->GetSource ();
+     SendMessage (packet, source, dest, type, code, route);
+    }
+  else
     {
       NS_LOG_WARN ("drop icmp message");
-      return;
     }
-  // XXX handle multi-address case
-  Ipv4Address source = ipv4->GetAddress (i, 0).GetLocal ();
-  SendMessage (packet, source, dest, type, code);
 }
 
 void
-Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code)
+Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr<Ipv4Route> route)
 {
   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
   Icmpv4Header icmp;
@@ -85,7 +116,7 @@
       icmp.EnableChecksum ();
     }
   packet->AddHeader (icmp);
-  ipv4->Send (packet, source, dest, ICMP_PROTOCOL);
+  ipv4->Send (packet, source, dest, ICMP_PROTOCOL, route);
 }
 void 
 Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header, 
@@ -140,7 +171,7 @@
   Icmpv4Echo echo;
   p->RemoveHeader (echo);
   reply->AddHeader (echo);
-  SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0);
+  SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0, 0);
 }
 void
 Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp,
--- a/src/internet-stack/icmpv4-l4-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/icmpv4-l4-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -9,6 +9,7 @@
 
 class Node;
 class Ipv4Interface;
+class Ipv4Route;
 
 class Icmpv4L4Protocol : public Ipv4L4Protocol
 {
@@ -29,7 +30,12 @@
   void SendDestUnreachFragNeeded (Ipv4Header header, Ptr<const Packet> orgData, uint16_t nextHopMtu);
   void SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData);
   void SendDestUnreachPort (Ipv4Header header, Ptr<const Packet> orgData);
-
+protected:
+  /*
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
 private:
   void HandleEcho (Ptr<Packet> p,
 		   Icmpv4Header header, 
@@ -46,7 +52,7 @@
   void SendDestUnreach (Ipv4Header header, Ptr<const Packet> orgData, 
 			uint8_t code, uint16_t nextHopMtu);
   void SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code);
-  void SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code);
+  void SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr<Ipv4Route> route);
   void Forward (Ipv4Address source, Icmpv4Header icmp,
 		uint32_t info, Ipv4Header ipHeader,
 		const uint8_t payload[8]);
--- a/src/internet-stack/internet-stack.cc	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//
-
-#include "ns3/net-device.h"
-#include "ns3/callback.h"
-#include "ns3/node.h"
-#include "ns3/core-config.h"
-
-#include "udp-l4-protocol.h"
-#include "tcp-l4-protocol.h"
-#include "ipv4-l3-protocol.h"
-#include "arp-l3-protocol.h"
-#include "udp-socket-factory-impl.h"
-#include "tcp-socket-factory-impl.h"
-#include "ipv4-raw-socket-factory-impl.h"
-#include "icmpv4-l4-protocol.h"
-#ifdef NETWORK_SIMULATION_CRADLE
-#include "nsc-tcp-socket-factory-impl.h"
-#include "nsc-tcp-l4-protocol.h"
-#endif
-
-namespace ns3 {
-
-static void
-AddArpStack (Ptr<Node> node)
-{
-  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
-  arp->SetNode (node);
-  node->AggregateObject (arp);
-}
-
-static void
-AddUdpStack(Ptr<Node> node)
-{
-  Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
-  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);
-}
-
-static void
-AddIcmpStack (Ptr<Node> node)
-{
-  Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
-  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
-  icmp->SetNode (node);
-  ipv4->Insert (icmp);
-  node->AggregateObject (icmp);
-
-  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
-  node->AggregateObject (rawFactory);
-}
-
-static void
-AddTcpStack(Ptr<Node> node)
-{
-  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);
-  node->AggregateObject (tcpFactory);
-}
-
-static void
-AddIpv4Stack(Ptr<Node> node)
-{
-  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
-  ipv4->SetNode (node);
-  node->AggregateObject (ipv4);
-}
-
-void
-AddInternetStack (Ptr<Node> node)
-{
-  AddArpStack (node);
-  AddIpv4Stack (node);
-  AddIcmpStack (node);
-  AddUdpStack (node);
-  AddTcpStack (node);
-}
-
-#ifdef NETWORK_SIMULATION_CRADLE
-static void
-AddNscStack(Ptr<Node> node, const std::string &soname)
-{
-  Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
-  Ptr<NscTcpL4Protocol> tcp = CreateObject<NscTcpL4Protocol> ();
-  tcp->SetNscLibrary(soname);
-  tcp->SetNode (node);
-  ipv4->Insert (tcp);
-  node->AggregateObject (tcp);
-
-  Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
-  tcpFactory->SetTcp (tcp);
-  node->AggregateObject (tcpFactory);
-}
-
-
-void
-AddNscInternetStack (Ptr<Node> node, const std::string &soname)
-{
-  AddArpStack (node);
-  AddIpv4Stack (node);
-  AddIcmpStack (node);
-  AddUdpStack (node);
-  AddNscStack (node, soname);
-}
-#else
-void
-AddNscInternetStack (Ptr<Node> node, const std::string &soname)
-{
-  NS_FATAL_ERROR ("NSC Not enabled on this platform.");
-}
-#endif
-}//namespace ns3
--- a/src/internet-stack/internet-stack.h	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-
-#ifndef INTERNET_STACK_H
-#define INTERNET_STACK_H
-
-#include "ns3/ptr.h"
-
-/**
- * \ingroup internetStack
- * \defgroup internetStackModel Internet Stack Model
- *
- * \section internetStackTracingModel Tracing in the Internet Stack
- *
- * The internet stack provides a number of trace sources in its various
- * protocol implementations.  These trace sources can be hooked using your own 
- * custom trace code, or you can use our helper functions in some cases to 
- * arrange for tracing to be enabled.
- *
- * \subsection internetStackArpTracingModel Tracing in ARP
- *
- * ARP provides two trace hooks, one in the cache, and one in the layer three
- * protocol.  The trace accessor in the cache is given the name "Drop."  When
- * a packet is transmitted over an interface that requires ARP, it is first
- * queued for transmission in the ARP cache until the required MAC address is
- * resolved.  There are a number of retries that may be done trying to get the 
- * address, and if the maximum retry count is exceeded the packet in question 
- * is dropped by ARP.  The single trace hook in the ARP cache is called,
- *
- * - If an outbound packet is placed in the ARP cache pending address resolution
- *   and no resolution can be made within the maximum retry count, the outbound 
- *   packet is dropped and this trace is fired;
- *
- * A second trace hook lives in the ARP L3 protocol (also named "Drop") and may 
- * be called for a  number of reasons.
- *
- * - If an ARP reply is received for an entry that is not waiting for a reply,
- *   the ARP reply packet is dropped and this trace is fired;
- * - If an ARP reply is received for a non-existant entry, the ARP reply packet 
- *   is dropped and this trace is fired;
- * - If an ARP cache entry is in the DEAD state (has timed out) and an ARP reply
- *   packet is received, the reply packet is dropped and this trace is fired.
- * - Each ARP cache entry has a queue of pending packets.  If the size of the
- *   queue is exceeded, the outbound packet is dropped and this trace is fired.
- *
- * \subsection internetStackIpv4TracingModel Tracing in IPv4
- *
- * The IPv4 layer three protocol provides three trace hooks.  These are the 
- * "Tx" (ns3::Ipv4L3Protocol::m_txTrace), "Rx" (ns3::Ipv4L3Protocol::m_rxTrace) 
- * and "Drop" (ns3::Ipv4L3Protocol::m_dropTrace) trace sources.
- *
- * The "Tx" trace is fired in a number of situations, all of which indicate that
- * a given packet is about to be sent down to a given ns3::Ipv4Interface.
- *
- * - In the case of a packet destined for the broadcast address, the 
- *   Ipv4InterfaceList is iterated and for every interface that is up and can
- *   fragment the packet or has a large enough MTU to transmit the packet,
- *   the trace is hit.  See ns3::Ipv4L3Protocol::Send.
- *
- * - In the case of a packet that needs routing, the "Tx" trace may be fired
- *   just before a packet is sent to the interface appropriate to the default 
- *   gateway.  See ns3::Ipv4L3Protocol::SendRealOut.
- *
- * - Also in the case of a packet that needs routing, the "Tx" trace may be 
- *   fired just before a packet is sent to the outgoing interface appropriate
- *   to the discovered route.  See ns3::Ipv4L3Protocol::SendRealOut.
- *
- * The "Rx" trace is fired when a packet is passed from the device up to the
- * ns3::Ipv4L3Protocol::Receive function.
- *
- * - In the receive function, the Ipv4InterfaceList is iterated, and if the
- *   Ipv4Interface corresponding to the receiving device is fount to be in the
- *   UP state, the trace is fired.
- *
- * The "Drop" trace is fired in any case where the packet is dropped (in both
- * the transmit and receive paths).
- *
- * - In the ns3::Ipv4Interface::Receive function, the packet is dropped and the
- *   drop trace is hit if the interface corresponding to the receiving device
- *   is in the DOWN state.
- *
- * - Also in the ns3::Ipv4Interface::Receive function, the packet is dropped and
- *   the drop trace is hit if the checksum is found to be bad.
- *
- * - In ns3::Ipv4L3Protocol::Send, an outgoing packet bound for the broadcast
- *   address is dropped and the "Drop" trace is fired if the "don't fragement"
- *   bit is set and fragmentation is available and required.
- *
- * - Also in ns3::Ipv4L3Protocol::Send, an outgoing packet destined for the 
- *   broadcast address is dropped and the "Drop" trace is hit if fragmentation
- *   is not available and is required (MTU < packet size).
- *
- * - In the case of a broadcast address, an outgoing packet is cloned for each
- *   outgoing interface.  If any of the interfaces is in the DOWN state, the 
- *   "Drop" trace event fires with a reference to the copied packet.
- *
- * - In the case of a packet requiring a route, an outgoing packet is dropped
- *   and the "Drop" trace event fires if no route to the remote host is found.
- *
- * - In ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed
- *   is dropped and the "Drop" trace is fired if the "don't fragement" bit is 
- *   set and fragmentation is available and required.
- *
- * - Also in ns3::Ipv4L3Protocol::SendRealOut, an outgoing packet being routed
- *   is dropped and the "Drop" trace is hit if fragmentation is not available 
- *   and is required (MTU < packet size).
- *
- * - An outgoing packet being routed is dropped and the "Drop" trace event fires
- *   if the required Ipv4Interface is in the DOWN state.
- *
- * - If a packet is being forwarded, and the TTL is exceeded (see
- *   ns3::Ipv4L3Protocol::DoForward), the packet is dropped and the "Drop" trace 
- *   event is fired.
- *
- * \subsection internetStackNs3TCPTracingModel Tracing in ns-3 TCP
- *
- * There is currently one trace source in the ns-3 TCP implementation named
- * "CongestionWindow" (see ns3::TcpSocketImpl::m_cWnd).  This is set in a number
- * of places (see file tcp-socket-impl.cc) whenever the value of the congestion
- * window is changed.
- *
- * \subsection internetStackNscTCPTracingModel Tracing in NSC TCP
- *
- * There is currently one trace source in the Network Simulation Cradle TCP 
- * implementation named "CongestionWindow" (see ns3::NscTcpSocketImpl::m_cWnd).
- * This is set in a number of places (see file nsc-tcp-socket-impl.cc) when 
- * the value of the cogestion window is initially set.  Note that this is not
- * instrumented from the underlying TCP implementaion.
- *
- * \subsection internetStackNs3UdpTracingModel Tracing in ns-3 UDP
- *
- * There is currently one trace source in the ns-3 UDP implementation named
- * "Drop" (see ns3::UdpSocketImpl::m_dropTrace).  This is set when a packet
- * is received in ns3::UdpSocketImpl::ForwardUp and the receive buffer cannot
- * accomodate the encapsulated data.
- */
-
-namespace ns3 {
-
-class Node;
-
-void AddInternetStack (Ptr<Node> node);
-void AddNscInternetStack (Ptr<Node> node, const std::string &soname);
-
-}//namespace ns3
-
-#endif /* INTERNET_STACK_H */
--- a/src/internet-stack/ipv4-global-routing.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-global-routing.cc	Sat May 30 17:37:38 2009 +0100
@@ -18,9 +18,11 @@
 
 #include "ns3/log.h"
 #include "ns3/object.h"
-#include "ipv4-global-routing.h"
 #include "ns3/packet.h"
 #include "ns3/node.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/ipv4-routing-table-entry.h"
+#include "ipv4-global-routing.h"
 
 NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting");
 
@@ -42,14 +44,19 @@
   NS_LOG_FUNCTION_NOARGS ();
 }
 
+Ipv4GlobalRouting::~Ipv4GlobalRouting ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
 void 
 Ipv4GlobalRouting::AddHostRouteTo (Ipv4Address dest, 
                                    Ipv4Address nextHop, 
                                    uint32_t interface)
 {
   NS_LOG_FUNCTION (dest << nextHop << interface);
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, nextHop, interface);
   m_hostRoutes.push_back (route);
 }
 
@@ -58,8 +65,8 @@
                                    uint32_t interface)
 {
   NS_LOG_FUNCTION (dest << interface);
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, interface);
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, interface);
   m_hostRoutes.push_back (route);
 }
 
@@ -70,8 +77,8 @@
                                       uint32_t interface)
 {
   NS_LOG_FUNCTION (network << networkMask << nextHop << interface);
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
                                             networkMask,
                                             nextHop,
                                             interface);
@@ -84,17 +91,21 @@
                                       uint32_t interface)
 {
   NS_LOG_FUNCTION (network << networkMask << interface);
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
                                             networkMask,
                                             interface);
   m_networkRoutes.push_back (route);
 }
 
-Ipv4Route *
+Ptr<Ipv4Route>
 Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest)
 {
   NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv4Route> rtentry = 0;
+  bool found = false;
+  Ipv4RoutingTableEntry* route = 0;
+
   for (HostRoutesCI i = m_hostRoutes.begin (); 
        i != m_hostRoutes.end (); 
        i++) 
@@ -103,23 +114,45 @@
       if ((*i)->GetDest ().IsEqual (dest)) 
         {
           NS_LOG_LOGIC ("Found global host route" << *i); 
-          return (*i);
+          route = (*i);
+          found = true; 
+          break;
         }
     }
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
+  if (found == false)
     {
-      NS_ASSERT ((*j)->IsNetwork ());
-      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
-      Ipv4Address entry = (*j)->GetDestNetwork ();
-      if (mask.IsMatch (dest, entry)) 
+      for (NetworkRoutesI j = m_networkRoutes.begin (); 
+           j != m_networkRoutes.end (); 
+           j++) 
         {
-          NS_LOG_LOGIC ("Found global network route" << *j); 
-          return (*j);
+          NS_ASSERT ((*j)->IsNetwork ());
+          Ipv4Mask mask = (*j)->GetDestNetworkMask ();
+          Ipv4Address entry = (*j)->GetDestNetwork ();
+          if (mask.IsMatch (dest, entry)) 
+            {
+              NS_LOG_LOGIC ("Found global network route" << *j); 
+              route = (*j);
+              found = true;
+              break;
+            }
         }
     }
-  return 0;
+  if (found == true)
+    {
+      Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+      rtentry = Create<Ipv4Route> ();
+      rtentry->SetDestination (route->GetDest ());
+      // XXX handle multi-address case
+      rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
+      rtentry->SetGateway (route->GetGateway ());
+      uint32_t interfaceIdx = route->GetInterface ();
+      rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx));
+      return rtentry;
+    }
+  else 
+    {
+      return 0;
+    }
 }
 
 uint32_t 
@@ -132,7 +165,7 @@
   return n;
 }
 
-Ipv4Route *
+Ipv4RoutingTableEntry *
 Ipv4GlobalRouting::GetRoute (uint32_t index)
 {
   NS_LOG_FUNCTION (index);
@@ -207,70 +240,6 @@
   NS_ASSERT (false);
 }
 
-bool
-Ipv4GlobalRouting::RequestRoute (
-  uint32_t interface,
-  Ipv4Header const &ipHeader,
-  Ptr<Packet> packet,
-  RouteReplyCallback routeReply)
-{
-  NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
-
-  NS_LOG_LOGIC ("source = " << ipHeader.GetSource ());
-
-  NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ());
-
-  if (ipHeader.GetDestination ().IsMulticast ())
-    {
-      NS_LOG_LOGIC ("Multicast destination-- returning false");
-      return false; // Let other routing protocols try to handle this
-    }
-
-// This is a unicast packet.  Check to see if we have a route for it.
-//
-  NS_LOG_LOGIC ("Unicast destination- looking up");
-  Ipv4Route *route = LookupGlobal (ipHeader.GetDestination ());
-  if (route != 0)
-    {
-      routeReply (true, *route, packet, ipHeader);
-      return true;
-    }
-  else
-    {
-      return false; // Let other routing protocols try to handle this
-                    // route request.
-    }
-}
-
-bool
-Ipv4GlobalRouting::RequestInterface (Ipv4Address destination, uint32_t& interface)
-{
-  NS_LOG_FUNCTION (this << destination << &interface);
-//
-// First, see if this is a multicast packet we have a route for.  If we
-// have a route, then send the packet down each of the specified interfaces.
-//
-  if (destination.IsMulticast ())
-    {
-      NS_LOG_LOGIC ("Multicast destination-- returning false");
-      return false; // Let other routing protocols try to handle this
-    }
-//
-// See if this is a unicast packet we have a route for.
-//
-  NS_LOG_LOGIC ("Unicast destination- looking up");
-  Ipv4Route *route = LookupGlobal (destination);
-  if (route)
-    {
-      interface = route->GetInterface ();
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
 void
 Ipv4GlobalRouting::DoDispose (void)
 {
@@ -290,4 +259,80 @@
   Ipv4RoutingProtocol::DoDispose ();
 }
 
+Ptr<Ipv4Route>
+Ipv4GlobalRouting::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
+{      
+
+//
+// First, see if this is a multicast packet we have a route for.  If we
+// have a route, then send the packet down each of the specified interfaces.
+//
+  if (header.GetDestination().IsMulticast ())
+    {
+      NS_LOG_LOGIC ("Multicast destination-- returning false");
+      return 0; // Let other routing protocols try to handle this
+    }
+//
+// See if this is a unicast packet we have a route for.
+//
+  NS_LOG_LOGIC ("Unicast destination- looking up");
+  Ptr<Ipv4Route> rtentry = LookupGlobal (header.GetDestination());
+  if (rtentry)
+    {
+      sockerr = Socket::ERROR_NOTERROR;
+    }
+  else
+    {
+      sockerr = Socket::ERROR_NOROUTETOHOST;
+    }
+  return rtentry;
+}
+
+bool 
+Ipv4GlobalRouting::RouteInput  (Ptr<const Packet> p, const Ipv4Header &ipHeader, Ptr<const NetDevice> idev,                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb) 
+{ 
+
+  NS_LOG_FUNCTION (this << p << ipHeader << ipHeader.GetSource () << ipHeader.GetDestination () << idev);
+
+  if (ipHeader.GetDestination ().IsMulticast ())
+    {
+      NS_LOG_LOGIC ("Multicast destination-- returning false");
+      return false; // Let other routing protocols try to handle this
+    }
+
+// This is a unicast packet.  Check to see if we have a route for it.
+//
+  NS_LOG_LOGIC ("Unicast destination- looking up");
+  Ptr<Ipv4Route> rtentry = LookupGlobal (ipHeader.GetDestination ());
+  if (rtentry != 0)
+    {
+      NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
+      ucb (rtentry, p, ipHeader);
+      return true;
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Did not find unicast destination- returning false");
+      return false; // Let other routing protocols try to handle this
+                    // route request.
+    }
+}
+
+void
+Ipv4GlobalRouting::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = node;
+}
+
+Ptr<Node>
+Ipv4GlobalRouting::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+
+
 }//namespace ns3
--- a/src/internet-stack/ipv4-global-routing.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-global-routing.h	Sat May 30 17:37:38 2009 +0100
@@ -26,6 +26,7 @@
 #include "ns3/ipv4-header.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv4-routing-protocol.h"
 
 namespace ns3 {
 
@@ -34,12 +35,13 @@
 class Ipv4Interface;
 class Ipv4Address;
 class Ipv4Header;
-class Ipv4Route;
+class Ipv4RoutingTableEntry;
+class Ipv4MulticastRoutingTableEntry;
 class Node;
 
 
 /**
- * @brief Global routing protocol for IP version 4 stacks.
+ * \brief Global routing protocol for IP version 4 stacks.
  *
  * In ns-3 we have the concept of a pluggable routing protocol.  Routing
  * protocols are added to a list maintained by the Ipv4L3Protocol.  Every 
@@ -60,126 +62,65 @@
  *
  * This class deals with Ipv4 unicast routes only.
  *
- * @see Ipv4RoutingProtocol
- * @see GlobalRouteManager
+ * \see Ipv4RoutingProtocol
+ * \see GlobalRouteManager
  */
 class Ipv4GlobalRouting : public Ipv4RoutingProtocol
 {
 public:
   static TypeId GetTypeId (void);
 /**
- * @brief Construct an empty Ipv4GlobalRouting routing protocol,
+ * \brief Construct an empty Ipv4GlobalRouting routing protocol,
  *
  * The Ipv4GlobalRouting class supports host and network unicast routes.
  * This method initializes the lists containing these routes to empty.
  *
- * @see Ipv4GlobalRouting
+ * \see Ipv4GlobalRouting
  */
   Ipv4GlobalRouting ();
+  virtual ~Ipv4GlobalRouting ();
 
-/**
- * @brief Request that a check for a route bw performed and if a route is found
- * that the packet be sent on its way using the pre-packaged send callback.
- *
- * The source and destination IP addresses for the packet in question are found
- * in the provided Ipv4Header.  There are two major processing forks depending
- * on the type of destination address.  
- *
- * If the destination address is unicast then the routing table is consulted 
- * for a route to the destination and if it is found, the routeReply callback
- * is executed to send the packet (with the found route).
- * 
- * If the destination address is a multicast, then the method will return
- * false.
- *
- * @param interface The network interface index over which the packed was 
- * received.  If the packet is from a local source, interface will be set to
- * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY.
- * @param ipHeader the Ipv4Header containing the source and destination IP
- * addresses for the packet.
- * @param packet The packet to be sent if a route is found.
- * @param routeReply A callback that packaged up the call to actually send the
- * packet.
- * @return Returns true if a route is found and the packet has been sent,
- * otherwise returns false indicating that the next routing protocol should
- * be consulted.  
- *
- * @see Ipv4GlobalRouting
- * @see Ipv4RoutingProtocol
- */
-  virtual bool RequestRoute (uint32_t interface,
-                             Ipv4Header const &ipHeader,
-                             Ptr<Packet> packet,
-                             RouteReplyCallback routeReply);
+  virtual Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+
+  virtual bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb);
 
 /**
- * @brief Check to see if we can determine the interface index that will be
- * used if a packet is sent to this destination.
- *
- * This method addresses a problem in the IP stack where a destination address
- * must be present and checksummed into the IP header before the actual 
- * interface over which the packet is sent can be determined.  The answer is
- * to implement a known and intentional cross-layer violation.  This is the
- * endpoint of a call chain that started up quite high in the stack (sockets)
- * and has found its way down to the Ipv4L3Protocol which is consulting the
- * routing protocols for what they would do if presented with a packet of the
- * given destination.
- *
- * If there are multiple paths out of the node, the resolution is performed
- * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more 
- * contextual information that is useful for making a determination.
- *
- * This method will return false on a multicast address.
+ * \brief Add a host route to the global routing table.
  *
- * @param destination The Ipv4Address if the destination of a hypothetical 
- * packet.  This may be a multicast group address.
- * @param interface A reference to the interface index over which a packet
- * sent to this destination would be sent.
- * @return Returns true if a route is found to the destination that involves
- * a single output interface index, otherwise returns false indicating that
- * the next routing protocol should be consulted.  
- *
- * @see Ipv4GlobalRouting
- * @see Ipv4RoutingProtocol
- * @see Ipv4L3Protocol
- */
-  virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface);
-
-/**
- * @brief Add a host route to the global routing table.
- *
- * @param dest The Ipv4Address destination for this route.
- * @param nextHop The Ipv4Address of the next hop in the route.
- * @param interface The network interface index used to send packets to the
+ * \param dest The Ipv4Address destination for this route.
+ * \param nextHop The Ipv4Address of the next hop in the route.
+ * \param interface The network interface index used to send packets to the
  * destination.
  *
- * @see Ipv4Address
+ * \see Ipv4Address
  */
   void AddHostRouteTo (Ipv4Address dest, 
                        Ipv4Address nextHop, 
                        uint32_t interface);
 /**
- * @brief Add a host route to the global routing table.
+ * \brief Add a host route to the global routing table.
  *
- * @param dest The Ipv4Address destination for this route.
- * @param interface The network interface index used to send packets to the
+ * \param dest The Ipv4Address destination for this route.
+ * \param interface The network interface index used to send packets to the
  * destination.
  *
- * @see Ipv4Address
+ * \see Ipv4Address
  */
   void AddHostRouteTo (Ipv4Address dest, 
                        uint32_t interface);
 
 /**
- * @brief Add a network route to the global routing table.
+ * \brief Add a network route to the global routing table.
  *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param nextHop The next hop in the route to the destination network.
- * @param interface The network interface index used to send packets to the
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param nextHop The next hop in the route to the destination network.
+ * \param interface The network interface index used to send packets to the
  * destination.
  *
- * @see Ipv4Address
+ * \see Ipv4Address
  */
   void AddNetworkRouteTo (Ipv4Address network, 
                           Ipv4Mask networkMask, 
@@ -187,29 +128,29 @@
                           uint32_t interface);
 
 /**
- * @brief Add a network route to the global routing table.
+ * \brief Add a network route to the global routing table.
  *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param interface The network interface index used to send packets to the
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param interface The network interface index used to send packets to the
  * destination.
  *
- * @see Ipv4Address
+ * \see Ipv4Address
  */
   void AddNetworkRouteTo (Ipv4Address network, 
                           Ipv4Mask networkMask, 
                           uint32_t interface);
 
 /**
- * @brief Get the number of individual unicast routes that have been added
+ * \brief Get the number of individual unicast routes that have been added
  * to the routing table.
  *
- * @warning The default route counts as one of the routes.
+ * \warning The default route counts as one of the routes.
  */
   uint32_t GetNRoutes (void);
 
 /**
- * @brief Get a route from the global unicast routing table.
+ * \brief Get a route from the global unicast routing table.
  *
  * Externally, the unicast global routing table appears simply as a table with
  * n entries.  The one sublety of note is that if a default route has been set
@@ -220,18 +161,18 @@
  * Similarly, if the default route has been set, calling RemoveRoute (0) will
  * remove the default route.
  *
- * @param i The index (into the routing table) of the route to retrieve.  If
+ * \param i The index (into the routing table) of the route to retrieve.  If
  * the default route has been set, it will occupy index zero.
- * @return If route is set, a pointer to that Ipv4Route is returned, otherwise
+ * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise
  * a zero pointer is returned.
  *
- * @see Ipv4Route
- * @see Ipv4GlobalRouting::RemoveRoute
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4GlobalRouting::RemoveRoute
  */
-  Ipv4Route *GetRoute (uint32_t i);
+  Ipv4RoutingTableEntry *GetRoute (uint32_t i);
 
 /**
- * @brief Remove a route from the global unicast routing table.
+ * \brief Remove a route from the global unicast routing table.
  *
  * Externally, the unicast global routing table appears simply as a table with
  * n entries.  The one sublety of note is that if a default route has been set
@@ -239,30 +180,35 @@
  * default route has been set, calling RemoveRoute (0) will remove the
  * default route.
  *
- * @param i The index (into the routing table) of the route to remove.  If
+ * \param i The index (into the routing table) of the route to remove.  If
  * the default route has been set, it will occupy index zero.
  *
- * @see Ipv4Route
- * @see Ipv4GlobalRouting::GetRoute
- * @see Ipv4GlobalRouting::AddRoute
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4GlobalRouting::GetRoute
+ * \see Ipv4GlobalRouting::AddRoute
  */
   void RemoveRoute (uint32_t i);
 
+  void SetNode (Ptr<Node> node);
+  Ptr<Node> GetNode (void) const;
+
 protected:
   void DoDispose (void);
 
 private:
-  typedef std::list<Ipv4Route *> HostRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator HostRoutesI;
-  typedef std::list<Ipv4Route *> NetworkRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
+  typedef std::list<Ipv4RoutingTableEntry *> HostRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator HostRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator HostRoutesI;
+  typedef std::list<Ipv4RoutingTableEntry *> NetworkRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator NetworkRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator NetworkRoutesI;
 
-  Ipv4Route *LookupGlobal (Ipv4Address dest);
+  Ptr<Ipv4Route> LookupGlobal (Ipv4Address dest);
 
   HostRoutes m_hostRoutes;
   NetworkRoutes m_networkRoutes;
+
+  Ptr<Node> m_node;
 };
 
 } // Namespace ns3
--- a/src/internet-stack/ipv4-interface.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-interface.cc	Sat May 30 17:37:38 2009 +0100
@@ -19,10 +19,16 @@
  */
 
 #include "ipv4-interface.h"
+#include "loopback-net-device.h"
 #include "ns3/ipv4-address.h"
+#include "ipv4-l3-protocol.h"
+#include "arp-l3-protocol.h"
+#include "arp-cache.h"
 #include "ns3/net-device.h"
 #include "ns3/log.h"
 #include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/pointer.h"
 
 NS_LOG_COMPONENT_DEFINE ("Ipv4Interface");
 
@@ -33,19 +39,27 @@
 {
   static TypeId tid = TypeId ("ns3::Ipv4Interface")
     .SetParent<Object> ()
+    .AddAttribute ("ArpCache",
+                   "The arp cache for this ipv4 interface",
+                   PointerValue (0),
+                   MakePointerAccessor (&Ipv4Interface::m_cache),
+                   MakePointerChecker<Ipv4Interface> ())
+    ;
     ;
   return tid;
 }
 
-  /**
-   * By default, Ipv4 interface are created in the "down" state
-   * with ip address 192.168.0.1 and a matching mask. Before
-   * becoming useable, the user must invoke SetUp on them
-   * once the final Ipv4 address and mask has been set.
-   */
+/** 
+ * By default, Ipv4 interface are created in the "down" state
+ *  with no IP addresses.  Before becoming useable, the user must 
+ * invoke SetUp on them once an Ipv4 address and mask have been set.
+ */
 Ipv4Interface::Ipv4Interface () 
-  : m_ifup(false),
-    m_metric(1)
+  : m_ifup (false),
+    m_metric (1),
+    m_node (0), 
+    m_device (0),
+    m_cache (0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -59,9 +73,46 @@
 Ipv4Interface::DoDispose (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  m_device = 0;
   Object::DoDispose ();
 }
 
+void 
+Ipv4Interface::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+  DoSetup ();
+}
+
+void 
+Ipv4Interface::SetDevice (Ptr<NetDevice> device)
+{
+  m_device = device;
+  DoSetup ();
+}
+
+void
+Ipv4Interface::DoSetup (void)
+{
+  if (m_node == 0 || m_device == 0)
+    {
+      return;
+    }
+  if (!m_device->NeedsArp ())
+    {
+      return;
+    }
+  Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
+  m_cache = arp->CreateCache (m_device, this);
+}
+
+Ptr<NetDevice>
+Ipv4Interface::GetDevice (void) const
+{
+  return m_device;
+}
+
 void
 Ipv4Interface::SetMetric (uint16_t metric)
 {
@@ -80,12 +131,7 @@
 Ipv4Interface::GetMtu (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
-  if (GetDevice () == 0)
-    {
-      uint32_t mtu = (1<<16) - 1;
-      return mtu;
-    }
-  return GetDevice ()->GetMtu ();
+  return m_device->GetMtu ();
 }
 
 /**
@@ -121,15 +167,92 @@
   m_ifup = false;
 }
 
-// public wrapper on private virtual function
-void 
-Ipv4Interface::Send(Ptr<Packet> p, Ipv4Address dest)
+void
+Ipv4Interface::Send (Ptr<Packet> p, Ipv4Address dest)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  if (IsUp()) {
-    NS_LOG_LOGIC ("SendTo");
-    SendTo(p, dest);
-  }
+  if (!IsUp()) 
+    {
+      return;
+    }
+  // Check for a loopback device
+  if (DynamicCast<LoopbackNetDevice> (m_device))
+    {
+      // XXX additional checks needed here (such as whether multicast
+      // goes to loopback)?
+      m_device->Send (p, m_device->GetBroadcast (), 
+                      Ipv4L3Protocol::PROT_NUMBER);
+      return;
+    } 
+  // is this packet aimed at a local interface ?
+  for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i)
+    {
+      if (dest == (*i).GetLocal ())
+        {
+          Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+        
+          ipv4->Receive (0, p, Ipv4L3Protocol::PROT_NUMBER, 
+                         m_device->GetBroadcast (),
+                         m_device->GetBroadcast (),
+                         NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
+                         );
+          return;
+        }
+    }
+  if (m_device->NeedsArp ())
+    {
+      NS_LOG_LOGIC ("Needs ARP" << " " << dest);
+      Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
+      Address hardwareDestination;
+      bool found = false;
+      if (dest.IsBroadcast ())
+        {
+          NS_LOG_LOGIC ("All-network Broadcast");
+          hardwareDestination = m_device->GetBroadcast ();
+          found = true;
+        }
+      else if (dest.IsMulticast ())
+        {
+          NS_LOG_LOGIC ("IsMulticast");
+          NS_ASSERT_MSG(m_device->IsMulticast (),
+            "ArpIpv4Interface::SendTo (): Sending multicast packet over "
+            "non-multicast device");
+
+          hardwareDestination = m_device->GetMulticast(dest);
+          found = true;
+        }
+      else
+        {
+          for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i)
+            {
+              if (dest.IsSubnetDirectedBroadcast ((*i).GetMask ()))
+                {
+                  NS_LOG_LOGIC ("Subnetwork Broadcast");
+                  hardwareDestination = m_device->GetBroadcast ();
+                  found = true;
+                  break;
+                }
+            }
+          if (!found)
+            {
+              NS_LOG_LOGIC ("ARP Lookup");
+              found = arp->Lookup (p, dest, m_device, m_cache, &hardwareDestination);
+            }
+        }
+
+      if (found)
+        {
+          NS_LOG_LOGIC ("Address Resolved.  Send.");
+          m_device ->Send (p, hardwareDestination, 
+                              Ipv4L3Protocol::PROT_NUMBER);
+        }
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Doesn't need ARP");
+      m_device->Send (p, m_device->GetBroadcast (), 
+                      Ipv4L3Protocol::PROT_NUMBER);
+    }
 }
 
 uint32_t
--- a/src/internet-stack/ipv4-interface.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-interface.h	Sat May 30 17:37:38 2009 +0100
@@ -32,6 +32,8 @@
 
 class NetDevice;
 class Packet;
+class Node;
+class ArpCache;
 
 /**
  * \brief The IPv4 representation of a network interface
@@ -40,26 +42,9 @@
  * of Linux; the main purpose is to provide address-family
  * specific information (addresses) about an interface.
  *
- * This class defines two APIs:
- *  - the public API which is expected to be used by both 
- *    the IPv4 layer and the user during forwarding and 
- *    configuration.
- *  - the private API which is expected to be implemented
- *    by subclasses of this base class. One such subclass 
- *    will be a Loopback interface which loops every
- *    packet sent back to the ipv4 layer. Another such 
- *    subclass typically contains the Ipv4 <-> MAC address
- *    translation logic which will use most of the time the
- *    ARP/RARP protocols.
- *
  * By default, Ipv4 interface are created in the "down" state
- * with ip address 192.168.0.1 and a matching mask. Before
- * becoming useable, the user must invoke SetUp on them
- * once the final Ipv4 address and mask has been set.
- *
- * Subclasses must implement the two methods:
- *   - Ipv4Interface::SendTo
- *   - Ipv4Interface::GetDevice
+ * no IP addresses.  Before becoming useable, the user must 
+ * add an address of some type and invoke Setup on them.
  */
 class Ipv4Interface  : public Object
 {
@@ -69,18 +54,29 @@
   Ipv4Interface ();
   virtual ~Ipv4Interface();
 
+  void SetNode (Ptr<Node> node); 
+  void SetDevice (Ptr<NetDevice> device);
+
   /**
-   * \returns the underlying NetDevice. This method can return
-   *          zero if this interface has no associated NetDevice.
+   * \returns the underlying NetDevice. This method cannot return zero.
    */
-  virtual Ptr<NetDevice> GetDevice (void) const = 0;
+  Ptr<NetDevice> GetDevice (void) const;
 
   /**
    * \param metric configured routing metric (cost) of this interface
+   *
+   * Note:  This is synonymous to the Metric value that ifconfig prints
+   * out.  It is used by ns-3 global routing, but other routing daemons
+   * choose to ignore it. 
    */
   void SetMetric (uint16_t metric);
+
   /**
    * \returns configured routing metric (cost) of this interface
+   *
+   * Note:  This is synonymous to the Metric value that ifconfig prints
+   * out.  It is used by ns-3 global routing, but other routing daemons 
+   * may choose to ignore it. 
    */
   uint16_t GetMetric (void) const;
 
@@ -88,6 +84,8 @@
    * This function a pass-through to NetDevice GetMtu, modulo
    * the  LLC/SNAP header i.e., ipv4MTU = NetDeviceMtu - LLCSNAPSIZE
    * \returns the Maximum Transmission Unit associated to this interface.
+   *
+   * XXX deprecated?  This is duplicate API to GetDevice ()->GetMtu ()
    */
   uint16_t GetMtu (void) const;
 
@@ -100,14 +98,17 @@
    * \returns true if this interface is enabled, false otherwise.
    */
   bool IsUp (void) const;
+
   /**
    * \returns true if this interface is disabled, false otherwise.
    */
   bool IsDown (void) const;
+
   /**
    * Enable this interface
    */
   void SetUp (void);
+
   /**
    * Disable this interface
    */
@@ -147,16 +148,19 @@
 protected:
   virtual void DoDispose (void);
 private:
-  virtual void SendTo (Ptr<Packet> p, Ipv4Address dest) = 0;
-  bool m_ifup;
-  uint16_t m_metric;
-
+  void DoSetup (void);
   typedef std::list<Ipv4InterfaceAddress> Ipv4InterfaceAddressList;
   typedef std::list<Ipv4InterfaceAddress>::const_iterator Ipv4InterfaceAddressListCI;
   typedef std::list<Ipv4InterfaceAddress>::iterator Ipv4InterfaceAddressListI;
+
+  bool m_ifup;
+  uint16_t m_metric;
   Ipv4InterfaceAddressList m_ifaddrs;
+  Ptr<Node> m_node;
+  Ptr<NetDevice> m_device;
+  Ptr<ArpCache> m_cache; 
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif
--- a/src/internet-stack/ipv4-l3-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -31,14 +31,16 @@
 #include "ns3/object-vector.h"
 #include "ns3/ipv4-header.h"
 #include "ns3/boolean.h"
+#include "ns3/ipv4-routing-table-entry.h"
+#include "ns3/ipv4-static-routing.h"
+
+#include "loopback-net-device.h"
 #include "arp-l3-protocol.h"
-
 #include "ipv4-l3-protocol.h"
 #include "ipv4-l4-protocol.h"
+#include "ipv4-list-routing-impl.h"
 #include "icmpv4-l4-protocol.h"
 #include "ipv4-interface.h"
-#include "ipv4-loopback-interface.h"
-#include "arp-ipv4-interface.h"
 #include "ipv4-raw-socket-impl.h"
 
 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
@@ -83,8 +85,6 @@
     m_identification (0)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  m_staticRouting = CreateObject<Ipv4StaticRouting> ();
-  AddRoutingProtocol (m_staticRouting, 0);
 }
 
 Ipv4L3Protocol::~Ipv4L3Protocol ()
@@ -119,6 +119,7 @@
 Ipv4L3Protocol::SetNode (Ptr<Node> node)
 {
   m_node = node;
+  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
   SetupLoopback ();
 }
 
@@ -145,18 +146,48 @@
     }
   return;
 }
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the ipv4 stack
+ */
+void
+Ipv4L3Protocol::NotifyNewAggregate ()
+{
+  Ptr<Node>node = this->GetObject<Node>();
+  // verify that it's a valid node and that
+  // the node has not been set before
+  if (node!= 0 && m_node == 0)
+    {
+      this->SetNode (node);
+    }
+  Object::NotifyNewAggregate ();
+}
+
+void 
+Ipv4L3Protocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routing)
+{
+  NS_LOG_FUNCTION (this);
+  m_routingProtocol = routing;
+  // XXX should check all interfaces to see if any were set to Up state
+  // prior to a routing protocol being added
+  if (GetStaticRouting () != 0)
+    {
+      GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), 0);
+    }
+}
+
+
+Ptr<Ipv4RoutingProtocol> 
+Ipv4L3Protocol::GetRoutingProtocol (void) const
+{
+  return m_routingProtocol;
+}
 
 void 
 Ipv4L3Protocol::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
- 
-  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
-    {
-      *i = 0;
-    }
-
- for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+  for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
     {
       *i = 0;
     }
@@ -167,10 +198,12 @@
       *i = 0;
     }
   m_interfaces.clear ();
-  m_routingProtocols.clear ();
   m_node = 0;
-  m_staticRouting->Dispose ();
-  m_staticRouting = 0;
+  if (m_routingProtocol)
+    {
+      m_routingProtocol->Dispose ();
+      m_routingProtocol = 0;
+    }
   Object::DoDispose ();
 }
 
@@ -179,12 +212,33 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
+  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
+  Ptr<LoopbackNetDevice> device = 0;
+  // First check whether an existing LoopbackNetDevice exists on the node
+  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
+    {
+      if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
+        {
+          break;
+        }
+    }
+  if (device == 0)
+    {
+      device = CreateObject<LoopbackNetDevice> (); 
+      m_node->AddDevice (device);
+    }
+  interface->SetDevice (device);
   interface->SetNode (m_node);
   Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
   interface->AddAddress (ifaceAddr);
   uint32_t index = AddIpv4Interface (interface);
-  AddHostRouteTo (Ipv4Address::GetLoopback (), index);
+  Ptr<Node> node = GetObject<Node> ();
+  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), 
+                                 Ipv4L3Protocol::PROT_NUMBER, device);
+  if (GetStaticRouting () != 0)
+    {
+      GetStaticRouting ()->AddHostRouteTo (Ipv4Address::GetLoopback (), index);
+    }
   interface->SetUp ();
 }
 
@@ -195,192 +249,24 @@
   m_defaultTtl = ttl;
 }
     
-
-void 
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
-                      Ipv4Address nextHop, 
-                      uint32_t interface)
-{
-  NS_LOG_FUNCTION (this << dest << nextHop << interface);
-  m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
-}
-
-void 
-Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
-				uint32_t interface)
-{
-  NS_LOG_FUNCTION (this << dest << interface);
-  m_staticRouting->AddHostRouteTo (dest, interface);
-}
-
-void 
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
-				   Ipv4Mask networkMask, 
-				   Ipv4Address nextHop, 
-				   uint32_t interface)
-{
-  NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
-  m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
-}
-
-void 
-Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
-				   Ipv4Mask networkMask, 
-				   uint32_t interface)
-{
-  NS_LOG_FUNCTION (this << network << networkMask << interface);
-  m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
-}
-
-void 
-Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, 
-				 uint32_t interface)
-{
-  NS_LOG_FUNCTION (this << nextHop << interface);
-  m_staticRouting->SetDefaultRoute (nextHop, interface);
-}
-
-void
-Ipv4L3Protocol::Lookup (
-  Ipv4Header const &ipHeader,
-  Ptr<Packet> packet,
-  Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
-  NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
-
-  Lookup (Ipv4RoutingProtocol::INTERFACE_ANY, ipHeader, packet, routeReply);
-}
-
-void
-Ipv4L3Protocol::Lookup (
-  uint32_t interface,
-  Ipv4Header const &ipHeader,
-  Ptr<Packet> packet,
-  Ipv4RoutingProtocol::RouteReplyCallback routeReply)
-{
-  NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
-
-  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = 
-         m_routingProtocols.begin ();
-       rprotoIter != m_routingProtocols.end (); 
-       rprotoIter++)
-    {
-      NS_LOG_LOGIC ("Requesting route");
-      if ((*rprotoIter).second->RequestRoute (interface, ipHeader, packet, 
-                                              routeReply))
-        return;
-    }
-
-  if (ipHeader.GetDestination ().IsMulticast () && 
-      interface == Ipv4RoutingProtocol::INTERFACE_ANY)
-    {
-      NS_LOG_LOGIC ("Multicast destination with local source");
-//
-// We have a multicast packet originating from the current node and were not
-// able to send it using the usual RequestRoute process.  Since the usual
-// process includes trying to use a default multicast route, this means that
-// there was no specific route out of the node found, and there was no default
-// multicast route set.
-//
-// The fallback position is to look for a default unicast route and use that
-// to get the packet off the node if we have one.
-//
-      Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
-      if (route)
-        {
-          NS_LOG_LOGIC ("Local source. Using unicast default route for "
-            "multicast packet");
-
-          routeReply (true, *route, packet, ipHeader);
-          return;
-        }
-    }
-//
-// No route found
-//
-  routeReply (false, Ipv4Route (), packet, ipHeader);
-}
-
-void
-Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
-                                    int16_t priority)
-{
-  NS_LOG_FUNCTION (this << &routingProtocol << priority);
-  m_routingProtocols.push_back
-    (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
-  m_routingProtocols.sort ();
-}
-
-uint32_t 
-Ipv4L3Protocol::GetNRoutes (void)
+// XXX need to remove dependencies on Ipv4StaticRouting from this class
+Ptr<Ipv4StaticRouting>
+Ipv4L3Protocol::GetStaticRouting (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
-  return m_staticRouting->GetNRoutes ();
-}
-
-Ipv4Route 
-Ipv4L3Protocol::GetRoute (uint32_t index)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return *m_staticRouting->GetRoute (index);
-}
-
-void 
-Ipv4L3Protocol::RemoveRoute (uint32_t index)
-{
-  NS_LOG_FUNCTION (this << index);
-  m_staticRouting->RemoveRoute (index);
-}
-
-void 
-Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
-                                   Ipv4Address group,
-                                   uint32_t inputInterface,
-                                   std::vector<uint32_t> outputInterfaces)
-{
-  NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
-
-  m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
-    outputInterfaces);
-}
-
-void 
-Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
-{
-  NS_LOG_FUNCTION (this << outputInterface);
-
-  m_staticRouting->SetDefaultMulticastRoute (outputInterface);
-}
-
-uint32_t 
-Ipv4L3Protocol::GetNMulticastRoutes (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_staticRouting->GetNMulticastRoutes ();
-}
-
-Ipv4MulticastRoute 
-Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
-{
-  NS_LOG_FUNCTION (this << index);
-  return *m_staticRouting->GetMulticastRoute (index);
-}
-
-void 
-Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
-                                       Ipv4Address group,
-                                       uint32_t inputInterface)
-{
-  NS_LOG_FUNCTION (this << origin << group << inputInterface);
-  m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
-}
-
-void 
-Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
-{
-  NS_LOG_FUNCTION (this << index);
-  m_staticRouting->RemoveMulticastRoute (index);
+  Ptr<Ipv4StaticRouting> staticRouting;
+  if (m_routingProtocol != 0)
+    {
+      Ptr<Ipv4StaticRoutingImpl> sr = DynamicCast<Ipv4StaticRoutingImpl> (m_routingProtocol);
+      if (sr != 0)
+        {
+          return sr;
+        }
+      Ptr<Ipv4ListRoutingImpl> lr = DynamicCast<Ipv4ListRoutingImpl> (m_routingProtocol);
+      NS_ASSERT (lr);
+      staticRouting = lr->GetStaticRouting ();
+    }
+  return staticRouting;
 }
 
 uint32_t 
@@ -394,7 +280,7 @@
   node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
                                  ArpL3Protocol::PROT_NUMBER, device);
 
-  Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
+  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
   interface->SetNode (m_node);
   interface->SetDevice (device);
   return AddIpv4Interface (interface);
@@ -433,60 +319,60 @@
   return m_nInterfaces;
 }
 
-uint32_t 
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
+int32_t 
+Ipv4L3Protocol::GetInterfaceForAddress (
+  Ipv4Address address) const
 {
-  NS_LOG_FUNCTION (this << addr);
+  NS_LOG_FUNCTION (this << address);
 
-  uint32_t interface = 0;
+  int32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
        i++, interface++)
     {
-      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++) 
+      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
         {
-          if ((*i)->GetAddress (j).GetLocal () == addr)
+          if ((*i)->GetAddress (j).GetLocal () == address)
             {
               return interface;
             }
         }
     }
 
-  NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
-                  "Interface not found for IP address " << addr);
-  return 0;
+  return -1;
 }
 
-uint32_t 
-Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
+int32_t 
+Ipv4L3Protocol::GetInterfaceForPrefix (
+  Ipv4Address address, 
+  Ipv4Mask mask) const
 {
-  NS_LOG_FUNCTION (this << addr << mask);
+  NS_LOG_FUNCTION (this << address << mask);
 
-  uint32_t interface = 0;
+  int32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
        i++, interface++)
     {
       for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
         {
-          if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == addr.CombineMask (mask))
+          if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
             {
               return interface;
             }
         }
     }
 
-  NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
-    "Interface not found for masked IP address");
-  return 0;
+  return -1;
 }
 
 int32_t 
-Ipv4L3Protocol::FindInterfaceForDevice (Ptr<NetDevice> device) const
+Ipv4L3Protocol::GetInterfaceForDevice (
+  Ptr<const NetDevice> device) const
 {
-  NS_LOG_FUNCTION (this << device);
+  NS_LOG_FUNCTION (this << device->GetIfIndex());
 
-  uint32_t interface = 0;
+  int32_t interface = 0;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
        i++, interface++)
@@ -500,31 +386,18 @@
   return -1;
 }
 
-Ptr<Ipv4Interface>
-Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
-{
-  NS_LOG_FUNCTION (this << &device);
-  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
-    {
-      if ((*i)->GetDevice () == device)
-        {
-          return *i;
-        }
-    }
-  return 0;
-}  
-
 void 
 Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
                          const Address &to, NetDevice::PacketType packetType)
 {
   NS_LOG_FUNCTION (this << &device << p << protocol <<  from);
 
-  NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
+  NS_LOG_LOGIC ("Packet from " << from << " received on node " << 
+    m_node->GetId ());
 
+  uint32_t interface = 0;
   Ptr<Packet> packet = p->Copy ();
 
-  uint32_t index = 0;
   Ptr<Ipv4Interface> ipv4Interface;
   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
        i != m_interfaces.end (); 
@@ -535,9 +408,9 @@
         {
           if (ipv4Interface->IsUp ())
             {
-              m_rxTrace (packet, index);
+              m_rxTrace (packet, interface);
               break;
-            } 
+            }
           else
             {
               NS_LOG_LOGIC ("Dropping received packet-- interface is down");
@@ -545,8 +418,9 @@
               return;
             }
         }
-      index++;
+      interface++;
     }
+
   Ipv4Header ipHeader;
   if (m_calcChecksum)
     {
@@ -566,12 +440,13 @@
       socket->ForwardUp (packet, ipHeader, device);
     }
 
-  if (Forwarding (index, packet, ipHeader, device)) 
-    {
-      return;
-    }
+  m_routingProtocol->RouteInput (packet, ipHeader, device, 
+    MakeCallback (&Ipv4L3Protocol::IpForward, this),
+    MakeCallback (&Ipv4L3Protocol::IpMulticastForward, this),
+    MakeCallback (&Ipv4L3Protocol::LocalDeliver, this),
+    MakeNullCallback <void, Ptr<const Packet>, const Ipv4Header &> ()
+  );
 
-  ForwardUp (packet, ipHeader, ipv4Interface);
 }
 
 Ptr<Icmpv4L4Protocol> 
@@ -598,75 +473,35 @@
 Ipv4L3Protocol::Send (Ptr<Packet> packet, 
             Ipv4Address source, 
             Ipv4Address destination,
-            uint8_t protocol)
+            uint8_t protocol,
+            Ptr<Ipv4Route> route)
 {
-  NS_LOG_FUNCTION (this << packet << source << destination << protocol);
+  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
 
   Ipv4Header ipHeader;
-
-  if (m_calcChecksum)
-    {
-      ipHeader.EnableChecksum ();
-    }
-
-  ipHeader.SetSource (source);
-  ipHeader.SetDestination (destination);
-  ipHeader.SetProtocol (protocol);
-  ipHeader.SetPayloadSize (packet->GetSize ());
-  ipHeader.SetIdentification (m_identification);
-
-  m_identification ++;
-
-  SocketSetDontFragmentTag dfTag;
-  bool found = packet->FindFirstMatchingTag (dfTag);
+  bool mayFragment = true;
+  uint8_t ttl = m_defaultTtl;
+  SocketIpTtlTag tag;
+  bool found = packet->FindFirstMatchingTag (tag);
   if (found)
     {
-      if (dfTag.IsEnabled ())
-        {
-          ipHeader.SetDontFragment ();
-        }
-      else
-        {
-          ipHeader.SetMayFragment ();
-        }
+      ttl = tag.GetTtl ();
+      // XXX remove tag here?  
     }
+
+  // Handle a few cases:
+  // 1) packet is destined to limited broadcast address
+  // 2) packet is destined to a subnet-directed broadcast address
+  // 3) packet is not broadcast, and is passed in with a route entry
+  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
+  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
   
-
-  // Set TTL to 1 if it is a broadcast packet of any type.  Otherwise,
-  // possibly override the default TTL if the packet is tagged
-  SocketIpTtlTag tag;
-  found = packet->FindFirstMatchingTag (tag);
-
+  // 1) packet is destined to limited broadcast address
   if (destination.IsBroadcast ()) 
     {
-      ipHeader.SetTtl (1);
-    }
-  else if (found)
-    {
-      ipHeader.SetTtl (tag.GetTtl ());
-      // XXX remove tag here?  
-    }
-  else
-    {
-      ipHeader.SetTtl (m_defaultTtl);
-      uint32_t ifaceIndex = 0;
-      for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
-           ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
-        {
-          Ptr<Ipv4Interface> outInterface = *ifaceIter;
-          // XXX this logic might not be completely correct for multi-addressed interface
-          for (uint32_t j = 0; j < outInterface->GetNAddresses(); j++)
-            {
-              if (destination.IsSubnetDirectedBroadcast (
-                outInterface->GetAddress (j).GetMask ()))
-                {
-                  ipHeader.SetTtl (1);
-                }
-            }
-        }
-    }
-  if (destination.IsBroadcast ())
-    {
+      NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1:  limited broadcast");
+      ttl = 1;
+      ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
       uint32_t ifaceIndex = 0;
       for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
            ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
@@ -674,209 +509,216 @@
           Ptr<Ipv4Interface> outInterface = *ifaceIter;
           Ptr<Packet> packetCopy = packet->Copy ();
 
+          NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
           packetCopy->AddHeader (ipHeader);
-          // XXX Handle multiple address on interface
-          if (packetCopy->GetSize () > outInterface->GetMtu () &&
-              ipHeader.IsDontFragment () &&
-              IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
-            {
-              Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
-              NS_ASSERT (icmp != 0);
-              icmp->SendDestUnreachFragNeeded (ipHeader, packet, outInterface->GetMtu ());
-              m_dropTrace (packetCopy);
-            }
-          else if (packet->GetSize () > outInterface->GetMtu () &&
-                   !ipHeader.IsDontFragment ())
+          m_txTrace (packetCopy, ifaceIndex);
+          outInterface->Send (packetCopy, destination);
+        }
+      return;
+    }
+
+  // 2) check: packet is destined to a subnet-directed broadcast address
+  uint32_t ifaceIndex = 0;
+  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
+    ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
+    {
+      Ptr<Ipv4Interface> outInterface = *ifaceIter;
+      for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
+        {
+          Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
+          NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
+          if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) && 
+              destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ())   )  
             {
-              NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
-              m_dropTrace (packet);
-            }
-          else
-            {
-              NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
-              if (outInterface->IsUp ())
-                {
-                  m_txTrace (packetCopy, ifaceIndex);
-                  outInterface->Send (packetCopy, destination);
-                }
-              else
-                {
-                  m_dropTrace (packetCopy);
-                }
+              NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2:  subnet directed bcast to " << ifAddr.GetLocal ());
+              ttl = 1;
+              ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+              Ptr<Packet> packetCopy = packet->Copy ();
+              packetCopy->AddHeader (ipHeader);
+              m_txTrace (packetCopy, ifaceIndex);
+              outInterface->Send (packetCopy, destination);
+              return;
             }
         }
     }
+
+  // 3) packet is not broadcast, and is passed in with a route entry
+  //    with a valid Ipv4Address as the gateway
+  if (route && route->GetGateway () != Ipv4Address ())
+    {
+      NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3:  passed in with route");
+      ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+      SendRealOut (route, packet, ipHeader);
+      return; 
+    } 
+  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
+  if (route && route->GetGateway () != Ipv4Address ())
+    {
+      // This could arise because the synchronous RouteOutput() call
+      // returned to the transport protocol with a source address but
+      // there was no next hop available yet (since a route may need
+      // to be queried).  So, call asynchronous version of RouteOutput?
+      NS_FATAL_ERROR("XXX This case not yet implemented");
+    }
+  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
+  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4:  passed in with no route " << destination);
+  Socket::SocketErrno errno; 
+  uint32_t oif = 0; // unused for now
+  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
+  Ptr<Ipv4Route> newRoute = m_routingProtocol->RouteOutput (ipHeader, oif, errno);
+  if (newRoute)
+    {
+      SendRealOut (newRoute, packet, ipHeader);
+    }
   else
     {
-      // XXX Note here that in most ipv4 stacks in the world,
-      // the route calculation for an outgoing packet is not
-      // done in the ip layer. It is done within the application
-      // socket when the first packet is sent to avoid this
-      // costly lookup on a per-packet basis.
-      // That would require us to get the route from the packet,
-      // most likely with a packet tag. The higher layers do not
-      // do this yet for us.
-      Lookup (ipHeader, packet,
-              MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+      NS_LOG_WARN ("No route to host.  Drop.");
+      m_dropTrace (packet);
     }
 }
 
+// XXX when should we set ip_id?   check whether we are incrementing
+// m_identification on packets that may later be dropped in this stack
+// and whether that deviates from Linux
+Ipv4Header
+Ipv4L3Protocol::BuildHeader (
+            Ipv4Address source, 
+            Ipv4Address destination,
+            uint8_t protocol,
+            uint16_t payloadSize,
+            uint8_t ttl,
+            bool mayFragment)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4Header ipHeader;
+  ipHeader.SetSource (source);
+  ipHeader.SetDestination (destination);
+  ipHeader.SetProtocol (protocol);
+  ipHeader.SetPayloadSize (payloadSize);
+  ipHeader.SetTtl (ttl);
+  if (mayFragment == true)
+    {
+      ipHeader.SetMayFragment ();
+      ipHeader.SetIdentification (m_identification);
+      m_identification ++;
+    }
+  else
+    {
+      ipHeader.SetDontFragment ();
+      // TBD:  set to zero here; will cause traces to change
+      ipHeader.SetIdentification (m_identification);
+      m_identification ++;
+    }
+  if (m_calcChecksum)
+    {
+      ipHeader.EnableChecksum ();
+    }
+  return ipHeader;
+}
+
 void
-Ipv4L3Protocol::SendRealOut (bool found,
-                             Ipv4Route const &route,
+Ipv4L3Protocol::SendRealOut (Ptr<Ipv4Route> route,
                              Ptr<Packet> packet,
                              Ipv4Header const &ipHeader)
 {
-  NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
+  NS_LOG_FUNCTION (this << packet << &ipHeader);
 
+  // We add a header regardless of whether there is a route, since 
+  // we may want to drop trace
   packet->AddHeader (ipHeader);
-  if (!found)
+  if (route == 0)
     {
       NS_LOG_WARN ("No route to host.  Drop.");
       m_dropTrace (packet);
       return;
     }
 
-  NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
+  Ptr<NetDevice> outDev = route->GetOutputDevice ();
+  int32_t interface = GetInterfaceForDevice (outDev);
+  NS_ASSERT (interface >= 0);
+  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
+  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
 
-  Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
-  // XXX handle multiple address on interface
-  if (packet->GetSize () > outInterface->GetMtu () &&
-      ipHeader.IsDontFragment () &&
-      IsUnicast (ipHeader.GetDestination (), outInterface->GetAddress (0).GetMask ()))
-    {
-      NS_LOG_LOGIC ("Too big: need fragmentation but not allowed");
-      Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
-      NS_ASSERT (icmp != 0);
-      Ptr<Packet> copyNoHeader = packet->Copy ();
-      Ipv4Header tmp;
-      copyNoHeader->RemoveHeader (tmp);
-      icmp->SendDestUnreachFragNeeded (ipHeader, copyNoHeader, outInterface->GetMtu ());
-      m_dropTrace (packet);
-    }
-  else if (packet->GetSize () > outInterface->GetMtu () &&
-           !ipHeader.IsDontFragment ())
-    {
-      NS_LOG_LOGIC ("Too big: need fragmentation but no frag support.");
-      m_dropTrace (packet);
-    }
-  else
+  NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
+  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0"))) 
     {
-      if (route.IsGateway ()) 
+      if (outInterface->IsUp ())
+        {
+          NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
+          m_txTrace (packet, interface);
+          outInterface->Send (packet, route->GetGateway ());
+        }
+      else
         {
-          if (outInterface->IsUp ())
-            {
-              NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
-              m_txTrace (packet, route.GetInterface ());
-              outInterface->Send (packet, route.GetGateway ());
-            }
-          else
-            {
-              NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
-              m_dropTrace (packet);
-            }
-        } 
-      else 
+          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
+          m_dropTrace (packet);
+        }
+    } 
+  else 
+    {
+      if (outInterface->IsUp ())
         {
-          if (outInterface->IsUp ())
-            {
-              NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
-              m_txTrace (packet, route.GetInterface ());
-              outInterface->Send (packet, ipHeader.GetDestination ());
-            }
-          else
-            {
-              NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route.GetGateway ());
-              m_dropTrace (packet);
-            }
+          NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
+          m_txTrace (packet, interface);
+          outInterface->Send (packet, ipHeader.GetDestination ());
+        }
+      else
+        {
+          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
+          m_dropTrace (packet);
         }
     }
 }
 
-bool
-Ipv4L3Protocol::Forwarding (
-  uint32_t interface, 
-  Ptr<Packet> packet, 
-  Ipv4Header &ipHeader, 
-  Ptr<NetDevice> device)
+// This function analogous to Linux ip_mr_forward()
+void
+Ipv4L3Protocol::IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv4Header &header)
 {
-  NS_LOG_FUNCTION (interface << packet << &ipHeader<< device);
-  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
-
-  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
-       i != m_interfaces.end (); i++) 
+  NS_LOG_FUNCTION (mrtentry << p << header);
+  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
+  // The output interfaces we could forward this onto are encoded
+  // in the OutputTtl of the Ipv4MulticastRoute
+  for (uint32_t i = 0; i < Ipv4MulticastRoute::MAX_INTERFACES; i++)
     {
-      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
+      if (mrtentry->GetOutputTtl (i) < Ipv4MulticastRoute::MAX_TTL)
         {
-          if ((*i)->GetAddress (j).GetLocal ().IsEqual (ipHeader.GetDestination ())) 
+          Ptr<Packet> packet = p->Copy ();
+          Ipv4Header h = header;
+          h.SetTtl (header.GetTtl () - 1);
+          if (h.GetTtl () == 0)
             {
-              NS_LOG_LOGIC ("For me (destination match)");
-              return false;
+              NS_LOG_WARN ("TTL exceeded.  Drop.");
+              m_dropTrace (packet);
+              return;
             }
+          NS_LOG_LOGIC ("Forward multicast via interface " << i);
+          Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
+          rtentry->SetSource (h.GetSource ());
+          rtentry->SetDestination (h.GetDestination ());
+          rtentry->SetGateway (Ipv4Address::GetAny ());
+          rtentry->SetOutputDevice (GetNetDevice (i));
+          SendRealOut (rtentry, packet, h);
+          return; 
         }
     }
-  
-  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
-       i != m_interfaces.end (); i++) 
-    {
-      Ptr<Ipv4Interface> interface = *i;
-      if (interface->GetDevice () == device)
-	{
-          // XXX multi-address case
-	  if (ipHeader.GetDestination ().IsEqual (interface->GetAddress (0).GetBroadcast ())) 
-	    {
-              NS_LOG_LOGIC ("For me (interface broadcast address)");
-	      return false;
-	    }
-	  break;
-	}
-    }
-      
-  if (ipHeader.GetDestination ().IsBroadcast ()) 
-    {
-      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
-      return false;
-    }
-
-  if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) 
-    {
-      NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
-      return false;
-    }
-//  
-// If this is a to a multicast address and this node is a member of the 
-// indicated group we need to return false so the multicast is forwarded up.
-//        
-  for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
-       i != m_multicastGroups.end (); i++)
-    {
-      if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
-          (*i).second.IsEqual (ipHeader.GetDestination ()))
-        {
-          NS_LOG_LOGIC ("For me (Joined multicast group)");
-          // We forward with a packet copy, since forwarding may change
-          // the packet, affecting our local delivery
-          NS_LOG_LOGIC ("Forwarding (multicast).");
-          DoForward (interface, packet->Copy (), ipHeader);
-          return false;
-        }   
-    }
-
-  DoForward (interface, packet, ipHeader);
-  return true;
 }
 
+// This function analogous to Linux ip_forward()
 void
-Ipv4L3Protocol::DoForward (uint32_t interface, 
-                           Ptr<Packet> packet, 
-                           Ipv4Header ipHeader)
+Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ipv4Header &header)
 {
-  NS_LOG_FUNCTION (this << interface << packet << ipHeader);
-
+  NS_LOG_FUNCTION (rtentry << p << header);
+  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
+  // Forwarding
+  Ipv4Header ipHeader = header;
+  Ptr<Packet> packet = p->Copy ();
   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
   // XXX handle multi-interfaces
   if (ipHeader.GetTtl () == 0)
     {
+      Ptr<NetDevice> outDev = rtentry->GetOutputDevice ();
+      int32_t interface = GetInterfaceForDevice (outDev);
+      NS_ASSERT (interface >= 0);
       if (IsUnicast (ipHeader.GetDestination (), GetInterface (interface)->GetAddress (0).GetMask ()))
         {
           Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
@@ -885,18 +727,15 @@
       NS_LOG_WARN ("TTL exceeded.  Drop.");
       m_dropTrace (packet);
       return;
-    }  
-  NS_LOG_LOGIC ("Not for me, forwarding.");
-  Lookup (interface, ipHeader, packet,
-          MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
+    }
+  SendRealOut (rtentry, packet, ipHeader);
 }
 
-
 void
-Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
-                           Ptr<Ipv4Interface> incomingInterface)
+Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
 {
-  NS_LOG_FUNCTION (this << p << &ip);
+  NS_LOG_FUNCTION (this << packet << &ip);
+  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
 
   Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
   if (protocol != 0)
@@ -905,15 +744,15 @@
       // RX_ENDPOINT_UNREACH codepath
       Ptr<Packet> copy = p->Copy ();
       enum Ipv4L4Protocol::RxStatus status = 
-        protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
+        protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
       switch (status) {
       case Ipv4L4Protocol::RX_OK:
         // fall through
       case Ipv4L4Protocol::RX_CSUM_FAILED:
         break;
       case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
-        // XXX handle multi-interface case
-        if (IsUnicast (ip.GetDestination (), incomingInterface->GetAddress (0).GetMask ()))
+        // XXX handle multi-interfaces
+        if (IsUnicast (ip.GetDestination (), GetInterface (iif)->GetAddress (0).GetMask ()))
           {
             GetIcmp ()->SendDestUnreachPort (ip, copy);
           }
@@ -922,32 +761,7 @@
     }
 }
 
-void 
-Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
-  NS_LOG_FUNCTION (this << origin << group);
-  m_multicastGroups.push_back(
-    std::pair<Ipv4Address, Ipv4Address> (origin, group));
-}
-
-void
-Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
-{
-  NS_LOG_FUNCTION (this << origin << group);
-
-  for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
-       i != m_multicastGroups.end (); 
-       i++)
-    {
-      if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
-        {
-          m_multicastGroups.erase (i);
-          return;
-        }
-    }
-}
-
-uint32_t
+uint32_t 
 Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
 {
   NS_LOG_FUNCTION (this << i << address);
@@ -955,7 +769,7 @@
   return interface->AddAddress (address);
 }
 
-Ipv4InterfaceAddress
+Ipv4InterfaceAddress 
 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
 {
   NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
@@ -963,7 +777,7 @@
   return interface->GetAddress (addressIndex);
 }
 
-uint32_t
+uint32_t 
 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
 {
   NS_LOG_FUNCTION (this << interface);
@@ -987,76 +801,6 @@
   return interface->GetMetric ();
 }
 
-bool
-Ipv4L3Protocol::GetInterfaceForDestination (
-  Ipv4Address destination, uint32_t& interface) const
-{
-  NS_LOG_FUNCTION (this << destination << &interface);
-//
-// The first thing we do in trying to determine a source address is to 
-// consult the routing protocols.  These will also check for a default route
-// if one has been set.
-//
-  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
-       i != m_routingProtocols.end (); 
-       i++)
-    {
-      NS_LOG_LOGIC ("Requesting Source Address");
-      uint32_t interfaceTmp;
-
-      if ((*i).second->RequestInterface (destination, interfaceTmp))
-        {
-          NS_LOG_LOGIC ("Found interface " << interfaceTmp);
-          interface = interfaceTmp;
-          return true;
-        }
-    }
-//
-// If there's no routing table entry telling us what *single* interface will 
-// be used to send a packet to this destination, we'll have to just pick one.  
-// If there's only one interface on this node, a good answer isn't very hard
-// to come up with.  Before jumping to any conclusions, remember that the 
-// zeroth interface is the loopback interface, so what we actually want is
-// a situation where there are exactly two interfaces on the node, in which
-// case interface one is the "single" interface connected to the outside world.
-//
-  if (GetNInterfaces () == 2)
-    {
-      NS_LOG_LOGIC ("One Interface.  Using interface 1.");
-      interface = 1;
-      return true;
-    }
-//
-// If we fall through to here, we have a node with multiple interfaces and
-// no routes to guide us in determining what interface to choose.  Either
-// no default route was found (for unicast or multicast), or in the case of a
-// multicast, the default route contained multiple outbound interfaces.
-//
-// The fallback position is to just get the unicast default route and use 
-// the outgoing interface specified there.  We don't want to leave the source
-// address unset, so we just assert here.
-//
-// N.B. that in the case of a multicast with a route containing multiple
-// outgoing interfaces, the source address of packets from that node will be
-// set to the IP address of the interface set in the default unicast route.
-// Also, in the case of a broadcast, the same will be true.
-//
-  NS_LOG_LOGIC ("Using default unicast route");
-  Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
-
-  if (route == NULL)
-    {
-      NS_LOG_LOGIC ("Ipv4L3Protocol::GetInterfaceForDestination (): "
-                    "Unable to determine outbound interface.  No default route set");
-      return false;
-    }
-
-  interface = route->GetInterface ();
-
-  NS_LOG_LOGIC ("Default route specifies interface " << interface);
-  return true;
-}
-
 uint16_t 
 Ipv4L3Protocol::GetMtu (uint32_t i) const
 {
@@ -1088,7 +832,9 @@
       if (((interface->GetAddress (j).GetLocal ()) != (Ipv4Address ()))
           && (interface->GetAddress (j).GetMask ()) != (Ipv4Mask ()))
         {
-          AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()), interface->GetAddress (j).GetMask (), i);
+          NS_ASSERT_MSG (GetStaticRouting(), "SetUp:: No static routing");
+          GetStaticRouting ()->AddNetworkRouteTo (interface->GetAddress (j).GetLocal ().CombineMask (interface->GetAddress (j).GetMask ()),
+            interface->GetAddress (j).GetMask (), i);
         }
     }
 }
@@ -1105,12 +851,12 @@
   while (modified)
     {
       modified = false;
-      for (uint32_t i = 0; i < GetNRoutes (); i++)
+      for (uint32_t i = 0; i < GetStaticRouting ()->GetNRoutes (); i++)
         {
-          Ipv4Route route = GetRoute (i);
+          Ipv4RoutingTableEntry route = GetStaticRouting ()->GetRoute (i);
           if (route.GetInterface () == ifaceIndex)
             {
-              RemoveRoute (i);
+              GetStaticRouting ()->RemoveRoute (i);
               modified = true;
               break;
             }
@@ -1118,43 +864,23 @@
     }
 }
 
-// Note:  This method will be removed in Ipv4 routing work
-Ipv4Address
-Ipv4L3Protocol::GetSourceAddress (Ipv4Address destination) const
-{
-  uint32_t interface = 0xffffffff;
-
-  bool result = GetInterfaceForDestination (destination, interface);
-
-  if (result)
-    {
-      // if multiple addresses exist, search for the first one on the same subnet
-      for (uint32_t i = 0; i < GetNAddresses (interface); i++)
-        {
-          Ipv4InterfaceAddress ipv4InAddr = GetAddress (interface, i);
-          if (ipv4InAddr.GetLocal().CombineMask(ipv4InAddr.GetMask ()) == destination.CombineMask (ipv4InAddr.GetMask ()))
-            {
-              return ipv4InAddr.GetLocal ();
-            }
-        }
-      // Destination is off-link, so return first address.
-      return GetAddress (interface, 0).GetLocal ();
-    }
-  else
-    {
-//
-// If we can't find any address, just leave it 0.0.0.0
-//
-      return Ipv4Address::GetAny ();
-    }
-}
-
 Ptr<NetDevice>
 Ipv4L3Protocol::GetNetDevice (uint32_t i)
 {
   return GetInterface (i)-> GetDevice ();
 }
 
+void 
+Ipv4L3Protocol::SetIpForward (bool forward) 
+{
+  m_ipForward = forward;
+}
+
+bool 
+Ipv4L3Protocol::GetIpForward (void) const
+{
+  return m_ipForward;
+}
 
 
 }//namespace ns3
--- a/src/internet-stack/ipv4-l3-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -29,7 +29,8 @@
 #include "ns3/ipv4.h"
 #include "ns3/traced-callback.h"
 #include "ns3/ipv4-header.h"
-#include "ipv4-static-routing.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ipv4-static-routing-impl.h"
 
 namespace ns3 {
 
@@ -38,6 +39,7 @@
 class Ipv4Interface;
 class Ipv4Address;
 class Ipv4Header;
+class Ipv4RoutingTableEntry;
 class Ipv4Route;
 class Node;
 class Socket;
@@ -64,6 +66,10 @@
 
   void SetNode (Ptr<Node> node);
 
+  // functions defined in base class Ipv4
+  void SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routing);
+  Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (void) const;
+
   Ptr<Socket> CreateRawSocket (void);
   void DeleteRawSocket (Ptr<Socket> socket);
 
@@ -105,15 +111,6 @@
   void SetDefaultTtl (uint8_t ttl);
 
   /**
-   * \param device the device to match
-   * \returns the matching interface, zero if not found.
-   *
-   * Try to find an Ipv4Interface whose NetDevice is equal to
-   * the input NetDevice.
-   */
-  Ptr<Ipv4Interface> FindInterfaceForDevice (Ptr<const NetDevice> device);
-
-  /**
    * Lower layer calls this method after calling L3Demux::Lookup
    * The ARP subclass needs to know from which NetDevice this
    * packet is coming to:
@@ -128,64 +125,21 @@
    * \param source source address of packet
    * \param destination address of packet
    * \param protocol number of packet
+   * \param route route entry
    *
    * Higher-level layers call this method to send a packet
    * down the stack to the MAC and PHY layers.
    */
   void Send (Ptr<Packet> packet, Ipv4Address source, 
-	     Ipv4Address destination, uint8_t protocol);
-
-
-    
-  void AddHostRouteTo (Ipv4Address dest, 
-                       Ipv4Address nextHop, 
-                       uint32_t interface);
-  void AddHostRouteTo (Ipv4Address dest, 
-                       uint32_t interface);
-
-  void AddNetworkRouteTo (Ipv4Address network, 
-                          Ipv4Mask networkMask, 
-                          Ipv4Address nextHop, 
-                          uint32_t interface);
-  void AddNetworkRouteTo (Ipv4Address network, 
-                          Ipv4Mask networkMask, 
-                          uint32_t interface);
-  void SetDefaultRoute (Ipv4Address nextHop, 
-                        uint32_t interface);
-
-  void Lookup (Ipv4Header const &ipHeader,
-               Ptr<Packet> packet,
-               Ipv4RoutingProtocol::RouteReplyCallback routeReply);
-
-  uint32_t GetNRoutes (void);
-  Ipv4Route GetRoute (uint32_t i);
-  void RemoveRoute (uint32_t i);
-
-  void AddMulticastRoute (Ipv4Address origin,
-                          Ipv4Address group,
-                          uint32_t inputInterface,
-                          std::vector<uint32_t> outputInterfaces);
-
-  void SetDefaultMulticastRoute (uint32_t onputInterface);
-
-  uint32_t GetNMulticastRoutes (void) const;
-  Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const;
-
-  void RemoveMulticastRoute (Ipv4Address origin,
-                             Ipv4Address group,
-                             uint32_t inputInterface);
-  void RemoveMulticastRoute (uint32_t i);
+	     Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route);
 
   uint32_t AddInterface (Ptr<NetDevice> device);
   Ptr<Ipv4Interface> GetInterface (uint32_t i) const;
   uint32_t GetNInterfaces (void) const;
 
-  uint32_t FindInterfaceForAddr (Ipv4Address addr) const;
-  uint32_t FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const;
-  int32_t FindInterfaceForDevice (Ptr<NetDevice> device) const;
-  
-  void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group);
-  void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group);
+  int32_t GetInterfaceForAddress (Ipv4Address addr) const;
+  int32_t GetInterfaceForPrefix (Ipv4Address addr, Ipv4Mask mask) const;
+  int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
 
   uint32_t AddAddress (uint32_t i, Ipv4InterfaceAddress address);
   Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
@@ -193,9 +147,6 @@
 
   void SetMetric (uint32_t i, uint16_t metric);
   uint16_t GetMetric (uint32_t i) const;
-  Ipv4Address GetSourceAddress (Ipv4Address destination) const;
-  bool GetInterfaceForDestination (Ipv4Address destination, 
-                                 uint32_t& interface) const;
   uint16_t GetMtu (uint32_t i) const;
   bool IsUp (uint32_t i) const;
   void SetUp (uint32_t i);
@@ -209,39 +160,52 @@
 protected:
 
   virtual void DoDispose (void);
-
+  /**
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
 private:
   Ipv4L3Protocol(const Ipv4L3Protocol &);
   Ipv4L3Protocol &operator = (const Ipv4L3Protocol &);
-  void Lookup (uint32_t interface,
-               Ipv4Header const &ipHeader,
-               Ptr<Packet> packet,
-               Ipv4RoutingProtocol::RouteReplyCallback routeReply);
+
+  virtual void SetIpForward (bool forward);
+  virtual bool GetIpForward (void) const;
+
+  Ipv4Header BuildHeader (
+            Ipv4Address source,
+            Ipv4Address destination,
+            uint8_t protocol,
+            uint16_t payloadSize,
+            uint8_t ttl,
+            bool mayFragment);
 
-  void SendRealOut (bool found,
-                    Ipv4Route const &route,
-                    Ptr<Packet> packet,
-                    Ipv4Header const &ipHeader);
-  bool Forwarding (uint32_t interface, 
-                   Ptr<Packet> packet, 
-                   Ipv4Header &ipHeader, 
-                   Ptr<NetDevice> device);
-  void ForwardUp (Ptr<Packet> p, Ipv4Header const&ip, Ptr<Ipv4Interface> incomingInterface);
+  void
+  SendRealOut (Ptr<Ipv4Route> route,
+               Ptr<Packet> packet,
+               Ipv4Header const &ipHeader);
+
+  void 
+  IpForward (Ptr<Ipv4Route> rtentry, 
+             Ptr<const Packet> p, 
+             const Ipv4Header &header);
+
+  void
+  IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, 
+                      Ptr<const Packet> p, 
+                      const Ipv4Header &header);
+
+  void LocalDeliver (Ptr<const Packet> p, Ipv4Header const&ip, uint32_t iif);
   uint32_t AddIpv4Interface (Ptr<Ipv4Interface> interface);
   void SetupLoopback (void);
   Ptr<Icmpv4L4Protocol> GetIcmp (void) const;
   bool IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const;
-  void DoForward (uint32_t interface, 
-                  Ptr<Packet> packet, 
-                  Ipv4Header ipHeader);
-
 
   typedef std::list<Ptr<Ipv4Interface> > Ipv4InterfaceList;
-  typedef std::list<std::pair<Ipv4Address, Ipv4Address> > Ipv4MulticastGroupList;
-  typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
   typedef std::list<Ptr<Ipv4RawSocketImpl> > SocketList;
   typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
 
+  bool m_ipForward;
   L4List_t m_protocols;
   Ipv4InterfaceList m_interfaces;
   uint32_t m_nInterfaces;
@@ -253,10 +217,8 @@
   TracedCallback<Ptr<const Packet>, uint32_t> m_rxTrace;
   TracedCallback<Ptr<const Packet> > m_dropTrace;
 
-  Ipv4RoutingProtocolList m_routingProtocols;
-
-  Ptr<Ipv4StaticRouting> m_staticRouting;
-  Ipv4MulticastGroupList m_multicastGroups;
+  Ptr<Ipv4RoutingProtocol> m_routingProtocol;
+  Ptr<Ipv4StaticRouting> GetStaticRouting (void) const;
 
   SocketList m_sockets;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-list-routing-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,270 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "ns3/log.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/node.h"
+#include "ns3/ipv4-static-routing.h"
+#include "ipv4-list-routing-impl.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4ListRoutingImpl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRoutingImpl);
+
+TypeId
+Ipv4ListRoutingImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4ListRoutingImpl")
+    .SetParent<Ipv4ListRouting> ()
+    ;
+  return tid;
+}
+
+
+Ipv4ListRoutingImpl::Ipv4ListRoutingImpl () 
+ : m_node (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv4ListRoutingImpl::~Ipv4ListRoutingImpl () 
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Ipv4ListRoutingImpl::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (Ipv4RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++)
+    {
+      // Note:  Calling dispose on these protocols causes memory leak
+      //        The routing protocols should not maintain a pointer to
+      //        this object, so Dispose() shouldn't be necessary.
+      (*rprotoIter).second = 0;
+    }
+  m_routingProtocols.clear ();
+  m_node = 0;
+}
+
+Ptr<Ipv4Route>
+Ipv4ListRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr)
+{
+  NS_LOG_FUNCTION (this << header.GetDestination () << " " << header.GetSource () << " " << oif);
+  Ptr<Ipv4Route> route;
+
+  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
+       i != m_routingProtocols.end ();
+       i++)
+    {
+      NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
+      NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestination ());
+      route = (*i).second->RouteOutput (header, oif, sockerr);
+      if (route)
+        {
+          NS_LOG_LOGIC ("Found route " << route);
+          sockerr = Socket::ERROR_NOTERROR;
+          return route;
+        }
+    }
+  NS_LOG_LOGIC ("Done checking " << GetTypeId ());
+  NS_LOG_LOGIC ("");
+  sockerr = Socket::ERROR_NOROUTETOHOST;
+  return 0;
+}
+
+// Patterned after Linux ip_route_input and ip_route_input_slow
+bool 
+Ipv4ListRoutingImpl::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, 
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+                             LocalDeliverCallback lcb, ErrorCallback ecb)
+{
+  bool retVal = false;
+  NS_LOG_FUNCTION (p << header << idev);
+  NS_LOG_LOGIC ("RouteInput logic for node: " << m_node->GetId ());
+
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+  NS_ASSERT (ipv4);
+  uint32_t iif = ipv4->GetInterfaceForDevice (idev); 
+
+  // Multicast recognition; handle local delivery here
+  //
+  if (header.GetDestination().IsMulticast ())
+    {
+#ifdef NOTYET
+      if (ipv4->MulticastCheckGroup (iif, header.GetDestination ()))
+#endif
+      if (true)
+        {
+          NS_LOG_LOGIC ("Multicast packet for me-- local deliver");
+          Ptr<Packet> packetCopy = p->Copy();
+          // Here may want to disable lcb callback in recursive RouteInput
+          // call below
+          lcb (packetCopy, header, iif);
+          // Fall through-- we may also need to forward this
+          retVal = true;
+        }
+      for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+           rprotoIter != m_routingProtocols.end ();
+           rprotoIter++)
+        {
+          NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
+          if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
+            {
+              retVal = true;
+            }
+        }
+      return retVal;
+    }
+
+  if (header.GetDestination ().IsBroadcast ())
+    {
+      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
+      // TODO:  Local Deliver for broadcast
+      // TODO:  Forward broadcast
+    }
+
+ // TODO:  Configurable option to enable RFC 1222 Strong End System Model
+ // Right now, we will be permissive and allow a source to send us
+ // a packet to one of our other interface addresses; that is, the
+ // destination unicast address does not match one of the iif addresses,
+ // but we check our other interfaces.  This could be an option
+ // (to remove the outer loop immediately below and just check iif).
+  for (uint32_t j = 0; j < ipv4->GetNInterfaces (); j++)
+    {
+      for (uint32_t i = 0; i < ipv4->GetNAddresses (j); i++)
+        {
+          Ipv4InterfaceAddress iaddr = ipv4->GetAddress (j, i);
+          Ipv4Address addr = iaddr.GetLocal ();
+          if (addr.IsEqual (header.GetDestination ()))
+            {
+              if (j == iif)
+                {
+                  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ());
+                }
+              lcb (p, header, iif);
+              return true;
+            }
+          if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ()))
+            {
+              NS_LOG_LOGIC ("For me (interface broadcast address)");
+              lcb (p, header, iif);
+              return true;
+            }
+          NS_LOG_LOGIC ("Address "<< addr << " not a match");
+        }
+    }
+ // Next, try to find a route
+  for (Ipv4RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
+        {
+          return true;
+        }
+    }
+  // No routing protocol has found a route.  
+  return retVal;
+}
+
+void
+Ipv4ListRoutingImpl::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority)
+{
+  NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
+  m_routingProtocols.push_back
+    (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
+  m_routingProtocols.sort ();
+}
+
+uint32_t 
+Ipv4ListRoutingImpl::GetNRoutingProtocols (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_routingProtocols.size (); 
+}
+
+Ptr<Ipv4RoutingProtocol> 
+Ipv4ListRoutingImpl::GetRoutingProtocol (uint32_t index, int16_t& priority) const
+{
+  NS_LOG_FUNCTION (index);
+  if (index > m_routingProtocols.size ())
+    {
+      NS_FATAL_ERROR ("Ipv4ListRoutingImpl::GetRoutingProtocol():  index " << index << " out of range");
+    }
+  uint32_t i = 0;
+  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
+    {
+      if (i == index)
+        {
+          priority = (*rprotoIter).first;
+          return (*rprotoIter).second;
+        }
+    }
+  return 0;
+}
+
+Ptr<Ipv4StaticRouting>
+Ipv4ListRoutingImpl::GetStaticRouting (void) const
+{
+  NS_LOG_FUNCTION (this);
+  Ipv4StaticRouting* srp;
+  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++)
+    {
+      NS_LOG_LOGIC ("Searching for static routing");
+      srp = dynamic_cast<Ipv4StaticRouting*> (PeekPointer((*rprotoIter).second));
+      if (srp)
+        {
+          NS_LOG_LOGIC ("Found static routing");
+          return Ptr<Ipv4StaticRouting> (srp);
+        }
+    }
+  NS_LOG_LOGIC ("Static routing not found");
+  return 0;
+
+}
+
+void
+Ipv4ListRoutingImpl::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = node;
+}
+
+Ptr<Node> 
+Ipv4ListRoutingImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-list-routing-impl.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,65 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef IPV4_LIST_ROUTING_IMPL_H
+#define IPV4_LIST_ROUTING_IMPL_H
+
+#include <list>
+#include "ns3/ipv4-list-routing.h"
+
+namespace ns3 {
+
+class Ipv4StaticRouting;
+
+class Ipv4ListRoutingImpl : public Ipv4ListRouting
+{
+public:
+  static TypeId GetTypeId (void);
+
+  Ipv4ListRoutingImpl ();
+  ~Ipv4ListRoutingImpl ();
+
+  virtual Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+  virtual bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, 
+                           UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+                           LocalDeliverCallback lcb, ErrorCallback ecb);
+
+  virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority);
+
+  virtual uint32_t GetNRoutingProtocols (void) const;
+
+  virtual Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (uint32_t index, int16_t& priority) const;
+  virtual Ptr<Ipv4StaticRouting> GetStaticRouting (void) const;
+
+
+  void SetNode (Ptr<Node> node);
+  Ptr<Node> GetNode (void) const;
+
+protected:
+  void DoDispose (void);
+private:
+  typedef std::list< std::pair< int, Ptr<Ipv4RoutingProtocol> > > Ipv4RoutingProtocolList;
+  Ipv4RoutingProtocolList m_routingProtocols;
+  Ptr<Node> m_node;
+
+};
+
+} // Namespace ns3
+
+#endif /* IPV4_LIST_ROUTING_IMPL_H */
--- a/src/internet-stack/ipv4-loopback-interface.cc	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: 
- *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-
-#include "ns3/log.h"
-#include "ns3/net-device.h"
-#include "ns3/node.h"
-#include "ns3/mac48-address.h"
-#include "ns3/packet.h"
-#include "ipv4-loopback-interface.h"
-#include "ipv4-l3-protocol.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4LoopbackInterface");
-
-namespace ns3 {
-
-TypeId 
-Ipv4LoopbackInterface::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Ipv4LoopbackInterface")
-    .SetParent<Ipv4Interface> ()
-    ;
-  return tid;
-}
-
-Ipv4LoopbackInterface::Ipv4LoopbackInterface ()
-  : m_node (0)
-{
-  NS_LOG_FUNCTION (this);
-}
-
-Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
-{
-  NS_LOG_FUNCTION (this);
-  NS_ASSERT (m_node != 0);
-}
-
-Ptr<NetDevice> 
-Ipv4LoopbackInterface::GetDevice (void) const
-{
-  return 0;
-}
-
-void 
-Ipv4LoopbackInterface::SetNode (Ptr<Node> node)
-{
-  m_node = node;
-}
-
-void 
-Ipv4LoopbackInterface::SendTo (Ptr<Packet> packet, Ipv4Address dest)
-{
-  NS_LOG_FUNCTION (this << packet << dest);
-
-  Ptr<Ipv4L3Protocol> ipv4 = 
-    m_node->GetObject<Ipv4L3Protocol> ();
-
-  ipv4->Receive (0, packet, Ipv4L3Protocol::PROT_NUMBER, 
-                 Mac48Address ("ff:ff:ff:ff:ff:ff"),
-                 Mac48Address ("ff:ff:ff:ff:ff:ff"),
-                 NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
-                 );
-}
-
-}//namespace ns3
--- a/src/internet-stack/ipv4-loopback-interface.h	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: 
- *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
- */
-#ifndef IPV4_LOOPBACK_INTERFACE_H
-#define IPV4_LOOPBACK_INTERFACE_H
-
-#include "ipv4-interface.h"
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Node;
-/**
- * \brief An IPv4 loopback interface
- */
-class Ipv4LoopbackInterface : public Ipv4Interface 
-{
-public:
-  static TypeId GetTypeId (void);
-  Ipv4LoopbackInterface ();
-  virtual ~Ipv4LoopbackInterface ();
-
-  virtual Ptr<NetDevice> GetDevice (void) const;
-
-  void SetNode (Ptr<Node> node);
-
- private:
-  virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
-
-  Ptr<Node> m_node;
-};
-
-}//namespace ns3
-
-
-#endif /* IPV4_LOOPBACK_INTERFACE_H */
--- a/src/internet-stack/ipv4-raw-socket-impl.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-raw-socket-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -170,14 +170,24 @@
   InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress);
   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
   Ipv4Address dst = ad.GetIpv4 ();
-  uint32_t localInterface;
-  if (ipv4->GetInterfaceForDestination(dst, localInterface))
+  if (ipv4->GetRoutingProtocol ())
     {
-      ipv4->Send (p, ipv4->GetSourceAddress (dst), dst, m_protocol);
-    }
-  else
-    {
-      NS_LOG_DEBUG ("dropped because no outgoing route.");
+      Ipv4Header header;
+      header.SetDestination (dst);
+      SocketErrno errno = ERROR_NOTERROR;;
+      Ptr<Ipv4Route> route;
+      uint32_t oif = 0; //specify non-zero if bound to a source address
+      // TBD-- we could cache the route and just check its validity
+      route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+      if (route != 0)
+        {
+          NS_LOG_LOGIC ("Route exists");
+          ipv4->Send (p, route->GetSource (), dst, m_protocol, route);
+        }
+      else
+        {
+          NS_LOG_DEBUG ("dropped because no outgoing route.");
+        }
     }
   return 0;
 }
--- a/src/internet-stack/ipv4-raw-socket-impl.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/ipv4-raw-socket-impl.h	Sat May 30 17:37:38 2009 +0100
@@ -3,6 +3,7 @@
 
 #include "ns3/socket.h"
 #include "ns3/ipv4-header.h"
+#include "ns3/ipv4-route.h"
 #include <list>
 
 namespace ns3 {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-static-routing-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,570 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//         Gustavo Carneiro <gjc@inescporto.pt>
+
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/ipv4-route.h"
+#include "ipv4-static-routing-impl.h"
+#include "ns3/ipv4-routing-table-entry.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRoutingImpl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4StaticRoutingImpl);
+
+TypeId
+Ipv4StaticRoutingImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4StaticRoutingImpl")
+    .SetParent<Ipv4StaticRouting> ()
+    ;
+  return tid;
+}
+
+Ipv4StaticRoutingImpl::Ipv4StaticRoutingImpl () 
+: m_defaultRoute (0), m_node (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void 
+Ipv4StaticRoutingImpl::AddHostRouteTo (Ipv4Address dest, 
+                                   Ipv4Address nextHop, 
+                                   uint32_t interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, nextHop, interface);
+  m_hostRoutes.push_back (route);
+}
+
+void 
+Ipv4StaticRoutingImpl::AddHostRouteTo (Ipv4Address dest, 
+                                   uint32_t interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, interface);
+  m_hostRoutes.push_back (route);
+}
+
+void 
+Ipv4StaticRoutingImpl::AddNetworkRouteTo (Ipv4Address network, 
+                                      Ipv4Mask networkMask, 
+                                      Ipv4Address nextHop, 
+                                      uint32_t interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            nextHop,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+
+void 
+Ipv4StaticRoutingImpl::AddNetworkRouteTo (Ipv4Address network, 
+                                      Ipv4Mask networkMask, 
+                                      uint32_t interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            interface);
+  m_networkRoutes.push_back (route);
+}
+
+void 
+Ipv4StaticRoutingImpl::SetDefaultRoute (Ipv4Address nextHop, 
+                                    uint32_t interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateDefaultRoute (nextHop, interface);
+  delete m_defaultRoute;
+  m_defaultRoute = route;
+}
+
+void 
+Ipv4StaticRoutingImpl::AddMulticastRoute(Ipv4Address origin,
+                                     Ipv4Address group,
+                                     uint32_t inputInterface,
+                                     std::vector<uint32_t> outputInterfaces)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4MulticastRoutingTableEntry *route = new Ipv4MulticastRoutingTableEntry ();
+  *route = Ipv4MulticastRoutingTableEntry::CreateMulticastRoute (origin, group, 
+    inputInterface, outputInterfaces);
+  m_multicastRoutes.push_back (route);
+}
+
+// default multicast routes are stored as a network route
+// these routes are _not_ consulted in the forwarding process-- only
+// for originating packets
+void 
+Ipv4StaticRoutingImpl::SetDefaultMulticastRoute(uint32_t outputInterface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  Ipv4Address network = Ipv4Address ("224.0.0.0");
+  Ipv4Mask networkMask = Ipv4Mask ("240.0.0.0");
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
+                                            networkMask,
+                                            outputInterface);
+  m_networkRoutes.push_back (route);
+}
+
+uint32_t 
+Ipv4StaticRoutingImpl::GetNMulticastRoutes (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_multicastRoutes.size ();
+}
+
+Ipv4MulticastRoutingTableEntry
+Ipv4StaticRoutingImpl::GetMulticastRoute (uint32_t index) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_ASSERT_MSG(index < m_multicastRoutes.size (),
+    "Ipv4StaticRoutingImpl::GetMulticastRoute ():  Index out of range");
+
+  if (index < m_multicastRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (MulticastRoutesCI i = m_multicastRoutes.begin (); 
+           i != m_multicastRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              return *i;
+            }
+          tmp++;
+        }
+    }
+  return 0;
+}
+
+bool
+Ipv4StaticRoutingImpl::RemoveMulticastRoute(Ipv4Address origin,
+                                        Ipv4Address group,
+                                        uint32_t inputInterface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoutingTableEntry *route = *i;
+      if (origin == route->GetOrigin () &&
+          group == route->GetGroup () &&
+          inputInterface == route->GetInputInterface ())
+        {
+          delete *i;
+          m_multicastRoutes.erase (i);
+          return true;
+        }
+    }
+  return false;
+}
+
+void 
+Ipv4StaticRoutingImpl::RemoveMulticastRoute(uint32_t index)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint32_t tmp = 0;
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      if (tmp  == index)
+        {
+          delete *i;
+          m_multicastRoutes.erase (i);
+          return;
+        }
+      tmp++;
+    }
+}
+
+Ptr<Ipv4Route>
+Ipv4StaticRoutingImpl::LookupStatic (Ipv4Address dest)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv4Route> rtentry = 0;
+  for (HostRoutesCI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i++) 
+    {
+      NS_ASSERT ((*i)->IsHost ());
+      if ((*i)->GetDest ().IsEqual (dest)) 
+        {
+          NS_LOG_LOGIC ("Found global host route" << *i);
+          Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+          Ipv4RoutingTableEntry* route = (*i);
+          rtentry = Create<Ipv4Route> ();
+          rtentry->SetDestination (route->GetDest ());
+          // XXX handle multi-address case
+          rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
+          rtentry->SetGateway (route->GetGateway ());
+          uint32_t interfaceIdx = route->GetInterface ();
+          rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx));
+          return rtentry;
+        }
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      NS_ASSERT ((*j)->IsNetwork ());
+      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
+      Ipv4Address entry = (*j)->GetDestNetwork ();
+      if (mask.IsMatch (dest, entry)) 
+        {
+          NS_LOG_LOGIC ("Found global network route" << *j);
+          Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+          Ipv4RoutingTableEntry* route = (*j);
+          rtentry = Create<Ipv4Route> ();
+          rtentry->SetDestination (route->GetDest ());
+          // XXX handle multi-address case
+          rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
+          rtentry->SetGateway (route->GetGateway ());
+          uint32_t interfaceIdx = route->GetInterface ();
+          rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx));
+          return rtentry;
+        }
+    }
+  if (m_defaultRoute != 0) 
+    {
+      NS_ASSERT (m_defaultRoute->IsDefault ());
+      NS_LOG_LOGIC ("Found global network route" << m_defaultRoute);
+      Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+      Ipv4RoutingTableEntry* route = m_defaultRoute;
+      rtentry = Create<Ipv4Route> ();
+      rtentry->SetDestination (route->GetDest ());
+      // XXX handle multi-address case
+      rtentry->SetSource (ipv4->GetAddress (route->GetInterface(), 0).GetLocal ());
+      rtentry->SetGateway (route->GetGateway ());
+      uint32_t interfaceIdx = route->GetInterface ();
+      rtentry->SetOutputDevice (ipv4->GetNetDevice (interfaceIdx));
+      return rtentry;
+    }
+  return 0;
+}
+
+Ptr<Ipv4MulticastRoute>
+Ipv4StaticRoutingImpl::LookupStatic (
+  Ipv4Address origin, 
+  Ipv4Address group,
+  uint32_t    interface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv4MulticastRoute> mrtentry = 0;
+
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i++) 
+    {
+      Ipv4MulticastRoutingTableEntry *route = *i;
+//
+// We've been passed an origin address, a multicast group address and an 
+// interface index.  We have to decide if the current route in the list is
+// a match.
+//
+// The first case is the restrictive case where the origin, group and index
+// matches.  
+//
+      if (origin == route->GetOrigin () && group == route->GetGroup ())
+        {
+          // Skipping this case (SSM) for now
+          NS_LOG_LOGIC ("Found multicast source specific route" << *i);
+        }
+      if (group == route->GetGroup ())
+        {
+          if (interface == Ipv4::IF_ANY || 
+              interface == route->GetInputInterface ())
+            {
+              NS_LOG_LOGIC ("Found multicast route" << *i);
+              Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+              mrtentry = Create<Ipv4MulticastRoute> ();
+              mrtentry->SetGroup (route->GetGroup ());
+              mrtentry->SetOrigin (route->GetOrigin ());
+              mrtentry->SetParent (route->GetInputInterface ());
+              for (uint32_t j = 0; j < route->GetNOutputInterfaces (); j++)
+                {
+                  if (route->GetOutputInterface (j))
+                    {
+                      NS_LOG_LOGIC ("Setting output interface index " << route->GetOutputInterface (j));
+                      mrtentry->SetOutputTtl (route->GetOutputInterface (j), Ipv4MulticastRoute::MAX_TTL - 1);
+                    }
+                }
+              return mrtentry;
+            }
+        }
+    }
+  return mrtentry;
+}
+
+uint32_t 
+Ipv4StaticRoutingImpl::GetNRoutes (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint32_t n = 0;
+  if (m_defaultRoute != 0)
+    {
+      n++;
+    }
+  n += m_hostRoutes.size ();
+  n += m_networkRoutes.size ();
+  return n;
+}
+
+Ipv4RoutingTableEntry
+Ipv4StaticRoutingImpl::GetDefaultRoute ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_defaultRoute != 0)
+    {
+      return *m_defaultRoute;
+    }
+  else
+    {
+      return Ipv4RoutingTableEntry ();
+    }
+}
+
+Ipv4RoutingTableEntry 
+Ipv4StaticRoutingImpl::GetRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      return *m_defaultRoute;
+    }
+  if (index > 0 && m_defaultRoute != 0)
+    {
+      index--;
+    }
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesCI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              return *i;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          return *j;
+        }
+      tmp++;
+    }
+  NS_ASSERT (false);
+  // quiet compiler.
+  return 0;
+}
+void 
+Ipv4StaticRoutingImpl::RemoveRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (index == 0 && m_defaultRoute != 0)
+    {
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  if (index > 0 && m_defaultRoute != 0)
+    {
+      index--;
+    }
+  if (index < m_hostRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (HostRoutesI i = m_hostRoutes.begin (); 
+           i != m_hostRoutes.end (); 
+           i++) 
+        {
+          if (tmp  == index)
+            {
+              delete *i;
+              m_hostRoutes.erase (i);
+              return;
+            }
+          tmp++;
+        }
+    }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j++) 
+    {
+      if (tmp == index)
+        {
+          delete *j;
+          m_networkRoutes.erase (j);
+          return;
+        }
+      tmp++;
+    }
+  NS_ASSERT (false);
+}
+
+Ptr<Ipv4Route> 
+Ipv4StaticRoutingImpl::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
+{
+  NS_LOG_FUNCTION (this << header << oif);
+  Ipv4Address destination = header.GetDestination ();
+  Ptr<Ipv4Route> rtentry = 0;
+
+  // Multicast goes here
+  if (destination.IsMulticast ())
+    {
+      // Note:  Multicast routes for outbound packets are stored in the
+      // normal unicast table.  An implication of this is that it is not
+      // possible to source multicast datagrams on multiple interfaces.
+      // This is a well-known property of sockets implementation on 
+      // many Unix variants.
+      // So, we just log it and fall through to LookupStatic ()
+      NS_LOG_LOGIC ("RouteOutput()::Multicast destination");
+    }
+  rtentry = LookupStatic (destination);
+  if (rtentry)
+    { 
+      sockerr = Socket::ERROR_NOTERROR;
+    }
+  else
+    { 
+      sockerr = Socket::ERROR_NOROUTETOHOST;
+    }
+  return rtentry;
+}
+
+// XXX this method not robust enough to work independent of ListRouting
+bool 
+Ipv4StaticRoutingImpl::RouteInput  (Ptr<const Packet> p, const Ipv4Header &ipHeader, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb)
+{
+  NS_LOG_FUNCTION (this << p << ipHeader << ipHeader.GetSource () << ipHeader.GetDestination () << idev);
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
+  if (ipHeader.GetDestination ().IsMulticast ())
+    {
+      NS_LOG_LOGIC ("Multicast destination");
+      Ptr<Ipv4MulticastRoute> mrtentry =  LookupStatic(ipHeader.GetSource (),
+        ipHeader.GetDestination (), ipv4->GetInterfaceForDevice (idev));
+
+      if (mrtentry)
+        {
+          NS_LOG_LOGIC ("Multicast route found");
+          mcb (mrtentry, p, ipHeader); // multicast forwarding callback
+          return true;
+        }
+      else
+        {
+          NS_LOG_LOGIC ("Multicast route not found");
+          return false; // Let other routing protocols try to handle this
+        }
+    }
+//
+// This is a unicast packet.  Check to see if we have a route for it.
+//
+  NS_LOG_LOGIC ("Unicast destination");
+  Ptr<Ipv4Route> rtentry = LookupStatic (ipHeader.GetDestination ());
+  if (rtentry != 0)
+    {
+      NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
+      ucb (rtentry, p, ipHeader);  // unicast forwarding callback
+      return true;
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Did not find unicast destination- returning false");
+      return false; // Let other routing protocols try to handle this
+    }
+}
+
+Ipv4StaticRoutingImpl::~Ipv4StaticRoutingImpl ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Ipv4StaticRoutingImpl::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (HostRoutesI i = m_hostRoutes.begin (); 
+       i != m_hostRoutes.end (); 
+       i = m_hostRoutes.erase (i)) 
+    {
+      delete (*i);
+    }
+  for (NetworkRoutesI j = m_networkRoutes.begin (); 
+       j != m_networkRoutes.end (); 
+       j = m_networkRoutes.erase (j)) 
+    {
+      delete (*j);
+    }
+  if (m_defaultRoute != 0)
+    {
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
+       i != m_multicastRoutes.end (); 
+       i = m_multicastRoutes.erase (i)) 
+    {
+      delete (*i);
+    }
+  Ipv4RoutingProtocol::DoDispose ();
+}
+
+void
+Ipv4StaticRoutingImpl::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = node;
+}
+
+Ptr<Node>
+Ipv4StaticRoutingImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node; 
+} 
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv4-static-routing-impl.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,367 @@
+// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: George F. Riley<riley@ece.gatech.edu>
+//         Gustavo Carneiro <gjc@inescporto.pt>
+//
+
+#ifndef IPV4_STATIC_ROUTING_IMPL_H
+#define IPV4_STATIC_ROUTING_IMPL_H
+
+#include <list>
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-static-routing.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4RoutingTableEntry;
+class Ipv4MulticastRoutingTableEntry;
+class Node;
+
+class Ipv4StaticRoutingImpl : public Ipv4StaticRouting
+{
+public:
+  static TypeId GetTypeId (void);
+
+  Ipv4StaticRoutingImpl ();
+  virtual ~Ipv4StaticRoutingImpl ();
+
+  virtual Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+
+  virtual bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb);
+
+/**
+ * \brief Add a host route to the static routing table.
+ *
+ * \param dest The Ipv4Address destination for this route.
+ * \param nextHop The Ipv4Address of the next hop in the route.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  void AddHostRouteTo (Ipv4Address dest, 
+                       Ipv4Address nextHop, 
+                       uint32_t interface);
+/**
+ * \brief Add a host route to the static routing table.
+ *
+ * \param dest The Ipv4Address destination for this route.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  void AddHostRouteTo (Ipv4Address dest, 
+                       uint32_t interface);
+
+/**
+ * \brief Add a network route to the static routing table.
+ *
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param nextHop The next hop in the route to the destination network.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          Ipv4Address nextHop, 
+                          uint32_t interface);
+
+/**
+ * \brief Add a network route to the static routing table.
+ *
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          uint32_t interface);
+
+/**
+ * \brief Add a default route to the static routing table.
+ *
+ * This method tells the routing system what to do in the case where a specific
+ * route to a destination is not found.  The system forwards packets to the
+ * specified node in the hope that it knows better how to route the packet.
+ * 
+ * If the default route is set, it is returned as the selected route from 
+ * LookupStatic irrespective of destination address if no specific route is
+ * found.
+ *
+ * \param nextHop The Ipv4Address to send packets to in the hope that they
+ * will be forwarded correctly.
+ * \param interface The network interface index used to send packets.
+ *
+ * \see Ipv4Address
+ * \see Ipv4StaticRouting::Lookup
+ */
+  void SetDefaultRoute (Ipv4Address nextHop, 
+                        uint32_t interface);
+
+/**
+ * \brief Get the number of individual unicast routes that have been added
+ * to the routing table.
+ *
+ * \warning The default route counts as one of the routes.
+ */
+  uint32_t GetNRoutes (void);
+
+/**
+ * \brief Get the default route from the static routing table.
+ *
+ * \return If the default route is set, a pointer to that Ipv4RoutingTableEntry is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * \see Ipv4RoutingTableEntry
+ */
+  Ipv4RoutingTableEntry GetDefaultRoute (void);
+
+/**
+ * \brief Get a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries.  The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table.  This means that if you
+ * add only a default route, the table will have one entry that can be accessed
+ * either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
+ * 
+ * Similarly, if the default route has been set, calling RemoveRoute (0) will
+ * remove the default route.
+ *
+ * \param i The index (into the routing table) of the route to retrieve.  If
+ * the default route has been set, it will occupy index zero.
+ * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise
+ * a zero pointer is returned.
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::RemoveRoute
+ */
+  Ipv4RoutingTableEntry GetRoute (uint32_t i);
+
+/**
+ * \brief Remove a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries.  The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table.  This means that if the
+ * default route has been set, calling RemoveRoute (0) will remove the
+ * default route.
+ *
+ * \param i The index (into the routing table) of the route to remove.  If
+ * the default route has been set, it will occupy index zero.
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::GetRoute
+ * \see Ipv4StaticRouting::AddRoute
+ */
+  void RemoveRoute (uint32_t i);
+
+/**
+ * \brief Add a multicast route to the static routing table.
+ *
+ * A multicast route must specify an origin IP address, a multicast group and
+ * an input network interface index as conditions and provide a vector of
+ * output network interface indices over which packets matching the conditions
+ * are sent.
+ *
+ * Typically there are two main types of multicast routes:  routes of the 
+ * first kind are used during forwarding.  All of the conditions must be
+ * exlicitly provided.  The second kind of routes are used to get packets off
+ * of a local node.  The difference is in the input interface.  Routes for
+ * forwarding will always have an explicit input interface specified.  Routes
+ * off of a node will always set the input interface to a wildcard specified
+ * by the index Ipv4RoutingProtocol::INTERFACE_ANY.
+ *
+ * For routes off of a local node wildcards may be used in the origin and
+ * multicast group addresses.  The wildcard used for Ipv4Adresses is that 
+ * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0".  Usage
+ * of a wildcard allows one to specify default behavior to varying degrees.
+ *
+ * For example, making the origin address a wildcard, but leaving the 
+ * multicast group specific allows one (in the case of a node with multiple
+ * interfaces) to create different routes using different output interfaces
+ * for each multicast group.
+ *
+ * If the origin and multicast addresses are made wildcards, you have created
+ * essentially a default multicast address that can forward to multiple 
+ * interfaces.  Compare this to the actual default multicast address that is
+ * limited to specifying a single output interface for compatibility with
+ * existing functionality in other systems.
+ * 
+ * \param origin The Ipv4Address of the origin of packets for this route.  May
+ * be Ipv4Address:GetAny for open groups.
+ * \param group The Ipv4Address of the multicast group or this route.
+ * \param inputInterface The input network interface index over which to 
+ * expect packets destined for this route.  May be
+ * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin.
+ * \param outputInterfaces A vector of network interface indices used to specify
+ * how to send packets to the destination(s).
+ *
+ * \see Ipv4Address
+ */
+  void AddMulticastRoute (Ipv4Address origin,
+                          Ipv4Address group,
+                          uint32_t inputInterface,
+                          std::vector<uint32_t> outputInterfaces);
+
+/**
+ * \brief Add a default multicast route to the static routing table.
+ *
+ * This is the multicast equivalent of the unicast version SetDefaultRoute.
+ * We tell the routing system what to do in the case where a specific route
+ * to a destination multicast group is not found.  The system forwards 
+ * packets out the specified interface in the hope that "something out there"
+ * knows better how to route the packet.  This method is only used in 
+ * initially sending packets off of a host.  The default multicast route is
+ * not consulted during forwarding -- exact routes must be specified using
+ * AddMulticastRoute for that case.
+ *
+ * Since we're basically sending packets to some entity we think may know
+ * better what to do, we don't pay attention to "subtleties" like origin
+ * address, nor do we worry about forwarding out multiple  interfaces.  If the
+ * default multicast route is set, it is returned as the selected route from 
+ * LookupStatic irrespective of origin or multicast group if another specific
+ * route is not found.
+ *
+ * \param outputInterface The network interface index used to specify where
+ * to send packets in the case of unknown routes.
+ *
+ * \see Ipv4Address
+ */
+  void SetDefaultMulticastRoute (uint32_t outputInterface);
+
+/**
+ * \brief Get the number of individual multicast routes that have been added
+ * to the routing table.
+ *
+ * \warning The default multicast route counts as one of the routes.
+ */
+  uint32_t GetNMulticastRoutes (void) const;
+
+/**
+ * \brief Get a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ * 
+ * \param i The index (into the routing table) of the multicast route to
+ * retrieve.  
+ * \return If route \e i is set, a pointer to that Ipv4MulticastRoutingTableEntry is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * \see Ipv4MulticastRoutingTableEntry
+ * \see Ipv4StaticRouting::RemoveRoute
+ */
+  Ipv4MulticastRoutingTableEntry GetMulticastRoute (uint32_t i) const;
+
+/**
+ * \brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ * This method causes the multicast routing table to be searched for the first
+ * route that matches the parameters and removes it.
+ *
+ * Wildcards may be provided to this function, but the wildcards are used to
+ * exacly match wildcards in the routes (see AddMulticastRoute).  That is,
+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
+ * remove routes with any address in the origin, but will only remove routes
+ * with "0.0.0.0" set as the the origin.
+ *
+ * \param origin The IP address specified as the origin of packets for the
+ * route.
+ * \param group The IP address specified as the multicast group addres of
+ * the route.
+ * \param inputInterface The network interface index specified as the expected
+ * input interface for the route.
+ * \returns true if a route was found and removed, false otherwise.
+ *
+ * \see Ipv4MulticastRoutingTableEntry
+ * \see Ipv4StaticRouting::AddMulticastRoute
+ */
+  bool RemoveMulticastRoute (Ipv4Address origin,
+                             Ipv4Address group,
+                             uint32_t inputInterface);
+
+/**
+ * \brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ *
+ * \param index The index (into the multicast routing table) of the route to
+ * remove.  
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::GetRoute
+ * \see Ipv4StaticRouting::AddRoute
+ */
+  void RemoveMulticastRoute (uint32_t index);
+
+  void SetNode (Ptr<Node> node);
+  Ptr<Node> GetNode (void) const;
+
+protected:
+  void DoDispose (void);
+
+private:
+  typedef std::list<Ipv4RoutingTableEntry *> HostRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator HostRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator HostRoutesI;
+  typedef std::list<Ipv4RoutingTableEntry *> NetworkRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator NetworkRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator NetworkRoutesI;
+
+  typedef std::list<Ipv4MulticastRoutingTableEntry *> MulticastRoutes;
+  typedef std::list<Ipv4MulticastRoutingTableEntry *>::const_iterator MulticastRoutesCI;
+  typedef std::list<Ipv4MulticastRoutingTableEntry *>::iterator MulticastRoutesI;
+  
+  Ptr<Ipv4Route> LookupStatic (Ipv4Address dest);
+  Ptr<Ipv4MulticastRoute> LookupStatic (Ipv4Address origin, Ipv4Address group,
+                                    uint32_t interface);
+
+  HostRoutes m_hostRoutes;
+  NetworkRoutes m_networkRoutes;
+  Ipv4RoutingTableEntry *m_defaultRoute;
+  MulticastRoutes m_multicastRoutes;
+
+  Ptr<Node> m_node;
+};
+
+} // Namespace ns3
+
+#endif /* IPV4_STATIC_ROUTING_IMPL_H */
--- a/src/internet-stack/ipv4-static-routing.cc	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,654 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//         Gustavo Carneiro <gjc@inescporto.pt>
-
-#include "ns3/log.h"
-#include "ipv4-static-routing.h"
-#include "ns3/packet.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4StaticRouting");
-
-namespace ns3 {
-
-Ipv4StaticRouting::Ipv4StaticRouting () 
-: m_defaultRoute (0), m_defaultMulticastRoute (0)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-}
-
-void 
-Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, 
-                                   Ipv4Address nextHop, 
-                                   uint32_t interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
-  m_hostRoutes.push_back (route);
-}
-
-void 
-Ipv4StaticRouting::AddHostRouteTo (Ipv4Address dest, 
-                                   uint32_t interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateHostRouteTo (dest, interface);
-  m_hostRoutes.push_back (route);
-}
-
-void 
-Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, 
-                                      Ipv4Mask networkMask, 
-                                      Ipv4Address nextHop, 
-                                      uint32_t interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
-                                            networkMask,
-                                            nextHop,
-                                            interface);
-  m_networkRoutes.push_back (route);
-}
-
-void 
-Ipv4StaticRouting::AddNetworkRouteTo (Ipv4Address network, 
-                                      Ipv4Mask networkMask, 
-                                      uint32_t interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateNetworkRouteTo (network,
-                                            networkMask,
-                                            interface);
-  m_networkRoutes.push_back (route);
-}
-
-void 
-Ipv4StaticRouting::SetDefaultRoute (Ipv4Address nextHop, 
-                                    uint32_t interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Route *route = new Ipv4Route ();
-  *route = Ipv4Route::CreateDefaultRoute (nextHop, interface);
-  delete m_defaultRoute;
-  m_defaultRoute = route;
-}
-
-void 
-Ipv4StaticRouting::AddMulticastRoute(Ipv4Address origin,
-                                     Ipv4Address group,
-                                     uint32_t inputInterface,
-                                     std::vector<uint32_t> outputInterfaces)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
-  *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, 
-    inputInterface, outputInterfaces);
-  m_multicastRoutes.push_back (route);
-}
-
-void 
-Ipv4StaticRouting::SetDefaultMulticastRoute(uint32_t outputInterface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  Ipv4Address origin = Ipv4Address::GetAny ();
-  Ipv4Address group = Ipv4Address::GetAny ();
-  uint32_t inputInterface = Ipv4RoutingProtocol::INTERFACE_ANY;
-
-  std::vector<uint32_t> outputInterfaces (1);
-  outputInterfaces[0] = outputInterface;
-  
-  Ipv4MulticastRoute *route = new Ipv4MulticastRoute ();
-  *route = Ipv4MulticastRoute::CreateMulticastRoute (origin, group, 
-    inputInterface, outputInterfaces);
-
-  delete m_defaultMulticastRoute;
-  m_defaultMulticastRoute = route;
-}
-
-uint32_t 
-Ipv4StaticRouting::GetNMulticastRoutes (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_multicastRoutes.size () + m_defaultMulticastRoute ? 1 : 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::GetMulticastRoute (uint32_t index) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  NS_ASSERT_MSG(index < m_multicastRoutes.size (),
-    "Ipv4StaticRouting::GetMulticastRoute ():  Index out of range");
-//
-// From an external point of view the default route appears to be in slot 0
-// of the routing table.  The implementation, however, puts it in a separate 
-// place.  So, if a client asks for index 0 and we have a default multicast
-// route, we have to return it from that different place 
-// (m_defaultMulticastRoute).
-//
-  if (index == 0 && m_defaultMulticastRoute != 0)
-    {
-      return m_defaultMulticastRoute;
-    }
-//
-// If there is a default multicast route present, a client will just assume
-// that it is in slot zero and there is one "extra" zeroth route in the table.
-// To return the correct indexed entry in our list, we have to decrement the
-// index to take into account the default route not being in the actual list.
-// Since we fell through to here, we've taken care of the case where the
-// index was zero.
-//
-  if (m_defaultMulticastRoute != 0)
-    {
-      NS_ASSERT(index > 0);
-      index--;
-    }
-
-  if (index < m_multicastRoutes.size ())
-    {
-      uint32_t tmp = 0;
-      for (MulticastRoutesCI i = m_multicastRoutes.begin (); 
-           i != m_multicastRoutes.end (); 
-           i++) 
-        {
-          if (tmp  == index)
-            {
-              return *i;
-            }
-          tmp++;
-        }
-    }
-  return 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::GetDefaultMulticastRoute () const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (m_defaultMulticastRoute != 0)
-    {
-      return m_defaultMulticastRoute;
-    }
-  return 0;
-}
-
-bool
-Ipv4StaticRouting::RemoveMulticastRoute(Ipv4Address origin,
-                                        Ipv4Address group,
-                                        uint32_t inputInterface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i++) 
-    {
-      Ipv4MulticastRoute *route = *i;
-      if (origin == route->GetOrigin () &&
-          group == route->GetGroup () &&
-          inputInterface == route->GetInputInterface ())
-        {
-          delete *i;
-          m_multicastRoutes.erase (i);
-          return true;
-        }
-    }
-  return false;
-}
-
-void 
-Ipv4StaticRouting::RemoveMulticastRoute(uint32_t index)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-//
-// From an external point of view the default route appears to be in slot 0
-// of the routing table.  The implementation, however, puts it in a separate 
-// place.  So, if a client asks to delete index 0 and we have a default
-// multicast route set, we have to delete it from that different place 
-// (m_defaultMulticastRoute).
-//
-  if (index == 0 && m_defaultMulticastRoute != 0)
-    {
-      delete m_defaultMulticastRoute;
-      m_defaultMulticastRoute = 0;
-    }
-//
-// If there is a default multicast route present, a client will just assume
-// that it is in slot zero and there is one "extra" zeroth route in the table.
-// To return the correct indexed entry in our list, we have to decrement the
-// index to take into account the default route not being in the actual list.
-// Since we fell through to here, we've taken care of the case where the
-// index was zero.
-//
-  if (m_defaultMulticastRoute != 0)
-    {
-      NS_ASSERT(index > 0);
-      index--;
-    }
-
-  uint32_t tmp = 0;
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i++) 
-    {
-      if (tmp  == index)
-        {
-          delete *i;
-          m_multicastRoutes.erase (i);
-          return;
-        }
-      tmp++;
-    }
-}
-
-Ipv4Route *
-Ipv4StaticRouting::LookupStatic (Ipv4Address dest)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  for (HostRoutesCI i = m_hostRoutes.begin (); 
-       i != m_hostRoutes.end (); 
-       i++) 
-    {
-      NS_ASSERT ((*i)->IsHost ());
-      if ((*i)->GetDest ().IsEqual (dest)) 
-        {
-          return (*i);
-        }
-    }
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      NS_ASSERT ((*j)->IsNetwork ());
-      Ipv4Mask mask = (*j)->GetDestNetworkMask ();
-      Ipv4Address entry = (*j)->GetDestNetwork ();
-      if (mask.IsMatch (dest, entry)) 
-        {
-          return (*j);
-        }
-    }
-  if (m_defaultRoute != 0) 
-    {
-      NS_ASSERT (m_defaultRoute->IsDefault ());
-      return m_defaultRoute;
-    }
-  return 0;
-}
-
-Ipv4MulticastRoute *
-Ipv4StaticRouting::LookupStatic (
-  Ipv4Address origin, 
-  Ipv4Address group,
-  uint32_t    interface)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-//
-// We treat the "any" address (typically 0.0.0.0) as a wildcard in our matching
-// scheme.
-//
-  Ipv4Address wildcard = Ipv4Address::GetAny ();
-
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i++) 
-    {
-      Ipv4MulticastRoute *route = *i;
-//
-// We've been passed an origin address, a multicast group address and an 
-// interface index.  We have to decide if the current route in the list is
-// a match.
-//
-// The first case is the restrictive case where the origin, group and index
-// matches.  This picks up exact routes during forwarded and exact routes from
-// the local node (in which case the interface is a wildcard).
-//
-      if (origin == route->GetOrigin () && group == route->GetGroup ())
-        {
-          if (interface == Ipv4RoutingProtocol::INTERFACE_ANY || 
-              interface == route->GetInputInterface ())
-            {
-              return *i;
-            }
-        }
-    }
-//
-// If the input interface index is not a wildcard (that means that the packet 
-// did not originally come from this node), we're done.  We don't
-// just happily forward packets we don't really know what to do with.  
-// Multicast storms are not generally considered a good thing.
-//
-  if (interface != Ipv4RoutingProtocol::INTERFACE_ANY)
-    {
-      return 0;
-    }
-//
-// Now, we're going to get a litle less restricive.  This only applies in the
-// case where the packet in question is coming from the local node.  In order
-// to avoid dependencies on the order in which routes were added, we will 
-// actually walk the list two more times, the first time looking for routes
-// with a single wildcard, and the last time looking for the first route
-// with two wildcards.
-//
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i++) 
-    {
-      Ipv4MulticastRoute *route = *i;
-//
-// Here we will ignore the origin.  We know that a single source address must
-// be picked for a packet, but we may want to send multicast packets out
-// multiple interfaces.  To support this case, a user would need to add
-// a Multicast route with the route's origin set to wildcard.  N.B As a
-// result, packets sourced from a node with multiple interface may have a
-// source IP address different from that of the interface actually used to
-// send the packet.
-//
-      if (route->GetOrigin () == wildcard && group == route->GetGroup ())
-        {
-          return *i;
-        }
-    }
-//
-// Finally we want to allow users to specify a default route that specifies
-// sending all multicast packets out multiple interfaces.  The standard
-// default multicast route is patterned after other systems and limits the 
-// number of outputs to one.  If, however a client manually adds a multicast
-// route with the origin, the multicast group and the input interface index
-// all set to wildcard, she has created a default route with multiple output
-// interfaces.
-//
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i++) 
-    {
-      Ipv4MulticastRoute *route = *i;
-
-      if (route->GetOrigin () == wildcard && route->GetGroup () == wildcard)
-        {
-          return *i;
-        }
-    }
-//
-// We also allow users to specify a typical default multicast route.  This
-// default route is limited to specifying a single output interface.
-//
-  if (m_defaultMulticastRoute != 0) 
-    {
-      return m_defaultMulticastRoute;
-    }
-
-  return 0;
-}
-
-uint32_t 
-Ipv4StaticRouting::GetNRoutes (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  uint32_t n = 0;
-  if (m_defaultRoute != 0)
-    {
-      n++;
-    }
-  n += m_hostRoutes.size ();
-  n += m_networkRoutes.size ();
-  return n;
-}
-
-Ipv4Route *
-Ipv4StaticRouting::GetDefaultRoute ()
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (m_defaultRoute != 0)
-    {
-      return m_defaultRoute;
-    }
-  else
-    {
-      return 0;
-    }
-}
-
-Ipv4Route *
-Ipv4StaticRouting::GetRoute (uint32_t index)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (index == 0 && m_defaultRoute != 0)
-    {
-      return m_defaultRoute;
-    }
-  if (index > 0 && m_defaultRoute != 0)
-    {
-      index--;
-    }
-  if (index < m_hostRoutes.size ())
-    {
-      uint32_t tmp = 0;
-      for (HostRoutesCI i = m_hostRoutes.begin (); 
-           i != m_hostRoutes.end (); 
-           i++) 
-        {
-          if (tmp  == index)
-            {
-              return *i;
-            }
-          tmp++;
-        }
-    }
-  index -= m_hostRoutes.size ();
-  uint32_t tmp = 0;
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      if (tmp == index)
-        {
-          return *j;
-        }
-      tmp++;
-    }
-  NS_ASSERT (false);
-  // quiet compiler.
-  return 0;
-}
-void 
-Ipv4StaticRouting::RemoveRoute (uint32_t index)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  if (index == 0 && m_defaultRoute != 0)
-    {
-      delete m_defaultRoute;
-      m_defaultRoute = 0;
-    }
-  if (index > 0 && m_defaultRoute != 0)
-    {
-      index--;
-    }
-  if (index < m_hostRoutes.size ())
-    {
-      uint32_t tmp = 0;
-      for (HostRoutesI i = m_hostRoutes.begin (); 
-           i != m_hostRoutes.end (); 
-           i++) 
-        {
-          if (tmp  == index)
-            {
-              delete *i;
-              m_hostRoutes.erase (i);
-              return;
-            }
-          tmp++;
-        }
-    }
-  index -= m_hostRoutes.size ();
-  uint32_t tmp = 0;
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
-    {
-      if (tmp == index)
-        {
-          delete *j;
-          m_networkRoutes.erase (j);
-          return;
-        }
-      tmp++;
-    }
-  NS_ASSERT (false);
-}
-
-bool
-Ipv4StaticRouting::RequestRoute (
-  uint32_t interface,
-  Ipv4Header const &ipHeader,
-  Ptr<Packet> packet,
-  RouteReplyCallback routeReply)
-{
-  NS_LOG_FUNCTION (this << interface << &ipHeader << packet << &routeReply);
-
-  NS_LOG_LOGIC ("source = " << ipHeader.GetSource ());
-
-  NS_LOG_LOGIC ("destination = " << ipHeader.GetDestination ());
-
-  if (ipHeader.GetDestination ().IsMulticast ())
-    {
-      NS_LOG_LOGIC ("Multicast destination");
-
-      Ipv4MulticastRoute *mRoute = LookupStatic(ipHeader.GetSource (),
-        ipHeader.GetDestination (), interface);
-
-      if (mRoute)
-        {
-          NS_LOG_LOGIC ("Multicast route found");
-
-          for (uint32_t i = 0; i < mRoute->GetNOutputInterfaces (); ++i)
-            {
-              Ptr<Packet> p = packet->Copy ();
-              Ipv4Header h = ipHeader;
-              Ipv4Route route = 
-                Ipv4Route::CreateHostRouteTo(h.GetDestination (), 
-                  mRoute->GetOutputInterface(i));
-              NS_LOG_LOGIC ( "Send via interface " << 
-                mRoute->GetOutputInterface(i));
-              routeReply (true, route, p, h);
-            }
-          return true;
-        }
-      return false; // Let other routing protocols try to handle this
-    }
-//
-// This is a unicast packet.  Check to see if we have a route for it.
-//
-  NS_LOG_LOGIC ("Unicast destination");
-  Ipv4Route *route = LookupStatic (ipHeader.GetDestination ());
-  if (route != 0)
-    {
-      routeReply (true, *route, packet, ipHeader);
-      return true;
-    }
-  else
-    {
-      return false; // Let other routing protocols try to handle this
-                    // route request.
-    }
-}
-
-bool
-Ipv4StaticRouting::RequestInterface (Ipv4Address destination, uint32_t& interface)
-{
-  NS_LOG_FUNCTION (this << destination << &interface);
-//
-// First, see if this is a multicast packet we have a route for.  If we
-// have a route, then send the packet down each of the specified interfaces.
-//
-  if (destination.IsMulticast ())
-    {
-      NS_LOG_LOGIC ("Multicast destination");
-
-      Ipv4MulticastRoute *mRoute = LookupStatic(Ipv4Address::GetAny (),
-        destination, Ipv4RoutingProtocol::INTERFACE_ANY);
-
-      if (mRoute)
-        {
-          NS_LOG_LOGIC ("Multicast route found");
-
-          if (mRoute->GetNOutputInterfaces () != 1)
-            {
-              NS_LOG_LOGIC ("Route is to multiple interfaces.  Ignoring.");
-              return false;
-            }
-
-          interface = mRoute->GetOutputInterface(0);
-          NS_LOG_LOGIC ("Found interface " << interface);
-          return true;
-        }
-      return false; // Let other routing protocols try to handle this
-    }
-//
-// See if this is a unicast packet we have a route for.
-//
-  NS_LOG_LOGIC ("Unicast destination");
-  Ipv4Route *route = LookupStatic (destination);
-  if (route)
-    {
-      interface = route->GetInterface ();
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
-void
-Ipv4StaticRouting::DoDispose (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  for (HostRoutesI i = m_hostRoutes.begin (); 
-       i != m_hostRoutes.end (); 
-       i = m_hostRoutes.erase (i)) 
-    {
-      delete (*i);
-    }
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j = m_networkRoutes.erase (j)) 
-    {
-      delete (*j);
-    }
-  if (m_defaultRoute != 0)
-    {
-      delete m_defaultRoute;
-      m_defaultRoute = 0;
-    }
-  for (MulticastRoutesI i = m_multicastRoutes.begin (); 
-       i != m_multicastRoutes.end (); 
-       i = m_multicastRoutes.erase (i)) 
-    {
-      delete (*i);
-    }
-  if (m_defaultMulticastRoute != 0)
-    {
-      delete m_defaultMulticastRoute;
-      m_defaultMulticastRoute = 0;
-    }
-  Ipv4RoutingProtocol::DoDispose ();
-}
-
-}//namespace ns3
--- a/src/internet-stack/ipv4-static-routing.h	Sat May 30 17:36:50 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,506 +0,0 @@
-// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License version 2 as
-// published by the Free Software Foundation;
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-//
-// Author: George F. Riley<riley@ece.gatech.edu>
-//         Gustavo Carneiro <gjc@inescporto.pt>
-//
-
-#ifndef IPV4_STATIC_ROUTING_H
-#define IPV4_STATIC_ROUTING_H
-
-#include <list>
-#include <stdint.h>
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/ptr.h"
-#include "ns3/ipv4.h"
-
-namespace ns3 {
-
-class Packet;
-class NetDevice;
-class Ipv4Interface;
-class Ipv4Address;
-class Ipv4Header;
-class Ipv4Route;
-class Node;
-
-
-/**
- * @brief Static routing protocol for IP version 4 stacks.
- *
- * In ns-3 we have the concept of a pluggable routing protocol.  Routing
- * protocols are added to a list maintained by the Ipv4L3Protocol.  Every 
- * stack gets one routing protocol for free -- the Ipv4StaticRouting routing
- * protocol is added in the constructor of the Ipv4L3Protocol (this is the 
- * piece of code that implements the functionality of the IP layer).
- *
- * The Ipv4StaticRouting class inherits from the abstract base class 
- * Ipv4RoutingProtocol that defines the interface methods that a routing 
- * protocol must support.
- *
- * When a packet arrives in the Ipv4L3Protocol for transmission, it comes
- * either from a local source via Ipv4L3Protocol::Send or from a remote 
- * source via Ipv4L3Protocol::Forwarding.  In both cases, a function is called
- * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet.
- *
- * The lookup function iterates through the list of routing protocols asking
- * each to see if it can find a route and send the packet.  A callback is 
- * provided during each of these calls that should be considered a pre-
- * packaged send call.  This is done to allow asynchronous calls into 
- * routing subsystems in order to support on-demand routing, for example.  The
- * method for requesting this operation is Ipv4StaticRouting::RequestRoute for
- * the static routing protocol.
- *
- * Each routing protocol is also free to implement its own methods for managing
- * routes which you will find below.  This class manages a set of "static" or
- * manually configured routes for host, network and multicast routes.
- *
- * @see Ipv4RoutingProtocol
- * @see Ipv4L3Protocol::AddRoutingProtocol
- * @see Ipv4L3Protocol::Ipv4L3Protocol
- */
-class Ipv4StaticRouting : public Ipv4RoutingProtocol
-{
-public:
-/**
- * @brief Construct an empty Ipv4StaticRouting routing protocol,
- * @internal
- *
- * The Ipv4StaticRouting class supports host, network and multicast routes.
- * This method initializes the lists containing these routes to empty.
- *
- * @see Ipv4StaticRouting
- */
-  Ipv4StaticRouting ();
-
-/**
- * @brief Request that a check for a route bw performed and if a route is found
- * that the packet be sent on its way using the pre-packaged send callback.
- *
- * The source and destination IP addresses for the packet in question are found
- * in the provided Ipv4Header.  There are two major processing forks depending
- * on the type of destination address.  
- *
- * If the destination address is unicast then the routing table is consulted 
- * for a route to the destination and if it is found, the routeReply callback
- * is executed to send the packet (with the found route).
- * 
- * If the destination address is a multicast, then the exact processing steps
- * depend on whether or not the packet has been sourced locally.  This is 
- * determined by the parameter interface.  This is the interface index over which
- * this packet was received.  If the packet has not been received over a
- * network interface, this index will be set to 
- * Ipv4RoutingProtocol::INTERFACE_INDEX_ANY (a very large number).  In that case, 
- * we want to avoid the requirement that an explicit route out of each node 
- * must be set, so we don't do anything here.
- * 
- * If the packet is a multicast destination and has been received over a 
- * network interface, a call to this method implies that the packet is being
- * forwarded.  In that case, there must be an explicit route out of the node.
- * A multicast route references the source address, the destination address
- * (the multicast group) and the input interface in order to find a route.
- * We consult the multicast routing table and, if a route is found, send the
- * packet out of as many interfaces as required using the provided callback
- * (think of it as a pre-packaged send call).
- *
- * @param interface The network interface index over which the packed was 
- * received.  If the packet is from a local source, interface will be set to
- * Ipv4RoutingProtocol::INTERFACE_ANY.
- * @param ipHeader the Ipv4Header containing the source and destination IP
- * addresses for the packet.
- * @param packet The packet to be sent if a route is found.
- * @param routeReply A callback that packaged up the call to actually send the
- * packet.
- * @return Returns true if a route is found and the packet has been sent,
- * otherwise returns false indicating that the next routing protocol should
- * be consulted.  In practice, the static routing protocol is the last chance
- * protocol.
- *
- * @see Ipv4StaticRouting
- * @see Ipv4RoutingProtocol
- */
-  virtual bool RequestRoute (uint32_t interface,
-                             Ipv4Header const &ipHeader,
-                             Ptr<Packet> packet,
-                             RouteReplyCallback routeReply);
-
-/**
- * @brief Check to see if we can determine the interface index that will be
- * used if a packet is sent to this destination.
- *
- * This method addresses a problem in the IP stack where a destination address
- * must be present and checksummed into the IP header before the actual 
- * interface over which the packet is sent can be determined.  The answer is
- * to implement a known and intentional cross-layer violation.  This is the
- * endpoint of a call chain that started up quite high in the stack (sockets)
- * and has found its way down to the Ipv4L3Protocol which is consulting the
- * routing protocols for what they would do if presented with a packet of the
- * given destination.
- *
- * Note that the a single interface index is returned.  This means that if
- * the destination address is a multicast, and an explicit route is present
- * that includeds multiple output interfaces, that route cannot be used.
- * 
- * If there are multiple paths out of the node, the resolution is performed
- * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more 
- * contextual information that is useful for making a determination.
- *
- * @param destination The Ipv4Address if the destination of a hypothetical 
- * packet.  This may be a multicast group address.
- * @param interface A reference to the interface index over which a packet
- * sent to this destination would be sent.
- * @return Returns true if a route is found to the destination that involves
- * a single output interface index, otherwise returns false indicating that
- * the next routing protocol should be consulted.  In practice, the static 
- * routing protocol is the last chance protocol.
- *
- * @see Ipv4StaticRouting
- * @see Ipv4RoutingProtocol
- * @see Ipv4L3Protocol
- */
-  virtual bool RequestInterface (Ipv4Address destination, uint32_t& interface);
-
-/**
- * @brief Add a host route to the static routing table.
- *
- * @param dest The Ipv4Address destination for this route.
- * @param nextHop The Ipv4Address of the next hop in the route.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
-  void AddHostRouteTo (Ipv4Address dest, 
-                       Ipv4Address nextHop, 
-                       uint32_t interface);
-/**
- * @brief Add a host route to the static routing table.
- *
- * @param dest The Ipv4Address destination for this route.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
-  void AddHostRouteTo (Ipv4Address dest, 
-                       uint32_t interface);
-
-/**
- * @brief Add a network route to the static routing table.
- *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param nextHop The next hop in the route to the destination network.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
-  void AddNetworkRouteTo (Ipv4Address network, 
-                          Ipv4Mask networkMask, 
-                          Ipv4Address nextHop, 
-                          uint32_t interface);
-
-/**
- * @brief Add a network route to the static routing table.
- *
- * @param network The Ipv4Address network for this route.
- * @param networkMask The Ipv4Mask to extract the network.
- * @param interface The network interface index used to send packets to the
- * destination.
- *
- * @see Ipv4Address
- */
-  void AddNetworkRouteTo (Ipv4Address network, 
-                          Ipv4Mask networkMask, 
-                          uint32_t interface);
-
-/**
- * @brief Add a default route to the static routing table.
- *
- * This method tells the routing system what to do in the case where a specific
- * route to a destination is not found.  The system forwards packets to the
- * specified node in the hope that it knows better how to route the packet.
- * 
- * If the default route is set, it is returned as the selected route from 
- * LookupStatic irrespective of destination address if no specific route is
- * found.
- *
- * @param nextHop The Ipv4Address to send packets to in the hope that they
- * will be forwarded correctly.
- * @param interface The network interface index used to send packets.
- *
- * @see Ipv4Address
- * @see Ipv4StaticRouting::Lookup
- */
-  void SetDefaultRoute (Ipv4Address nextHop, 
-                        uint32_t interface);
-
-/**
- * @brief Get the number of individual unicast routes that have been added
- * to the routing table.
- *
- * @warning The default route counts as one of the routes.
- */
-  uint32_t GetNRoutes (void);
-
-/**
- * @brief Get the default route from the static routing table.
- *
- * @return If the default route is set, a pointer to that Ipv4Route is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4Route
- */
-  Ipv4Route *GetDefaultRoute (void);
-
-/**
- * @brief Get a route from the static unicast routing table.
- *
- * Externally, the unicast static routing table appears simply as a table with
- * n entries.  The one sublety of note is that if a default route has been set
- * it will appear as the zeroth entry in the table.  This means that if you
- * add only a default route, the table will have one entry that can be accessed
- * either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
- * 
- * Similarly, if the default route has been set, calling RemoveRoute (0) will
- * remove the default route.
- *
- * @param i The index (into the routing table) of the route to retrieve.  If
- * the default route has been set, it will occupy index zero.
- * @return If route is set, a pointer to that Ipv4Route is returned, otherwise
- * a zero pointer is returned.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::RemoveRoute
- */
-  Ipv4Route *GetRoute (uint32_t i);
-
-/**
- * @brief Remove a route from the static unicast routing table.
- *
- * Externally, the unicast static routing table appears simply as a table with
- * n entries.  The one sublety of note is that if a default route has been set
- * it will appear as the zeroth entry in the table.  This means that if the
- * default route has been set, calling RemoveRoute (0) will remove the
- * default route.
- *
- * @param i The index (into the routing table) of the route to remove.  If
- * the default route has been set, it will occupy index zero.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::GetRoute
- * @see Ipv4StaticRouting::AddRoute
- */
-  void RemoveRoute (uint32_t i);
-
-/**
- * @brief Add a multicast route to the static routing table.
- *
- * A multicast route must specify an origin IP address, a multicast group and
- * an input network interface index as conditions and provide a vector of
- * output network interface indices over which packets matching the conditions
- * are sent.
- *
- * Typically there are two main types of multicast routes:  routes of the 
- * first kind are used during forwarding.  All of the conditions must be
- * exlicitly provided.  The second kind of routes are used to get packets off
- * of a local node.  The difference is in the input interface.  Routes for
- * forwarding will always have an explicit input interface specified.  Routes
- * off of a node will always set the input interface to a wildcard specified
- * by the index Ipv4RoutingProtocol::INTERFACE_ANY.
- *
- * For routes off of a local node wildcards may be used in the origin and
- * multicast group addresses.  The wildcard used for Ipv4Adresses is that 
- * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0".  Usage
- * of a wildcard allows one to specify default behavior to varying degrees.
- *
- * For example, making the origin address a wildcard, but leaving the 
- * multicast group specific allows one (in the case of a node with multiple
- * interfaces) to create different routes using different output interfaces
- * for each multicast group.
- *
- * If the origin and multicast addresses are made wildcards, you have created
- * essentially a default multicast address that can forward to multiple 
- * interfaces.  Compare this to the actual default multicast address that is
- * limited to specifying a single output interface for compatibility with
- * existing functionality in other systems.
- * 
- * @param origin The Ipv4Address of the origin of packets for this route.  May
- * be Ipv4Address:GetAny for open groups.
- * @param group The Ipv4Address of the multicast group or this route.
- * @param inputInterface The input network interface index over which to 
- * expect packets destined for this route.  May be
- * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin.
- * @param outputInterfaces A vector of network interface indices used to specify
- * how to send packets to the destination(s).
- *
- * @see Ipv4Address
- */
-  void AddMulticastRoute (Ipv4Address origin,
-                          Ipv4Address group,
-                          uint32_t inputInterface,
-                          std::vector<uint32_t> outputInterfaces);
-
-/**
- * @brief Add a default multicast route to the static routing table.
- *
- * This is the multicast equivalent of the unicast version SetDefaultRoute.
- * We tell the routing system what to do in the case where a specific route
- * to a destination multicast group is not found.  The system forwards 
- * packets out the specified interface in the hope that "something out there"
- * knows better how to route the packet.  This method is only used in 
- * initially sending packets off of a host.  The default multicast route is
- * not consulted during forwarding -- exact routes must be specified using
- * AddMulticastRoute for that case.
- *
- * Since we're basically sending packets to some entity we think may know
- * better what to do, we don't pay attention to "subtleties" like origin
- * address, nor do we worry about forwarding out multiple  interfaces.  If the
- * default multicast route is set, it is returned as the selected route from 
- * LookupStatic irrespective of origin or multicast group if another specific
- * route is not found.
- *
- * @param outputInterface The network interface index used to specify where
- * to send packets in the case of unknown routes.
- *
- * @see Ipv4Address
- */
-  void SetDefaultMulticastRoute (uint32_t outputInterface);
-
-/**
- * @brief Get the number of individual multicast routes that have been added
- * to the routing table.
- *
- * @warning The default multicast route counts as one of the routes.
- */
-  uint32_t GetNMulticastRoutes (void) const;
-
-/**
- * @brief Get a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table 
- * with n entries.  The one sublety of note is that if a default route has 
- * been set it will appear as the zeroth entry in the table.  This means that 
- * if you add only a default route, the table will have one entry that can be
- * accessed either by explicity calling GetDefaultMulticastRoute () or by
- * calling GetMulticastRoute (0).
- * 
- * Similarly, if the default route has been set, calling 
- * RemoveMulticastRoute (0) will remove the default route.
- *
- * @param i The index (into the routing table) of the multicast route to
- * retrieve.  If the default route has been set, it will occupy index zero.
- * @return If route \e i is set, a pointer to that Ipv4MulticastRoute is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4MulticastRoute
- * @see Ipv4StaticRouting::RemoveRoute
- */
-  Ipv4MulticastRoute *GetMulticastRoute (uint32_t i) const;
-
-/**
- * @brief Get the default multicast route from the static routing table.
- *
- * @return If the default route is set, a pointer to that Ipv4MulticastRoute is
- * returned, otherwise a zero pointer is returned.
- *
- * @see Ipv4Route
- */
-  Ipv4MulticastRoute *GetDefaultMulticastRoute (void) const;
-
-/**
- * @brief Remove a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table 
- * with n entries.  The one sublety of note is that if a default multicast
- * route has been set it will appear as the zeroth entry in the table.  This
- * means that the default route may be removed by calling this method with
- * appropriate wildcard parameters.
- *
- * This method causes the multicast routing table to be searched for the first
- * route that matches the parameters and removes it.
- *
- * Wildcards may be provided to this function, but the wildcards are used to
- * exacly match wildcards in the routes (see AddMulticastRoute).  That is,
- * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
- * remove routes with any address in the origin, but will only remove routes
- * with "0.0.0.0" set as the the origin.
- *
- * @param origin The IP address specified as the origin of packets for the
- * route.
- * @param group The IP address specified as the multicast group addres of
- * the route.
- * @param inputInterface The network interface index specified as the expected
- * input interface for the route.
- * @returns true if a route was found and removed, false otherwise.
- *
- * @see Ipv4MulticastRoute
- * @see Ipv4StaticRouting::AddMulticastRoute
- */
-  bool RemoveMulticastRoute (Ipv4Address origin,
-                             Ipv4Address group,
-                             uint32_t inputInterface);
-
-/**
- * @brief Remove a route from the static multicast routing table.
- *
- * Externally, the multicast static routing table appears simply as a table 
- * with n entries.  The one sublety of note is that if a default multicast
- * route has been set it will appear as the zeroth entry in the table.  This 
- * means that if the default route has been set, calling 
- * RemoveMulticastRoute (0) will remove the default route.
- *
- * @param index The index (into the multicast routing table) of the route to
- * remove.  If the default route has been set, it will occupy index zero.
- *
- * @see Ipv4Route
- * @see Ipv4StaticRouting::GetRoute
- * @see Ipv4StaticRouting::AddRoute
- */
-  void RemoveMulticastRoute (uint32_t index);
-
-protected:
-  void DoDispose (void);
-
-private:
-  typedef std::list<Ipv4Route *> HostRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator HostRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator HostRoutesI;
-  typedef std::list<Ipv4Route *> NetworkRoutes;
-  typedef std::list<Ipv4Route *>::const_iterator NetworkRoutesCI;
-  typedef std::list<Ipv4Route *>::iterator NetworkRoutesI;
-
-  typedef std::list<Ipv4MulticastRoute *> MulticastRoutes;
-  typedef std::list<Ipv4MulticastRoute *>::const_iterator MulticastRoutesCI;
-  typedef std::list<Ipv4MulticastRoute *>::iterator MulticastRoutesI;
-
-  Ipv4Route *LookupStatic (Ipv4Address dest);
-  Ipv4MulticastRoute *LookupStatic (Ipv4Address origin, Ipv4Address group,
-                                    uint32_t interface);
-
-  HostRoutes m_hostRoutes;
-  NetworkRoutes m_networkRoutes;
-  Ipv4Route *m_defaultRoute;
-  Ipv4MulticastRoute *m_defaultMulticastRoute;
-  MulticastRoutes m_multicastRoutes;
-};
-
-} // Namespace ns3
-
-#endif /* IPV4_STATIC_ROUTING_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/loopback-net-device.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,234 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "loopback-net-device.h"
+#include "ns3/log.h"
+#include "ns3/channel.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+
+NS_LOG_COMPONENT_DEFINE ("LoopbackNetDevice");
+
+namespace ns3 {
+
+TypeId 
+LoopbackNetDevice::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LoopbackNetDevice")
+    .SetParent<NetDevice> ()
+    .AddConstructor<LoopbackNetDevice> ()
+    ;
+  return tid;
+}
+
+LoopbackNetDevice::LoopbackNetDevice ()
+  : m_node (0),
+    m_mtu (0xffff),
+    m_ifIndex (0),
+    m_address (Mac48Address ("00:00:00:00:00:00"))
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void 
+LoopbackNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol, 
+                            Mac48Address to, Mac48Address from)
+{
+  NS_LOG_FUNCTION (packet << " " << protocol << " " << to << " " << from);
+  NetDevice::PacketType packetType;
+  if (to == m_address)
+    {
+      packetType = NetDevice::PACKET_HOST;
+    }
+  else if (to.IsBroadcast ())
+    {
+      packetType = NetDevice::PACKET_HOST;
+    }
+  else if (to.IsGroup ())
+    {
+      packetType = NetDevice::PACKET_MULTICAST;
+    }
+  else 
+    {
+      packetType = NetDevice::PACKET_OTHERHOST;
+    }
+  m_rxCallback (this, packet, protocol, from);
+  if (!m_promiscCallback.IsNull ())
+    {
+      m_promiscCallback (this, packet, protocol, from, to, packetType);
+    }
+}
+
+void 
+LoopbackNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+
+uint32_t 
+LoopbackNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+
+Ptr<Channel> 
+LoopbackNetDevice::GetChannel (void) const
+{
+  return 0;
+}
+
+Address 
+LoopbackNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+
+bool 
+LoopbackNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+
+uint16_t 
+LoopbackNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+
+bool 
+LoopbackNetDevice::IsLinkUp (void) const
+{
+  return true;
+}
+
+void 
+LoopbackNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{}
+
+bool 
+LoopbackNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
+
+Address
+LoopbackNetDevice::GetBroadcast (void) const
+{
+  // This is typically set to all zeros rather than all ones in real systems
+  return Mac48Address ("00:00:00:00:00:00");
+}
+
+bool 
+LoopbackNetDevice::IsMulticast (void) const
+{
+  // Multicast loopback will need to be supported for outgoing 
+  // datagrams but this will probably be handled in multicast sockets
+  return false;
+}
+
+Address 
+LoopbackNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+  return Mac48Address::GetMulticast (multicastGroup);
+}
+
+Address LoopbackNetDevice::GetMulticast (Ipv6Address addr) const
+{
+	return Mac48Address::GetMulticast (addr);
+}
+
+bool 
+LoopbackNetDevice::IsPointToPoint (void) const
+{
+  return false;
+}
+
+bool 
+LoopbackNetDevice::IsBridge (void) const
+{
+  return false;
+}
+
+bool 
+LoopbackNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (packet << " " << dest << " " << protocolNumber);
+  Mac48Address to = Mac48Address::ConvertFrom (dest);
+  NS_ASSERT_MSG (to == GetBroadcast () || to == m_address, "Invalid destination address");
+  Receive (packet, protocolNumber, to, m_address);
+  return true;
+}
+
+bool 
+LoopbackNetDevice::SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (packet << " " << source << " " << dest << " " << protocolNumber);
+  Mac48Address to = Mac48Address::ConvertFrom (dest);
+  Mac48Address from = Mac48Address::ConvertFrom (source);
+  NS_ASSERT_MSG (to.IsBroadcast () || to == m_address, "Invalid destination address");
+  Receive (packet, protocolNumber, to, from);
+  return true;
+}
+
+Ptr<Node> 
+LoopbackNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+
+void 
+LoopbackNetDevice::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+bool 
+LoopbackNetDevice::NeedsArp (void) const
+{
+  return false;
+}
+
+void 
+LoopbackNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
+}
+
+void
+LoopbackNetDevice::DoDispose (void)
+{
+  m_node = 0;
+  NetDevice::DoDispose ();
+}
+
+
+void
+LoopbackNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)
+{
+  m_promiscCallback = cb;
+}
+
+bool
+LoopbackNetDevice::SupportsSendFrom (void) const
+{
+  return true;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/loopback-net-device.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef LOOPBACK_NET_DEVICE_H
+#define LOOPBACK_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include <stdint.h>
+#include <string>
+
+namespace ns3 {
+
+class Node;
+
+/**
+ * \ingroup netdevice
+ * 
+ * \brief Virtual network interface that loops back any data sent to it to
+ *        be immediately received on the same interface
+ */
+class LoopbackNetDevice : public NetDevice
+{
+public:
+  static TypeId GetTypeId (void);
+  LoopbackNetDevice ();
+
+  // inherited from NetDevice base class.
+  virtual void SetIfIndex(const uint32_t index);
+  virtual uint32_t GetIfIndex(void) const;
+  virtual Ptr<Channel> GetChannel (void) const;
+  virtual Address GetAddress (void) const;
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+  virtual bool IsLinkUp (void) const;
+  virtual void SetLinkChangeCallback (Callback<void> callback);
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool IsBridge (void) const;
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool SendFrom(Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual void SetNode (Ptr<Node> node);
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
+  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
+  virtual bool SupportsSendFrom (void) const;
+
+protected:
+  virtual void DoDispose (void);
+private:
+  void Receive (Ptr<Packet> packet, uint16_t protocol, Mac48Address to, Mac48Address from);
+  NetDevice::ReceiveCallback m_rxCallback;
+  NetDevice::PromiscReceiveCallback m_promiscCallback;
+  Ptr<Node> m_node;
+  uint16_t m_mtu;
+  uint32_t m_ifIndex;
+  Mac48Address m_address;
+};
+
+} // namespace ns3
+
+#endif /* LOOPBACK_NET_DEVICE_H */
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -23,15 +23,17 @@
 
 #include "ns3/packet.h"
 #include "ns3/node.h"
+#include "ns3/ipv4-route.h"
 
 #include "ns3/object-vector.h"
-
+#include "ns3/string.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-sysctl.h"
+#include "nsc-tcp-socket-factory-impl.h"
 
 #include "tcp-typedefs.h"
 
@@ -65,7 +67,7 @@
 {
   static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
     .SetParent<Ipv4L4Protocol> ()
-
+    .AddConstructor<NscTcpL4Protocol>()
     .AddAttribute ("RttEstimatorFactory",
                    "How RttEstimator objects are created.",
                    ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
@@ -75,6 +77,12 @@
                    ObjectVectorValue (),
                    MakeObjectVectorAccessor (&NscTcpL4Protocol::m_sockets),
                    MakeObjectVectorChecker<NscTcpSocketImpl> ())
+    .AddAttribute ("Library",
+                   "Set the linux library to be used to create the stack",
+                   TypeId::ATTR_GET|TypeId::ATTR_CONSTRUCT,
+                   StringValue("liblinux2.6.26.so"),
+                   MakeStringAccessor (&NscTcpL4Protocol::GetNscLibrary,&NscTcpL4Protocol::SetNscLibrary),
+                   MakeStringChecker ())
     ;
   return tid;
 }
@@ -101,13 +109,22 @@
 
 void
 NscTcpL4Protocol::SetNscLibrary(const std::string &soname)
-{
-  NS_ASSERT(!m_dlopenHandle);
-  m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
-  if (m_dlopenHandle == NULL)
-    NS_FATAL_ERROR (dlerror());
+{    
+  if (soname!="")
+    {
+      m_nscLibrary = soname;
+      NS_ASSERT(!m_dlopenHandle);
+      m_dlopenHandle = dlopen(soname.c_str (), RTLD_NOW);
+      if (m_dlopenHandle == NULL)
+        NS_FATAL_ERROR (dlerror());
+    }
 }
 
+std::string 
+NscTcpL4Protocol::GetNscLibrary () const
+{
+  return m_nscLibrary;
+}
 void 
 NscTcpL4Protocol::SetNode (Ptr<Node> node)
 {
@@ -144,6 +161,23 @@
   Simulator::ScheduleNow (&NscTcpL4Protocol::AddInterface, this);
 }
 
+void
+NscTcpL4Protocol::NotifyNewAggregate ()
+{ 
+  bool is_not_initialized = (m_node == 0);
+  Ptr<Node>node = this->GetObject<Node> ();
+  Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+  if (is_not_initialized && node!= 0 && ipv4 != 0)
+    {
+      this->SetNode (node);
+      ipv4->Insert (this);
+      Ptr<NscTcpSocketFactoryImpl> tcpFactory = CreateObject<NscTcpSocketFactoryImpl> ();
+      tcpFactory->SetTcp (this);
+      node->AggregateObject (tcpFactory);
+    }
+  Object::NotifyNewAggregate ();
+}
+
 int 
 NscTcpL4Protocol::GetProtocolNumber (void) const
 {
@@ -302,7 +336,7 @@
   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
   NS_ASSERT_MSG (ipv4, "nsc callback invoked, but node has no ipv4 object");
 
-  ipv4->Send (p, saddr, daddr, PROT_NUMBER);
+  ipv4->Send (p, saddr, daddr, PROT_NUMBER, 0);
   m_nscStack->if_send_finish(0);
 }
 
--- a/src/internet-stack/nsc-tcp-l4-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -54,8 +54,8 @@
   virtual ~NscTcpL4Protocol ();
 
   void SetNode (Ptr<Node> node);
-  void SetNscLibrary(const std::string &lib);
-
+  void SetNscLibrary (const std::string &lib);
+  std::string GetNscLibrary (void) const;
   virtual int GetProtocolNumber (void) const;
   virtual int GetVersion (void) const;
 
@@ -105,6 +105,7 @@
 
 protected:
   virtual void DoDispose (void);
+  virtual void NotifyNewAggregate ();
 private:
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
@@ -116,6 +117,7 @@
   friend class NscTcpSocketImpl;
   INetStack* m_nscStack;
   void *m_dlopenHandle;
+  std::string m_nscLibrary;
   Timer m_softTimer;
   std::vector<Ptr<NscTcpSocketImpl> > m_sockets;
 };
--- a/src/internet-stack/tcp-l4-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/tcp-l4-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -26,12 +26,14 @@
 
 #include "ns3/packet.h"
 #include "ns3/node.h"
+#include "ns3/ipv4-route.h"
 
 #include "tcp-l4-protocol.h"
 #include "tcp-header.h"
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
+#include "tcp-socket-factory-impl.h"
 
 #include "tcp-typedefs.h"
 
@@ -324,6 +326,7 @@
 {
   static TypeId tid = TypeId ("ns3::TcpL4Protocol")
     .SetParent<Ipv4L4Protocol> ()
+    .AddConstructor<TcpL4Protocol> ()
     .AddAttribute ("RttEstimatorFactory",
                    "How RttEstimator objects are created.",
                    ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
@@ -360,6 +363,28 @@
   m_node = node;
 }
 
+/* 
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the TCP stack, link it to the ipv4 stack and 
+ * adding TCP socket factory to the node.
+ */
+void
+TcpL4Protocol::NotifyNewAggregate ()
+{
+  bool is_not_initialized = (m_node == 0);
+  Ptr<Node>node = this->GetObject<Node> ();
+  Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+  if (is_not_initialized && node!= 0 && ipv4 != 0)
+    {
+      this->SetNode (node);
+      ipv4->Insert (this);
+      Ptr<TcpSocketFactoryImpl> tcpFactory = CreateObject<TcpSocketFactoryImpl> ();
+      tcpFactory->SetTcp (this);
+      node->AggregateObject (tcpFactory);
+    }
+  Object::NotifyNewAggregate ();
+}
+
 int 
 TcpL4Protocol::GetProtocolNumber (void) const
 {
@@ -520,7 +545,15 @@
     m_node->GetObject<Ipv4L3Protocol> ();
   if (ipv4 != 0)
     {
-      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+      // XXX We've already performed the route lookup in TcpSocketImpl
+      // should be cached.
+      Ipv4Header header;
+      header.SetDestination (daddr);
+      Socket::SocketErrno errno;
+      Ptr<Ipv4Route> route;
+      uint32_t oif = 0; //specify non-zero if bound to a source address
+      route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
     }
 }
 
@@ -550,7 +583,15 @@
     m_node->GetObject<Ipv4L3Protocol> ();
   if (ipv4 != 0)
     {
-      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+      // XXX We've already performed the route lookup in TcpSocketImpl
+      // should be cached.
+      Ipv4Header header;
+      header.SetDestination (daddr);
+      Socket::SocketErrno errno;
+      Ptr<Ipv4Route> route;
+      uint32_t oif = 0; //specify non-zero if bound to a source address
+      route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
     }
   else
     NS_FATAL_ERROR("Trying to use Tcp on a node without an Ipv4 interface");
--- a/src/internet-stack/tcp-l4-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/tcp-l4-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -109,6 +109,11 @@
 
 protected:
   virtual void DoDispose (void);
+  /* 
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
 private:
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
--- a/src/internet-stack/tcp-socket-impl.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/tcp-socket-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -23,6 +23,8 @@
 #include "ns3/inet-socket-address.h"
 #include "ns3/log.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv4-interface-address.h"
+#include "ns3/ipv4-route.h"
 #include "tcp-socket-impl.h"
 #include "tcp-l4-protocol.h"
 #include "ipv4-end-point.h"
@@ -327,6 +329,9 @@
 TcpSocketImpl::Connect (const Address & address)
 {
   NS_LOG_FUNCTION (this << address);
+
+  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
   if (m_endPoint == 0)
     {
       if (Bind () == -1)
@@ -340,17 +345,31 @@
   m_remoteAddress = transport.GetIpv4 ();
   m_remotePort = transport.GetPort ();
   
-  uint32_t localInterface;
-  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
-
-  if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface))
+  if (ipv4->GetRoutingProtocol () != 0)
     {
-      m_endPoint->SetLocalAddress (ipv4->GetSourceAddress (m_remoteAddress));
+      Ipv4Header header;
+      header.SetDestination (m_remoteAddress);
+      Socket::SocketErrno errno;
+      Ptr<Ipv4Route> route;
+      uint32_t oif = 0; //specify non-zero if bound to a source address
+      // XXX here, cache the route in the endpoint?
+      route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+      if (route != 0)
+        {
+          NS_LOG_LOGIC ("Route exists");
+          m_endPoint->SetLocalAddress (route->GetSource ());
+        }
+      else
+        {
+          NS_LOG_LOGIC ("TcpSocketImpl::Connect():  Route to " << m_remoteAddress << " does not exist");
+          NS_LOG_ERROR (errno);
+          m_errno = errno;
+          return -1;
+        }
     }
   else
     {
-      m_errno = ERROR_NOROUTETOHOST;
-      return -1;
+      NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
     }
 
   Actions_t action = ProcessEvent (APP_CONNECT);
@@ -794,8 +813,8 @@
                                      const Address& fromAddress)
 {
   NS_LOG_FUNCTION (this << a << p  << fromAddress);
-  uint32_t localInterface;
   Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
+
   switch (a)
   {
     case ACK_TX:
@@ -807,12 +826,6 @@
       break;
     case SYN_ACK_TX:
       NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action SYN_ACK_TX");
-//      m_remotePort = InetSocketAddress::ConvertFrom (fromAddress).GetPort ();
-//      m_remoteAddress = InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 ();
-//       if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface))
-//         {
-//           m_localAddress = ipv4->GetAddress (localInterface);
-//         }
       if (m_state == LISTEN) //this means we should fork a new TcpSocketImpl
         {
           NS_LOG_DEBUG("In SYN_ACK_TX, m_state is LISTEN, this " << this);
@@ -827,20 +840,37 @@
                                   p, tcpHeader,fromAddress);
           return true;
         }
-      // This is the cloned endpoint
-      NS_ASSERT (m_state == SYN_RCVD);
-      m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
-      if (ipv4->GetInterfaceForDestination (m_remoteAddress, localInterface))
-        {
-          m_localAddress = ipv4->GetSourceAddress (m_remoteAddress);
-          m_endPoint->SetLocalAddress (m_localAddress);
-          // Leave local addr in the portmap to any, as the path from
-          // remote can change and packets can arrive on different interfaces
-          //m_endPoint->SetLocalAddress (Ipv4Address::GetAny());
-        }
-      // TCP SYN consumes one byte
-      m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
-      SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
+        // This is the cloned endpoint
+        m_endPoint->SetPeer (m_remoteAddress, m_remotePort);
+
+        // Look up the source address
+        if (ipv4->GetRoutingProtocol () != 0)
+          {
+            Ipv4Header header;
+            Socket::SocketErrno errno;
+            Ptr<Ipv4Route> route;
+            uint32_t oif = 0; //specify non-zero if bound to a source address
+            header.SetDestination (m_remoteAddress);
+            route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno);
+            if (route != 0)
+              {
+                NS_LOG_LOGIC ("Route exists");
+                m_endPoint->SetLocalAddress (route->GetSource ());
+              }
+            else
+              {
+                NS_LOG_ERROR (errno);
+                m_errno = errno;
+                return -1;
+              }
+          }
+        else
+          {
+            NS_FATAL_ERROR ("No Ipv4RoutingProtocol in the node");
+          }
+        // TCP SYN consumes one byte
+        m_nextRxSequence = tcpHeader.GetSequenceNumber() + SequenceNumber(1);
+        SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK);
       break;
     case ACK_TX_1:
       NS_LOG_LOGIC ("TcpSocketImpl " << this <<" Action ACK_TX_1");
@@ -1683,309 +1713,4 @@
 
 }//namespace ns3
 
-#ifdef RUN_SELF_TESTS
 
-#include "ns3/test.h"
-#include "ns3/socket-factory.h"
-#include "ns3/tcp-socket-factory.h"
-#include "ns3/simulator.h"
-#include "ns3/simple-channel.h"
-#include "ns3/simple-net-device.h"
-#include "ns3/drop-tail-queue.h"
-#include "ns3/config.h"
-#include "internet-stack.h"
-#include <string>
-
-namespace ns3 {
-	
-class TcpSocketImplTest: public Test
-{
-  public:
-  TcpSocketImplTest ();
-  virtual bool RunTests (void);
-  private:
-  //test 1, which sends string "Hello world" server->client
-  void Test1 (void);
-  void Test1_HandleConnectionCreated (Ptr<Socket>, const Address &);
-  void Test1_HandleRecv (Ptr<Socket> sock);
-
-  //test 2, which sends a number of bytes server->client
-  void Test2 (uint32_t payloadSize);
-  void Test2_HandleConnectionCreated (Ptr<Socket>, const Address &);
-  void Test2_HandleRecv (Ptr<Socket> sock);
-  uint32_t test2_payloadSize;
-
-  //test 3, which makes sure the rx buffer is finite
-  void Test3 (uint32_t payloadSize);
-  void Test3_HandleConnectionCreated (Ptr<Socket>, const Address &);
-  void Test3_HandleRecv (Ptr<Socket> sock);
-  uint32_t test3_payloadSize;
-
-  //helpers to make topology construction easier
-  Ptr<Node> CreateInternetNode ();
-  Ptr<SimpleNetDevice> AddSimpleNetDevice (Ptr<Node>,const char*,const char*);
-  void SetupDefaultSim ();
-
-  //reset all of the below state for another run
-  void Reset ();
-
-  //all of the state this class needs; basically both ends of the connection,
-  //and this test kind of acts as an single application running on both nodes
-  //simultaneously
-  Ptr<Node> node0;
-  Ptr<Node> node1;
-  Ptr<SimpleNetDevice> dev0;
-  Ptr<SimpleNetDevice> dev1;
-  Ptr<SimpleChannel> channel;
-  Ptr<Socket> listeningSock;
-  Ptr<Socket> sock0;
-  Ptr<Socket> sock1;
-  uint32_t rxBytes0;
-  uint32_t rxBytes1;
-
-  uint8_t* rxPayload;
-
-  bool result;
-};
-
-TcpSocketImplTest::TcpSocketImplTest ()
-  : Test ("TcpSocketImpl"), 
-    rxBytes0 (0),
-    rxBytes1 (0),
-    rxPayload (0),
-    result (true)
-{
-}
-
-bool
-TcpSocketImplTest::RunTests (void)
-{
-  Test1();
-  if (!result) return false;
-  Test2(600);
-  if (!result) return false;
-  Test3(20000);
-  return result;
-}
-
-//-----------------------------------------------------------------------------
-//test 1-----------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void
-TcpSocketImplTest::Test1 ()
-{
-  SetupDefaultSim ();
-  listeningSock->SetAcceptCallback 
-      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
-       MakeCallback(&TcpSocketImplTest::Test1_HandleConnectionCreated,this));
-  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this));
-
-  Simulator::Run ();
-  Simulator::Destroy ();
-
-  result = result && (rxBytes1 == 13);
-  result = result && (strcmp((const char*) rxPayload,"Hello World!") == 0);
-
-  Reset ();
-}
-
-void
-TcpSocketImplTest::Test1_HandleConnectionCreated (Ptr<Socket> s, const Address & addr)
-{
-  NS_ASSERT(s != listeningSock);
-  NS_ASSERT(sock0 == 0);
-  sock0 = s;
-  const uint8_t* hello = (uint8_t*)"Hello World!";
-  Ptr<Packet> p = Create<Packet> (hello, 13);
-  sock0->Send(p);
-  
-  sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this));
-}
-
-void
-TcpSocketImplTest::Test1_HandleRecv (Ptr<Socket> sock)
-{
-  NS_ASSERT (sock == sock0 || sock == sock1);
-  Ptr<Packet> p = sock->Recv();
-  uint32_t sz = p->GetSize();
-  if (sock == sock1)
-  {
-    rxBytes1 += sz;
-    rxPayload = new uint8_t[sz];
-    memcpy (rxPayload, p->PeekData(), sz);
-  }
-  else
-  {
-    NS_FATAL_ERROR ("Recv from unknown socket "<<sock);
-  }
-}
-
-//-----------------------------------------------------------------------------
-//test 2-----------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void
-TcpSocketImplTest::Test2 (uint32_t payloadSize)
-{
-  test2_payloadSize = payloadSize;
-  SetupDefaultSim ();
-  listeningSock->SetAcceptCallback 
-      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
-       MakeCallback(&TcpSocketImplTest::Test2_HandleConnectionCreated,this));
-  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this));
-
-  Simulator::Run ();
-  Simulator::Destroy ();
-
-  result = result && (rxBytes1 == test2_payloadSize);
-
-  Reset ();
-}
-
-void
-TcpSocketImplTest::Test2_HandleConnectionCreated (Ptr<Socket> s, const Address & addr)
-{
-  NS_ASSERT(s != listeningSock);
-  NS_ASSERT(sock0 == 0);
-  sock0 = s;
-  Ptr<Packet> p = Create<Packet> (test2_payloadSize);
-  sock0->Send(p);
-  
-  sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this));
-}
-
-void
-TcpSocketImplTest::Test2_HandleRecv (Ptr<Socket> sock)
-{
-  NS_ASSERT (sock == sock0 || sock == sock1);
-  Ptr<Packet> p = sock->Recv();
-  uint32_t sz = p->GetSize();
-  if (sock == sock1)
-  {
-    rxBytes1 += sz;
-  }
-  else
-  {
-    NS_FATAL_ERROR ("Not supposed to be back traffic in test 2..."<<sock);
-  }
-}
-
-//-----------------------------------------------------------------------------
-//test 3-----------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-void
-TcpSocketImplTest::Test3 (uint32_t payloadSize)
-{
-  Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (10000));
-  test3_payloadSize = payloadSize;
-  SetupDefaultSim ();
-  listeningSock->SetAcceptCallback 
-      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
-       MakeCallback(&TcpSocketImplTest::Test3_HandleConnectionCreated,this));
-  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test3_HandleRecv, this));
-
-  Simulator::Run ();
-  Simulator::Destroy ();
-
-  result = result && (rxBytes1 == test3_payloadSize);
-
-  Reset();
-}
-void
-TcpSocketImplTest::Test3_HandleConnectionCreated (Ptr<Socket> s, const Address &)
-{
-  NS_ASSERT(s != listeningSock);
-  NS_ASSERT(sock0 == 0);
-  sock0 = s;
-  Ptr<Packet> p = Create<Packet> (test3_payloadSize);
-  sock0->Send(p);
-}
-void
-TcpSocketImplTest::Test3_HandleRecv (Ptr<Socket> sock)
-{
-  NS_ASSERT_MSG (sock == sock1, "Not supposed to be back traffic in test 3... ");
-  if(sock->GetRxAvailable() >= 10000 ) //perform batch reads every 10000 bytes
-  {
-    Ptr<Packet> p = sock->Recv();
-    uint32_t sz = p->GetSize();
-    rxBytes1 += sz;
-  }
-}
-
-//-----------------------------------------------------------------------------
-//helpers----------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-Ptr<Node>
-TcpSocketImplTest::CreateInternetNode ()
-{
-  Ptr<Node> node = CreateObject<Node> ();
-  AddInternetStack (node);
-  return node;
-}
-
-Ptr<SimpleNetDevice>
-TcpSocketImplTest::AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask)
-{
-  Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
-  dev->SetAddress (Mac48Address::Allocate ());
-  node->AddDevice (dev);
-  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-  uint32_t ndid = ipv4->AddInterface (dev);
-  Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask));
-  ipv4->AddAddress (ndid, ipv4Addr);
-  ipv4->SetUp (ndid);
-  return dev;
-}
-
-void 
-TcpSocketImplTest::SetupDefaultSim ()
-{
-  const char* netmask = "255.255.255.0";
-  const char* ipaddr0 = "192.168.1.1";
-  const char* ipaddr1 = "192.168.1.2";
-  node0 = CreateInternetNode ();
-  node1 = CreateInternetNode ();
-  dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask);
-  dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask);
-
-  channel = CreateObject<SimpleChannel> ();
-  dev0->SetChannel (channel);
-  dev1->SetChannel (channel);
-
-  Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
-  Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
-
-  listeningSock = sockFactory0->CreateSocket();
-  sock1 = sockFactory1->CreateSocket();
-
-  uint16_t port = 50000;
-  InetSocketAddress serverlocaladdr (Ipv4Address::GetAny(), port);
-  InetSocketAddress serverremoteaddr (Ipv4Address(ipaddr0), port);
-
-  listeningSock->Bind(serverlocaladdr);
-  listeningSock->Listen ();
-
-  sock1->Connect(serverremoteaddr);
-}
-
-void
-TcpSocketImplTest::Reset ()
-{
-  node0 = 0;
-  node1 = 0;
-  dev0 = 0;
-  dev1 = 0;
-  channel = 0;
-  listeningSock = 0;
-  sock0 = 0;
-  sock1 = 0;
-  rxBytes0 = 0;
-  rxBytes1 = 0;
-  delete[] rxPayload;
-  rxPayload = 0;
-}
-
-static TcpSocketImplTest gTcpSocketImplTest;
-
-}//namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/tcp-test.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,369 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+/**
+ * This is the test code for tcp-socket-impl.cc, it was moved out of tcp-socket-impl.cc 
+ * to be in an independent file for clarity purposes.
+ */
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/config.h"
+#include "ipv4-end-point.h"
+#include "arp-l3-protocol.h"
+#include "ipv4-l3-protocol.h"
+#include "icmpv4-l4-protocol.h"
+#include "udp-l4-protocol.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-static-routing-impl.h"
+#include "ipv4-list-routing-impl.h"
+
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+
+#include <string>
+
+namespace ns3 {
+    
+static void
+AddInternetStack (Ptr<Node> node)
+{
+  //ARP
+  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+  node->AggregateObject(arp);
+  //IPV4
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+  //Routing for Ipv4
+  //Routing for Ipv4
+  Ptr<Ipv4ListRoutingImpl> ipv4RoutingImpl = CreateObject<Ipv4ListRoutingImpl> ();
+  ipv4->SetRoutingProtocol (ipv4RoutingImpl);
+  ipv4RoutingImpl->SetNode (node);
+  Ptr<Ipv4StaticRoutingImpl> ipv4staticRoutingImpl = CreateObject<Ipv4StaticRoutingImpl> ();
+  ipv4staticRoutingImpl->SetNode (node);
+  ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0);
+  node->AggregateObject(ipv4);
+  //ICMP
+  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
+  node->AggregateObject(icmp);
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject(udp); 
+  //TCP
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  node->AggregateObject(tcp);
+}
+
+class TcpSocketImplTest: public Test
+{
+  public:
+  TcpSocketImplTest ();
+  virtual bool RunTests (void);
+  private:
+  //test 1, which sends string "Hello world" server->client
+  void Test1 (void);
+  void Test1_HandleConnectionCreated (Ptr<Socket>, const Address &);
+  void Test1_HandleRecv (Ptr<Socket> sock);
+
+  //test 2, which sends a number of bytes server->client
+  void Test2 (uint32_t payloadSize);
+  void Test2_HandleConnectionCreated (Ptr<Socket>, const Address &);
+  void Test2_HandleRecv (Ptr<Socket> sock);
+  uint32_t test2_payloadSize;
+
+  //test 3, which makes sure the rx buffer is finite
+  void Test3 (uint32_t payloadSize);
+  void Test3_HandleConnectionCreated (Ptr<Socket>, const Address &);
+  void Test3_HandleRecv (Ptr<Socket> sock);
+  uint32_t test3_payloadSize;
+
+  //helpers to make topology construction easier
+  Ptr<Node> CreateInternetNode ();
+  Ptr<SimpleNetDevice> AddSimpleNetDevice (Ptr<Node>,const char*,const char*);
+  void SetupDefaultSim ();
+
+  //reset all of the below state for another run
+  void Reset ();
+
+  //all of the state this class needs; basically both ends of the connection,
+  //and this test kind of acts as an single application running on both nodes
+  //simultaneously
+  Ptr<Node> node0;
+  Ptr<Node> node1;
+  Ptr<SimpleNetDevice> dev0;
+  Ptr<SimpleNetDevice> dev1;
+  Ptr<SimpleChannel> channel;
+  Ptr<Socket> listeningSock;
+  Ptr<Socket> sock0;
+  Ptr<Socket> sock1;
+  uint32_t rxBytes0;
+  uint32_t rxBytes1;
+
+  uint8_t* rxPayload;
+
+  bool result;
+};
+
+TcpSocketImplTest::TcpSocketImplTest ()
+  : Test ("TcpSocketImpl"), 
+    rxBytes0 (0),
+    rxBytes1 (0),
+    rxPayload (0),
+    result (true)
+{
+}
+
+bool
+TcpSocketImplTest::RunTests (void)
+{
+  Test1();
+  if (!result) return false;
+  Test2(600);
+  if (!result) return false;
+  Test3(20000);
+  return result;
+}
+
+//-----------------------------------------------------------------------------
+//test 1-----------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void
+TcpSocketImplTest::Test1 ()
+{
+  SetupDefaultSim ();
+  listeningSock->SetAcceptCallback 
+      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+       MakeCallback(&TcpSocketImplTest::Test1_HandleConnectionCreated,this));
+  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  result = result && (rxBytes1 == 13);
+  result = result && (strcmp((const char*) rxPayload,"Hello World!") == 0);
+
+  Reset ();
+}
+
+void
+TcpSocketImplTest::Test1_HandleConnectionCreated (Ptr<Socket> s, const Address & addr)
+{
+  NS_ASSERT(s != listeningSock);
+  NS_ASSERT(sock0 == 0);
+  sock0 = s;
+  const uint8_t* hello = (uint8_t*)"Hello World!";
+  Ptr<Packet> p = Create<Packet> (hello, 13);
+  sock0->Send(p);
+  
+  sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test1_HandleRecv, this));
+}
+
+void
+TcpSocketImplTest::Test1_HandleRecv (Ptr<Socket> sock)
+{
+  NS_ASSERT (sock == sock0 || sock == sock1);
+  Ptr<Packet> p = sock->Recv();
+  uint32_t sz = p->GetSize();
+  if (sock == sock1)
+  {
+    rxBytes1 += sz;
+    rxPayload = new uint8_t[sz];
+    memcpy (rxPayload, p->PeekData(), sz);
+  }
+  else
+  {
+    NS_FATAL_ERROR ("Recv from unknown socket "<<sock);
+  }
+}
+
+//-----------------------------------------------------------------------------
+//test 2-----------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void
+TcpSocketImplTest::Test2 (uint32_t payloadSize)
+{
+  test2_payloadSize = payloadSize;
+  SetupDefaultSim ();
+  listeningSock->SetAcceptCallback 
+      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+       MakeCallback(&TcpSocketImplTest::Test2_HandleConnectionCreated,this));
+  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  result = result && (rxBytes1 == test2_payloadSize);
+
+  Reset ();
+}
+
+void
+TcpSocketImplTest::Test2_HandleConnectionCreated (Ptr<Socket> s, const Address & addr)
+{
+  NS_ASSERT(s != listeningSock);
+  NS_ASSERT(sock0 == 0);
+  sock0 = s;
+  Ptr<Packet> p = Create<Packet> (test2_payloadSize);
+  sock0->Send(p);
+  
+  sock0->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test2_HandleRecv, this));
+}
+
+void
+TcpSocketImplTest::Test2_HandleRecv (Ptr<Socket> sock)
+{
+  NS_ASSERT (sock == sock0 || sock == sock1);
+  Ptr<Packet> p = sock->Recv();
+  uint32_t sz = p->GetSize();
+  if (sock == sock1)
+  {
+    rxBytes1 += sz;
+  }
+  else
+  {
+    NS_FATAL_ERROR ("Not supposed to be back traffic in test 2..."<<sock);
+  }
+}
+
+//-----------------------------------------------------------------------------
+//test 3-----------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+void
+TcpSocketImplTest::Test3 (uint32_t payloadSize)
+{
+  Config::SetDefault ("ns3::TcpSocket::RcvBufSize", UintegerValue (10000));
+  test3_payloadSize = payloadSize;
+  SetupDefaultSim ();
+  listeningSock->SetAcceptCallback 
+      (MakeNullCallback<bool, Ptr< Socket >, const Address &> (),
+       MakeCallback(&TcpSocketImplTest::Test3_HandleConnectionCreated,this));
+  sock1->SetRecvCallback (MakeCallback(&TcpSocketImplTest::Test3_HandleRecv, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  result = result && (rxBytes1 == test3_payloadSize);
+
+  Reset();
+}
+void
+TcpSocketImplTest::Test3_HandleConnectionCreated (Ptr<Socket> s, const Address &)
+{
+  NS_ASSERT(s != listeningSock);
+  NS_ASSERT(sock0 == 0);
+  sock0 = s;
+  Ptr<Packet> p = Create<Packet> (test3_payloadSize);
+  sock0->Send(p);
+}
+void
+TcpSocketImplTest::Test3_HandleRecv (Ptr<Socket> sock)
+{
+  NS_ASSERT_MSG (sock == sock1, "Not supposed to be back traffic in test 3... ");
+  if(sock->GetRxAvailable() >= 10000 ) //perform batch reads every 10000 bytes
+  {
+    Ptr<Packet> p = sock->Recv();
+    uint32_t sz = p->GetSize();
+    rxBytes1 += sz;
+  }
+}
+
+//-----------------------------------------------------------------------------
+//helpers----------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+Ptr<Node>
+TcpSocketImplTest::CreateInternetNode ()
+{
+  Ptr<Node> node = CreateObject<Node> ();
+  AddInternetStack (node);
+  return node;
+}
+
+Ptr<SimpleNetDevice>
+TcpSocketImplTest::AddSimpleNetDevice (Ptr<Node> node, const char* ipaddr, const char* netmask)
+{
+  Ptr<SimpleNetDevice> dev = CreateObject<SimpleNetDevice> ();
+  dev->SetAddress (Mac48Address::Allocate ());
+  node->AddDevice (dev);
+  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+  uint32_t ndid = ipv4->AddInterface (dev);
+  Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address (ipaddr), Ipv4Mask (netmask));
+  ipv4->AddAddress (ndid, ipv4Addr);
+  ipv4->SetUp (ndid);
+  return dev;
+}
+
+void 
+TcpSocketImplTest::SetupDefaultSim ()
+{
+  const char* netmask = "255.255.255.0";
+  const char* ipaddr0 = "192.168.1.1";
+  const char* ipaddr1 = "192.168.1.2";
+  node0 = CreateInternetNode ();
+  node1 = CreateInternetNode ();
+  dev0 = AddSimpleNetDevice (node0, ipaddr0, netmask);
+  dev1 = AddSimpleNetDevice (node1, ipaddr1, netmask);
+
+  channel = CreateObject<SimpleChannel> ();
+  dev0->SetChannel (channel);
+  dev1->SetChannel (channel);
+
+  Ptr<SocketFactory> sockFactory0 = node0->GetObject<TcpSocketFactory> ();
+  Ptr<SocketFactory> sockFactory1 = node1->GetObject<TcpSocketFactory> ();
+
+  listeningSock = sockFactory0->CreateSocket();
+  sock1 = sockFactory1->CreateSocket();
+
+  uint16_t port = 50000;
+  InetSocketAddress serverlocaladdr (Ipv4Address::GetAny(), port);
+  InetSocketAddress serverremoteaddr (Ipv4Address(ipaddr0), port);
+
+  listeningSock->Bind(serverlocaladdr);
+  listeningSock->Listen ();
+
+  sock1->Connect(serverremoteaddr);
+}
+
+void
+TcpSocketImplTest::Reset ()
+{
+  node0 = 0;
+  node1 = 0;
+  dev0 = 0;
+  dev1 = 0;
+  channel = 0;
+  listeningSock = 0;
+  sock0 = 0;
+  sock1 = 0;
+  rxBytes0 = 0;
+  rxBytes1 = 0;
+  delete[] rxPayload;
+  rxPayload = 0;
+}
+
+static TcpSocketImplTest gTcpSocketImplTest;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
+
--- a/src/internet-stack/udp-l4-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/udp-l4-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -23,9 +23,11 @@
 #include "ns3/packet.h"
 #include "ns3/node.h"
 #include "ns3/boolean.h"
+#include "ns3/ipv4-route.h"
 
 #include "udp-l4-protocol.h"
 #include "udp-header.h"
+#include "udp-socket-factory-impl.h"
 #include "ipv4-end-point-demux.h"
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
@@ -72,6 +74,28 @@
   m_node = node;
 }
 
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the udp stack and link it to the ipv4 object
+ * present in the node along with the socket factory
+ */
+void
+UdpL4Protocol::NotifyNewAggregate ()
+{  
+  bool is_not_initialized = (m_node == 0);
+  Ptr<Node>node = this->GetObject<Node> ();
+  Ptr<Ipv4L3Protocol> ipv4 = this->GetObject<Ipv4L3Protocol> ();
+  if (is_not_initialized && node!= 0 && ipv4 != 0)
+    {
+      this->SetNode (node);
+      ipv4->Insert (this);
+      Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+      udpFactory->SetUdp (this);
+      node->AggregateObject (udpFactory);
+    }
+  Object::NotifyNewAggregate ();
+}
+
 int 
 UdpL4Protocol::GetProtocolNumber (void) const
 {
@@ -200,6 +224,7 @@
                          source, udpHeader.GetSourcePort (), interface);
   if (endPoints.empty ())
     {
+      NS_LOG_LOGIC ("RX_ENDPOINT_UNREACH");
       return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
     }
   for (Ipv4EndPointDemux::EndPointsI endPoint = endPoints.begin ();
@@ -234,7 +259,36 @@
   if (ipv4 != 0)
     {
       NS_LOG_LOGIC ("Sending to IP");
-      ipv4->Send (packet, saddr, daddr, PROT_NUMBER);
+      // Send with null route
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER, 0);
+    }
+}
+
+void
+UdpL4Protocol::Send (Ptr<Packet> packet, 
+                     Ipv4Address saddr, Ipv4Address daddr, 
+                     uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << saddr << daddr << sport << dport);
+
+  UdpHeader udpHeader;
+  if(m_calcChecksum)
+  {
+    udpHeader.EnableChecksums();
+    udpHeader.InitializeChecksum (saddr,
+                                  daddr,
+                                  PROT_NUMBER);
+  }
+  udpHeader.SetDestinationPort (dport);
+  udpHeader.SetSourcePort (sport);
+
+  packet->AddHeader (udpHeader);
+
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  if (ipv4 != 0)
+    {
+      NS_LOG_LOGIC ("Sending to IP");
+      ipv4->Send (packet, saddr, daddr, PROT_NUMBER, route);
     }
 }
 
--- a/src/internet-stack/udp-l4-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/udp-l4-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -33,6 +33,7 @@
 
 class Node;
 class Socket;
+class Ipv4Route;
 /**
  * \ingroup udp
  * \brief Implementation of the UDP protocol
@@ -76,6 +77,9 @@
   void Send (Ptr<Packet> packet,
              Ipv4Address saddr, Ipv4Address daddr, 
              uint16_t sport, uint16_t dport);
+  void Send (Ptr<Packet> packet,
+             Ipv4Address saddr, Ipv4Address daddr, 
+             uint16_t sport, uint16_t dport, Ptr<Ipv4Route> route);
   /**
    * \brief Receive a packet up the protocol stack
    * \param p The Packet to dump the contents into
@@ -106,6 +110,11 @@
                             const uint8_t payload[8]);
 protected:
   virtual void DoDispose (void);
+  /*
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
 private:
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
--- a/src/internet-stack/udp-socket-impl.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/udp-socket-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -23,6 +23,8 @@
 #include "ns3/inet-socket-address.h"
 #include "ns3/ipv4-route.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-routing-protocol.h"
 #include "ns3/udp-socket-factory.h"
 #include "ns3/trace-source-accessor.h"
 #include "udp-socket-impl.h"
@@ -70,6 +72,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
+  // XXX todo:  leave any multicast groups that have been joined
   m_node = 0;
   if (m_endPoint != 0)
     {
@@ -308,7 +311,6 @@
       return -1;
     }
 
-  uint32_t localInterface;
   Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
 
   // Locally override the IP TTL for this socket
@@ -319,7 +321,6 @@
   // irrespective of what is set in these socket options.  So, this tagging  
   // may end up setting the TTL of a limited broadcast packet to be
   // the same as a unicast, but it will be fixed further down the stack
-  //NS_LOG_UNCOND ("IPttl: " << m_ipTtl);
   if (m_ipMulticastTtl != 0 && dest.IsMulticast ())
     {
       SocketIpTtlTag tag;
@@ -391,14 +392,31 @@
       NS_LOG_LOGIC ("Limited broadcast end.");
       return p->GetSize();
     }
-  else if (ipv4->GetInterfaceForDestination(dest, localInterface))
+  else if (ipv4->GetRoutingProtocol () != 0)
     {
-      NS_LOG_LOGIC ("Route exists");
-      m_udp->Send (p->Copy (), ipv4->GetSourceAddress (dest), dest,
-		   m_endPoint->GetLocalPort (), port);
-      NotifyDataSent (p->GetSize ());
-      NotifySend (GetTxAvailable ());
-      return p->GetSize();;
+      Ipv4Header header;
+      header.SetDestination (dest);
+      Socket::SocketErrno errno;
+      Ptr<Ipv4Route> route;
+      uint32_t oif = 0; //specify non-zero if bound to a source address
+      // TBD-- we could cache the route and just check its validity
+      route = ipv4->GetRoutingProtocol ()->RouteOutput (header, oif, errno); 
+      if (route != 0)
+        {
+          NS_LOG_LOGIC ("Route exists");
+          header.SetSource (route->GetSource ());
+          m_udp->Send (p->Copy (), header.GetSource (), header.GetDestination (),
+                       m_endPoint->GetLocalPort (), port, route);
+          NotifyDataSent (p->GetSize ());
+          return p->GetSize();
+        }
+      else 
+        {
+          NS_LOG_LOGIC ("No route to destination");
+          NS_LOG_ERROR (errno);
+          m_errno = errno;
+          return -1;
+        }
     }
   else
    {
@@ -494,6 +512,34 @@
   return 0;
 }
 
+int 
+UdpSocketImpl::MulticastJoinGroup (uint32_t interface, const Address &groupAddress)
+{
+  NS_LOG_FUNCTION (interface << groupAddress);
+  /*
+   1) sanity check interface
+   2) sanity check that it has not been called yet on this interface/group
+   3) determine address family of groupAddress
+   4) locally store a list of (interface, groupAddress)
+   5) call ipv4->MulticastJoinGroup () or Ipv6->MulticastJoinGroup ()
+  */
+  return 0;
+} 
+
+int 
+UdpSocketImpl::MulticastLeaveGroup (uint32_t interface, const Address &groupAddress) 
+{
+  NS_LOG_FUNCTION (interface << groupAddress);
+  /*
+   1) sanity check interface
+   2) determine address family of groupAddress
+   3) delete from local list of (interface, groupAddress); raise a LOG_WARN
+      if not already present (but return 0) 
+   5) call ipv4->MulticastLeaveGroup () or Ipv6->MulticastLeaveGroup ()
+  */
+  return 0;
+}
+
 void 
 UdpSocketImpl::ForwardUp (Ptr<Packet> packet, Ipv4Address ipv4, uint16_t port)
 {
@@ -552,30 +598,54 @@
 }
 
 void 
-UdpSocketImpl::SetIpTtl (uint32_t ipTtl)
+UdpSocketImpl::SetIpTtl (uint8_t ipTtl)
 {
   m_ipTtl = ipTtl;
 }
 
-uint32_t 
+uint8_t 
 UdpSocketImpl::GetIpTtl (void) const
 {
   return m_ipTtl;
 }
 
 void 
-UdpSocketImpl::SetIpMulticastTtl (uint32_t ipTtl)
+UdpSocketImpl::SetIpMulticastTtl (uint8_t ipTtl)
 {
   m_ipMulticastTtl = ipTtl;
 }
 
-uint32_t 
+uint8_t 
 UdpSocketImpl::GetIpMulticastTtl (void) const
 {
   return m_ipMulticastTtl;
 }
 
 void 
+UdpSocketImpl::SetIpMulticastIf (int32_t ipIf)
+{
+  m_ipMulticastIf = ipIf;
+}
+
+int32_t 
+UdpSocketImpl::GetIpMulticastIf (void) const
+{
+  return m_ipMulticastIf;
+}
+
+void 
+UdpSocketImpl::SetIpMulticastLoop (bool loop)
+{
+  m_ipMulticastLoop = loop;
+}
+
+bool 
+UdpSocketImpl::GetIpMulticastLoop (void) const
+{
+  return m_ipMulticastLoop;
+}
+
+void 
 UdpSocketImpl::SetMtuDiscover (bool discover)
 {
   m_mtuDiscover = discover;
@@ -588,207 +658,3 @@
 
 
 } //namespace ns3
-
-
-#ifdef RUN_SELF_TESTS
-
-#include "ns3/test.h"
-#include "ns3/socket-factory.h"
-#include "ns3/udp-socket-factory.h"
-#include "ns3/simulator.h"
-#include "ns3/simple-channel.h"
-#include "ns3/simple-net-device.h"
-#include "ns3/drop-tail-queue.h"
-#include "internet-stack.h"
-#include <string>
-
-namespace ns3 {
-
-class UdpSocketImplTest: public Test
-{
-  Ptr<Packet> m_receivedPacket;
-  Ptr<Packet> m_receivedPacket2;
-
-public:
-  virtual bool RunTests (void);
-  UdpSocketImplTest ();
-
-  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
-  void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
-  void ReceivePkt (Ptr<Socket> socket);
-  void ReceivePkt2 (Ptr<Socket> socket);
-};
-
-
-UdpSocketImplTest::UdpSocketImplTest ()
-  : Test ("UdpSocketImpl") 
-{
-}
-
-void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
-  m_receivedPacket = packet;
-}
-
-void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
-{
-  m_receivedPacket2 = packet;
-}
-
-void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
-{
-  uint32_t availableData;
-  availableData = socket->GetRxAvailable ();
-  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
-  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
-}
-
-void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
-{
-  uint32_t availableData;
-  availableData = socket->GetRxAvailable ();
-  m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
-  NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
-}
-
-bool
-UdpSocketImplTest::RunTests (void)
-{
-  bool result = true;
-
-  // Create topology
-  
-  // Receiver Node
-  Ptr<Node> rxNode = CreateObject<Node> ();
-  AddInternetStack (rxNode);
-  Ptr<SimpleNetDevice> rxDev1, rxDev2;
-  { // first interface
-    rxDev1 = CreateObject<SimpleNetDevice> ();
-    rxDev1->SetAddress (Mac48Address::Allocate ());
-    rxNode->AddDevice (rxDev1);
-    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
-    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U));
-    ipv4->AddAddress (netdev_idx, ipv4Addr);
-    ipv4->SetUp (netdev_idx);
-  }
-
-  { // second interface
-    rxDev2 = CreateObject<SimpleNetDevice> ();
-    rxDev2->SetAddress (Mac48Address::Allocate ());
-    rxNode->AddDevice (rxDev2);
-    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
-    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U));
-    ipv4->AddAddress (netdev_idx, ipv4Addr);
-    ipv4->SetUp (netdev_idx);
-  }
-  
-  // Sender Node
-  Ptr<Node> txNode = CreateObject<Node> ();
-  AddInternetStack (txNode);
-  Ptr<SimpleNetDevice> txDev1;
-  {
-    txDev1 = CreateObject<SimpleNetDevice> ();
-    txDev1->SetAddress (Mac48Address::Allocate ());
-    txNode->AddDevice (txDev1);
-    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (txDev1);
-    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U));
-    ipv4->AddAddress (netdev_idx, ipv4Addr);
-    ipv4->SetUp (netdev_idx);
-  }
-  Ptr<SimpleNetDevice> txDev2;
-  {
-    txDev2 = CreateObject<SimpleNetDevice> ();
-    txDev2->SetAddress (Mac48Address::Allocate ());
-    txNode->AddDevice (txDev2);
-    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
-    uint32_t netdev_idx = ipv4->AddInterface (txDev2);
-    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U));
-    ipv4->AddAddress (netdev_idx, ipv4Addr);
-    ipv4->SetUp (netdev_idx);
-  }
-
-  // link the two nodes
-  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
-  rxDev1->SetChannel (channel1);
-  txDev1->SetChannel (channel1);
-
-  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
-  rxDev2->SetChannel (channel2);
-  txDev2->SetChannel (channel2);
-
-
-  // Create the UDP sockets
-  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
-  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
-  NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
-  rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
-
-  Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
-  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
-  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
-
-  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
-  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
-
-  // ------ Now the tests ------------
-
-  // Unicast test
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0, 
-    InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
-
-  m_receivedPacket->RemoveAllTags ();
-  m_receivedPacket2->RemoveAllTags ();
-
-  // Simple broadcast test
-
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0, 
-    InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  // second socket should not receive it (it is bound specifically to the second interface's address
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
-
-  m_receivedPacket->RemoveAllTags ();
-  m_receivedPacket2->RemoveAllTags ();
-
-  // Broadcast test with multiple receiving sockets
-
-  // When receiving broadcast packets, all sockets sockets bound to
-  // the address/port should receive a copy of the same packet -- if
-  // the socket address matches.
-  rxSocket2->Dispose ();
-  rxSocket2 = rxSocketFactory->CreateSocket ();
-  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
-  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
-
-  m_receivedPacket = Create<Packet> ();
-  m_receivedPacket2 = Create<Packet> ();
-  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123), 0,
-InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
-  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
-
-  m_receivedPacket->RemoveAllTags ();
-  m_receivedPacket2->RemoveAllTags ();
-
-  Simulator::Destroy ();
-
-  return result;
-}
-
-static UdpSocketImplTest gUdpSocketImplTest;
-
-}; // namespace ns3
-
-#endif /* RUN_SELF_TESTS */
--- a/src/internet-stack/udp-socket-impl.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/udp-socket-impl.h	Sat May 30 17:37:38 2009 +0100
@@ -75,15 +75,21 @@
   virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,
     Address &fromAddress);
   virtual int GetSockName (Address &address) const; 
+  virtual int MulticastJoinGroup (uint32_t interfaceIndex, const Address &groupAddress);
+  virtual int MulticastLeaveGroup (uint32_t interfaceIndex, const Address &groupAddress);
 
 private:
   // Attributes set through UdpSocket base class 
   virtual void SetRcvBufSize (uint32_t size);
   virtual uint32_t GetRcvBufSize (void) const;
-  virtual void SetIpTtl (uint32_t ipTtl);
-  virtual uint32_t GetIpTtl (void) const;
-  virtual void SetIpMulticastTtl (uint32_t ipTtl);
-  virtual uint32_t GetIpMulticastTtl (void) const;
+  virtual void SetIpTtl (uint8_t ipTtl);
+  virtual uint8_t GetIpTtl (void) const;
+  virtual void SetIpMulticastTtl (uint8_t ipTtl);
+  virtual uint8_t GetIpMulticastTtl (void) const;
+  virtual void SetIpMulticastIf (int32_t ipIf);
+  virtual int32_t GetIpMulticastIf (void) const;
+  virtual void SetIpMulticastLoop (bool loop);
+  virtual bool GetIpMulticastLoop (void) const;
   virtual void SetMtuDiscover (bool discover);
   virtual bool GetMtuDiscover (void) const;
 
@@ -117,8 +123,10 @@
   
   // Socket attributes
   uint32_t m_rcvBufSize;
-  uint32_t m_ipTtl;
-  uint32_t m_ipMulticastTtl;
+  uint8_t m_ipTtl;
+  uint8_t m_ipMulticastTtl;
+  int32_t m_ipMulticastIf;
+  bool m_ipMulticastLoop;
   bool m_mtuDiscover;
   Callback<void, Ipv4Address,uint8_t,uint8_t,uint8_t,uint32_t> m_icmpCallback;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/udp-test.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,266 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Georgia Tech Research Corporation
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Raj Bhattacharjea <raj.b@gatech.edu>
+ */
+/**
+ * This is the test code for udp-socket-impl.cc, it was moved out of udp-socket-impl.cc to 
+ * be in an independent file for clarity purposes.
+ */
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/socket.h"
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+
+#include "arp-l3-protocol.h"
+#include "ipv4-l3-protocol.h"
+#include "icmpv4-l4-protocol.h"
+#include "udp-l4-protocol.h"
+#include "tcp-l4-protocol.h"
+#include "ipv4-list-routing-impl.h"
+#include "ipv4-static-routing-impl.h"
+
+#include <string>
+#include <limits>
+namespace ns3 {
+
+static void
+AddInternetStack (Ptr<Node> node)
+{
+  //ARP
+  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
+  node->AggregateObject(arp);
+  //IPV4
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> ();
+  //Routing for Ipv4
+  Ptr<Ipv4ListRoutingImpl> ipv4RoutingImpl = CreateObject<Ipv4ListRoutingImpl> ();
+  ipv4->SetRoutingProtocol (ipv4RoutingImpl);
+  ipv4RoutingImpl->SetNode (node);
+  Ptr<Ipv4StaticRoutingImpl> ipv4staticRoutingImpl = CreateObject<Ipv4StaticRoutingImpl> ();
+  ipv4staticRoutingImpl->SetNode (node);
+  ipv4RoutingImpl->AddRoutingProtocol (ipv4staticRoutingImpl, 0);
+  node->AggregateObject(ipv4);
+  //ICMP
+  Ptr<Icmpv4L4Protocol> icmp = CreateObject<Icmpv4L4Protocol> ();
+  node->AggregateObject(icmp);
+  //UDP
+  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
+  node->AggregateObject(udp); 
+  //TCP
+  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> ();
+  node->AggregateObject(tcp);
+}
+
+
+class UdpSocketImplTest: public Test
+{
+  Ptr<Packet> m_receivedPacket;
+  Ptr<Packet> m_receivedPacket2;
+
+public:
+  virtual bool RunTests (void);
+  UdpSocketImplTest ();
+
+  void ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
+  void ReceivePkt (Ptr<Socket> socket);
+  void ReceivePkt2 (Ptr<Socket> socket);
+};
+
+
+UdpSocketImplTest::UdpSocketImplTest ()
+  : Test ("UdpSocketImpl") 
+{
+}
+
+void UdpSocketImplTest::ReceivePacket (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket = packet;
+}
+
+void UdpSocketImplTest::ReceivePacket2 (Ptr<Socket> socket, Ptr<Packet> packet, const Address &from)
+{
+  m_receivedPacket2 = packet;
+}
+
+void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
+}
+
+void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
+{
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
+  m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
+  NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
+}
+
+bool
+UdpSocketImplTest::RunTests (void)
+{
+  bool result = true;
+
+  // Create topology
+  
+  // Receiver Node
+  Ptr<Node> rxNode = CreateObject<Node> ();
+  AddInternetStack (rxNode);
+  Ptr<SimpleNetDevice> rxDev1, rxDev2;
+  { // first interface
+    rxDev1 = CreateObject<SimpleNetDevice> ();
+    rxDev1->SetAddress (Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev1);
+    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
+    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.1"), Ipv4Mask (0xffff0000U));
+    ipv4->AddAddress (netdev_idx, ipv4Addr);
+    ipv4->SetUp (netdev_idx);
+  }
+
+  { // second interface
+    rxDev2 = CreateObject<SimpleNetDevice> ();
+    rxDev2->SetAddress (Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev2);
+    Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
+    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.1"), Ipv4Mask (0xffff0000U));
+    ipv4->AddAddress (netdev_idx, ipv4Addr);
+    ipv4->SetUp (netdev_idx);
+  }
+  
+  // Sender Node
+  Ptr<Node> txNode = CreateObject<Node> ();
+  AddInternetStack (txNode);
+  Ptr<SimpleNetDevice> txDev1;
+  {
+    txDev1 = CreateObject<SimpleNetDevice> ();
+    txDev1->SetAddress (Mac48Address::Allocate ());
+    txNode->AddDevice (txDev1);
+    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (txDev1);
+    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.0.2"), Ipv4Mask (0xffff0000U));
+    ipv4->AddAddress (netdev_idx, ipv4Addr);
+    ipv4->SetUp (netdev_idx);
+  }
+  Ptr<SimpleNetDevice> txDev2;
+  {
+    txDev2 = CreateObject<SimpleNetDevice> ();
+    txDev2->SetAddress (Mac48Address::Allocate ());
+    txNode->AddDevice (txDev2);
+    Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
+    uint32_t netdev_idx = ipv4->AddInterface (txDev2);
+    Ipv4InterfaceAddress ipv4Addr = Ipv4InterfaceAddress (Ipv4Address ("10.0.1.2"), Ipv4Mask (0xffff0000U));
+    ipv4->AddAddress (netdev_idx, ipv4Addr);
+    ipv4->SetUp (netdev_idx);
+  }
+
+  // link the two nodes
+  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
+  rxDev1->SetChannel (channel1);
+  txDev1->SetChannel (channel1);
+
+  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
+  rxDev2->SetChannel (channel2);
+  txDev2->SetChannel (channel2);
+
+
+  // Create the UDP sockets
+  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
+  NS_TEST_ASSERT_EQUAL (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.0.1"), 1234)), 0);
+  rxSocket->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt, this));
+
+  Ptr<Socket> rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("10.0.1.1"), 1234)), 0);
+
+  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
+  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
+
+  // ------ Now the tests ------------
+
+  // Unicast test
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0, 
+    InetSocketAddress (Ipv4Address("10.0.0.1"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0); // second interface should receive it
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  // Simple broadcast test
+
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo ( Create<Packet> (123), 0, 
+    InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  // second socket should not receive it (it is bound specifically to the second interface's address
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 0);
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  // Broadcast test with multiple receiving sockets
+
+  // When receiving broadcast packets, all sockets sockets bound to
+  // the address/port should receive a copy of the same packet -- if
+  // the socket address matches.
+  rxSocket2->Dispose ();
+  rxSocket2 = rxSocketFactory->CreateSocket ();
+  rxSocket2->SetRecvCallback (MakeCallback (&UdpSocketImplTest::ReceivePkt2, this));
+  NS_TEST_ASSERT_EQUAL (rxSocket2->Bind (InetSocketAddress (Ipv4Address ("0.0.0.0"), 1234)), 0);
+
+  m_receivedPacket = Create<Packet> ();
+  m_receivedPacket2 = Create<Packet> ();
+  NS_TEST_ASSERT_EQUAL (txSocket->SendTo (Create<Packet> (123), 0,
+InetSocketAddress (Ipv4Address("255.255.255.255"), 1234)), 123);
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket->GetSize (), 123);
+  NS_TEST_ASSERT_EQUAL (m_receivedPacket2->GetSize (), 123);
+
+  m_receivedPacket->RemoveAllTags ();
+  m_receivedPacket2->RemoveAllTags ();
+
+  Simulator::Destroy ();
+
+  return result;
+}
+
+static UdpSocketImplTest gUdpSocketImplTest;
+
+}; // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/internet-stack/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/src/internet-stack/wscript	Sat May 30 17:37:38 2009 +0100
@@ -72,23 +72,23 @@
 def build(bld):
     obj = bld.create_ns3_module('internet-stack', ['node'])
     obj.source = [
-        'internet-stack.cc',
+        'tcp-test.cc',
+        'udp-test.cc',
         'ipv4-l4-protocol.cc',
         'udp-header.cc',
         'tcp-header.cc',
         'ipv4-checksum.cc',
         'ipv4-interface.cc',
         'ipv4-l3-protocol.cc',
-        'ipv4-static-routing.cc',
+        'ipv4-static-routing-impl.cc',
+        'ipv4-list-routing-impl.cc',
         'ipv4-global-routing.cc',
         'ipv4-end-point.cc',
         'udp-l4-protocol.cc',
         'tcp-l4-protocol.cc',
         'arp-header.cc',
         'arp-cache.cc',
-        'arp-ipv4-interface.cc',
         'arp-l3-protocol.cc',
-        'ipv4-loopback-interface.cc',
         'udp-socket-impl.cc',
         'tcp-socket-impl.cc',
         'ipv4-end-point-demux.cc',
@@ -101,16 +101,18 @@
         'ipv4-raw-socket-impl.cc',
         'icmpv4.cc',
         'icmpv4-l4-protocol.cc',
+        'loopback-net-device.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
     headers.module = 'internet-stack'
     headers.source = [
-        'internet-stack.h',
         'udp-header.h',
         'tcp-header.h',
         'sequence-number.h',
         'ipv4-global-routing.h',
+        'ipv4-list-routing-impl.h',
+        'ipv4-static-routing-impl.h',
         'icmpv4.h',
         ]
 
--- a/src/node/address-utils.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/address-utils.cc	Sat May 30 17:37:38 2009 +0100
@@ -18,6 +18,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "address-utils.h"
+#include "inet-socket-address.h"
 
 namespace ns3 {
 
@@ -67,4 +68,20 @@
   ad.CopyFrom (mac);
 }
 
+namespace addressUtils {
+
+bool IsMulticast (const Address &ad)
+{
+  if (InetSocketAddress::IsMatchingType (ad))
+    {
+      InetSocketAddress inetAddr = InetSocketAddress::ConvertFrom (ad);
+      Ipv4Address ipv4 = inetAddr.GetIpv4 ();
+      return ipv4.IsMulticast ();
+    }
+  // IPv6 case can go here, in future
+  return false;
+}
+
+} // namespace addressUtils
+
 } // namespace ns3
--- a/src/node/address-utils.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/address-utils.h	Sat May 30 17:37:38 2009 +0100
@@ -38,6 +38,14 @@
 void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len);
 void ReadFrom (Buffer::Iterator &i, Mac48Address &ad);
 
+namespace addressUtils {
+
+/**
+ * \brief Address family-independent test for a multicast address
+ */
+bool IsMulticast (const Address &ad);
+};  
+
 };
 
 #endif /* ADDRESS_UTILS_H */
--- a/src/node/ipv4-address.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/ipv4-address.cc	Sat May 30 17:37:38 2009 +0100
@@ -55,6 +55,7 @@
 
 namespace ns3 {
 
+  
 Ipv4Mask::Ipv4Mask ()
   : m_mask (0x66666666)
 {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-list-routing.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ipv4-list-routing.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4ListRouting);
+
+TypeId 
+Ipv4ListRouting::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4ListRouting")
+    .SetParent<Ipv4RoutingProtocol> ()
+    ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-list-routing.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,61 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IPV4_LIST_ROUTING_H
+#define IPV4_LIST_ROUTING_H
+
+#include "ipv4-routing-protocol.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup ipv4 
+ */
+
+/**
+ * This class is a specialization of Ipv4RoutingProtocol that allows 
+ * other instances of Ipv4RoutingProtocol to be inserted in a 
+ * prioritized list.  Routing protocols in the list are consulted one
+ * by one, from highest to lowest proirity, until a routing protocol
+ * is found that will take the packet (this corresponds to a non-zero
+ * return value to RouteOutput, or a return value of true to RouteInput).
+ * The order by which routing protocols with the same priority value 
+ * are consulted is undefined.
+ * 
+ */
+class Ipv4ListRouting : public Ipv4RoutingProtocol
+{
+public:
+  static TypeId GetTypeId (void);
+  /**
+   * \brief Register a new routing protocol to be used in this IPv4 stack
+   *
+   * \param routingProtocol new routing protocol implementation object
+   * \param priority priority to give to this routing protocol.
+   * Values may range between -32768 and +32767.  
+   */
+  virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol, int16_t priority) = 0;
+
+  virtual uint32_t GetNRoutingProtocols (void) const = 0;
+
+  virtual Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (uint32_t index, int16_t& priority) const = 0;
+};
+
+} //namespace ns3
+
+#endif /* IPV4_LIST_ROUTING_H */
--- a/src/node/ipv4-route.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/ipv4-route.cc	Sat May 30 17:37:38 2009 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2005 INRIA
+ * Copyright (c) 2009 University of Washington
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,253 +15,97 @@
  * 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 "ipv4-route.h"
+#include "net-device.h"
 #include "ns3/assert.h"
 
 namespace ns3 {
 
-/*****************************************************
- *     Network Ipv4Route
- *****************************************************/
-
 Ipv4Route::Ipv4Route ()
 {}
 
-Ipv4Route::Ipv4Route (Ipv4Route const &route)
-  : m_dest (route.m_dest),
-    m_destNetworkMask (route.m_destNetworkMask),
-    m_gateway (route.m_gateway),
-    m_interface (route.m_interface)
-{}
-
-Ipv4Route::Ipv4Route (Ipv4Route const *route)
-  : m_dest (route->m_dest),
-    m_destNetworkMask (route->m_destNetworkMask),
-    m_gateway (route->m_gateway),
-    m_interface (route->m_interface)
-{}
+void 
+Ipv4Route::SetDestination (Ipv4Address dest)
+{
+  m_dest = dest;
+}
 
-Ipv4Route::Ipv4Route (Ipv4Address dest,
-                      Ipv4Address gateway,
-                      uint32_t interface)
-  : m_dest (dest),
-    m_destNetworkMask (Ipv4Mask::GetZero ()),
-    m_gateway (gateway),
-    m_interface (interface)
-{}
-Ipv4Route::Ipv4Route (Ipv4Address dest,
-                      uint32_t interface)
-  : m_dest (dest),
-    m_destNetworkMask (Ipv4Mask::GetZero ()),
-    m_gateway (Ipv4Address::GetZero ()),
-    m_interface (interface)
-{}
-Ipv4Route::Ipv4Route (Ipv4Address network,
-                      Ipv4Mask networkMask,
-                      Ipv4Address gateway,
-                      uint32_t interface)
-  : m_dest (network),
-    m_destNetworkMask (networkMask),
-    m_gateway (gateway),
-    m_interface (interface)
-{}
-Ipv4Route::Ipv4Route (Ipv4Address network,
-                      Ipv4Mask networkMask,
-                      uint32_t interface)
-  : m_dest (network),
-    m_destNetworkMask (networkMask),
-    m_gateway (Ipv4Address::GetZero ()),
-    m_interface (interface)
-{}
-
-bool 
-Ipv4Route::IsHost (void) const
-{
-  if (m_destNetworkMask.IsEqual (Ipv4Mask::GetZero ())) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
 Ipv4Address 
-Ipv4Route::GetDest (void) const
+Ipv4Route::GetDestination (void) const
 {
   return m_dest;
 }
-bool 
-Ipv4Route::IsNetwork (void) const
-{
-  return !IsHost ();
-}
-bool 
-Ipv4Route::IsDefault (void) const
+
+void 
+Ipv4Route::SetSource (Ipv4Address src)
 {
-  if (m_dest.IsEqual (Ipv4Address::GetZero ())) 
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
+  m_source = src;
 }
+
 Ipv4Address 
-Ipv4Route::GetDestNetwork (void) const
+Ipv4Route::GetSource (void) const
 {
-  return m_dest;
+  return m_source;
 }
-Ipv4Mask 
-Ipv4Route::GetDestNetworkMask (void) const
-{
-  return m_destNetworkMask;
-}
-bool 
-Ipv4Route::IsGateway (void) const
+
+void 
+Ipv4Route::SetGateway (Ipv4Address gw)
 {
-  if (m_gateway.IsEqual (Ipv4Address::GetZero ())) 
-    {
-      return false;
-    } 
-  else 
-    {
-      return true;
-    }
+  m_gateway = gw;
 }
+
 Ipv4Address 
 Ipv4Route::GetGateway (void) const
 {
   return m_gateway;
 }
-uint32_t
-Ipv4Route::GetInterface (void) const
+
+void 
+Ipv4Route::SetOutputDevice (Ptr<NetDevice> outputDevice)
 {
-  return m_interface;
+  m_outputDevice = outputDevice;
 }
 
-Ipv4Route 
-Ipv4Route::CreateHostRouteTo (Ipv4Address dest, 
-			      Ipv4Address nextHop, 
-			      uint32_t interface)
-{
-  return Ipv4Route (dest, nextHop, interface);
-}
-Ipv4Route 
-Ipv4Route::CreateHostRouteTo (Ipv4Address dest,
-			      uint32_t interface)
-{
-  return Ipv4Route (dest, interface);
-}
-Ipv4Route 
-Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, 
-				 Ipv4Mask networkMask, 
-				 Ipv4Address nextHop, 
-				 uint32_t interface)
+Ptr<NetDevice> 
+Ipv4Route::GetOutputDevice (void) const
 {
-  return Ipv4Route (network, networkMask, 
-                    nextHop, interface);
+  return m_outputDevice;
 }
-Ipv4Route 
-Ipv4Route::CreateNetworkRouteTo (Ipv4Address network, 
-				 Ipv4Mask networkMask, 
-				 uint32_t interface)
-{
-  return Ipv4Route (network, networkMask, 
-                    interface);
-}
-Ipv4Route 
-Ipv4Route::CreateDefaultRoute (Ipv4Address nextHop, 
-			       uint32_t interface)
-{
-  return Ipv4Route (Ipv4Address::GetZero (), nextHop, interface);
-}
-
 
 std::ostream& operator<< (std::ostream& os, Ipv4Route const& route)
 {
-  if (route.IsDefault ())
-    {
-      NS_ASSERT (route.IsGateway ());
-      os << "default out=" << route.GetInterface () << ", next hop=" << route.GetGateway ();
-    }
-  else if (route.IsHost ())
-    {
-      if (route.IsGateway ())
-        {
-          os << "host="<< route.GetDest () << 
-            ", out=" << route.GetInterface () << 
-            ", next hop=" << route.GetGateway ();
-        }
-      else
-        {
-          os << "host="<< route.GetDest () << 
-            ", out=" << route.GetInterface ();
-        }
-    }
-  else if (route.IsNetwork ()) 
-    {
-      if (route.IsGateway ())
-        {
-          os << "network=" << route.GetDestNetwork () <<
-            ", mask=" << route.GetDestNetworkMask () <<
-            ",out=" << route.GetInterface () <<
-            ", next hop=" << route.GetGateway ();
-        }
-      else
-        {
-          os << "network=" << route.GetDestNetwork () <<
-            ", mask=" << route.GetDestNetworkMask () <<
-            ",out=" << route.GetInterface ();
-        }
-    }
-  else
-    {
-      NS_ASSERT (false);
-    }
-  return os;
+   os << "source=" << route.GetSource () << " dest="<< route.GetDestination () <<" gw=" << route.GetGateway ();
+   return os;
 }
 
-/*****************************************************
- *     Ipv4MulticastRoute
- *****************************************************/
-
 Ipv4MulticastRoute::Ipv4MulticastRoute ()
 {
-}
-
-Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const &route)
-: 
-  m_origin (route.m_origin),
-  m_group (route.m_group),
-  m_inputInterface (route.m_inputInterface),
-  m_outputInterfaces (route.m_outputInterfaces)
-{
+  uint32_t initial_ttl = MAX_TTL;
+  // Initialize array to MAX_TTL, which means that all interfaces are "off"
+  for (uint32_t i = 0; i < MAX_INTERFACES; i++)
+    {
+      m_ttls.push_back(initial_ttl);
+    }
 }
 
-Ipv4MulticastRoute::Ipv4MulticastRoute (Ipv4MulticastRoute const *route)
-: 
-  m_origin (route->m_origin),
-  m_group (route->m_group),
-  m_inputInterface (route->m_inputInterface),
-  m_outputInterfaces (route->m_outputInterfaces)
+void 
+Ipv4MulticastRoute::SetGroup (const Ipv4Address group)
 {
+  m_group = group;
 }
 
-Ipv4MulticastRoute::Ipv4MulticastRoute (
-  Ipv4Address origin, 
-  Ipv4Address group, 
-  uint32_t inputInterface, 
-  std::vector<uint32_t> outputInterfaces)
+Ipv4Address 
+Ipv4MulticastRoute::GetGroup (void) const
+{
+  return m_group;
+}
+
+void 
+Ipv4MulticastRoute::SetOrigin (const Ipv4Address origin)
 {
   m_origin = origin;
-  m_group = group;
-  m_inputInterface = inputInterface;
-  m_outputInterfaces = outputInterfaces;
 }
 
 Ipv4Address 
@@ -270,64 +114,28 @@
   return m_origin;
 }
 
-Ipv4Address 
-Ipv4MulticastRoute::GetGroup (void) const
+void 
+Ipv4MulticastRoute::SetParent (uint32_t parent)
 {
-  return m_group;
+  m_parent = parent;
 }
 
 uint32_t 
-Ipv4MulticastRoute::GetInputInterface (void) const
+Ipv4MulticastRoute::GetParent (void) const
 {
-  return m_inputInterface;
+  return m_parent;
 }
 
-uint32_t
-Ipv4MulticastRoute::GetNOutputInterfaces (void) const
+void 
+Ipv4MulticastRoute::SetOutputTtl (uint32_t oif, uint32_t ttl)
 {
-  return m_outputInterfaces.size ();
+  m_ttls[oif] = ttl;
 }
 
 uint32_t
-Ipv4MulticastRoute::GetOutputInterface (uint32_t n) const
-{
-  NS_ASSERT_MSG(n < m_outputInterfaces.size (), 
-    "Ipv4MulticastRoute::GetOutputInterface (): index out of bounds");
-
-  return m_outputInterfaces[n];
-}
-
-std::vector<uint32_t>
-Ipv4MulticastRoute::GetOutputInterfaces (void) const
+Ipv4MulticastRoute::GetOutputTtl (uint32_t oif) const
 {
-  return m_outputInterfaces;
-}
-
-Ipv4MulticastRoute 
-Ipv4MulticastRoute::CreateMulticastRoute (
-  Ipv4Address origin, 
-  Ipv4Address group, 
-  uint32_t inputInterface,
-  std::vector<uint32_t> outputInterfaces)
-{
-  return Ipv4MulticastRoute (origin, group, inputInterface, outputInterfaces);
-}
-
-std::ostream& 
-operator<< (std::ostream& os, Ipv4MulticastRoute const& route)
-{
-  os << "origin=" << route.GetOrigin () << 
-    ", group=" << route.GetGroup () <<
-    ", input interface=" << route.GetInputInterface () <<
-    ", output interfaces=";
-
-  for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i)
-    {
-      os << route.GetOutputInterface (i) << " ";
-
-    }
-
-  return os;
+  return m_ttls[oif];
 }
 
 }//namespace ns3
--- a/src/node/ipv4-route.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/ipv4-route.h	Sat May 30 17:37:38 2009 +0100
@@ -1,6 +1,6 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2005 INRIA
+ * Copyright (c) 2009 University of Washington
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -15,7 +15,6 @@
  * 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 IPV4_ROUTE_H
 #define IPV4_ROUTE_H
@@ -24,157 +23,82 @@
 #include <vector>
 #include <ostream>
 
+#include "ns3/ref-count-base.h"
 #include "ipv4-address.h"
 
 namespace ns3 {
+
+class NetDevice;
+
 /**
- * \ingroup ipv4
- * \brief A record of an IPv4 route
+ *\brief Ipv4 route cache entry (similar to Linux struct rtable)
+ *
+ * In the future, we will add other entries from struct dst_entry, struct rtable, and struct dst_ops as needed.
  */
-class Ipv4Route {
+class Ipv4Route : public RefCountBase {
 public:
-  /**
-   * \brief This constructor does nothing
-   */
   Ipv4Route ();
 
-  /**
-   * \brief Copy Constructor
-   * \param route The route to copy
-   */
-  Ipv4Route (Ipv4Route const &route);
-
-  /**
-   * \brief Copy Constructor
-   * \param route The route to copy
-   */
-  Ipv4Route (Ipv4Route const *route);
+  void SetDestination (Ipv4Address dest);
+  Ipv4Address GetDestination (void) const;
 
-  bool IsHost (void) const;
-  /**
-   * \return The IPv4 address of the destination of this route
-   */
-  Ipv4Address GetDest (void) const;
+  void SetSource (Ipv4Address src);
+  Ipv4Address GetSource (void) const;
 
-  bool IsNetwork (void) const;
-  Ipv4Address GetDestNetwork (void) const;
-  Ipv4Mask GetDestNetworkMask (void) const;
-  /**
-   * \return True if this route is a default route; false otherwise
-   */
-  bool IsDefault (void) const;
-
-  bool IsGateway (void) const;
+  void SetGateway (Ipv4Address gw);
   Ipv4Address GetGateway (void) const;
 
-  uint32_t GetInterface (void) const;
+  // dst_entry.dev
+  void SetOutputDevice (Ptr<NetDevice> outputDevice);
+  Ptr<NetDevice> GetOutputDevice (void) const;
 
-  static Ipv4Route CreateHostRouteTo (Ipv4Address dest, 
-				      Ipv4Address nextHop, 
-				      uint32_t interface);
-  static Ipv4Route CreateHostRouteTo (Ipv4Address dest, 
-				      uint32_t interface);
-  static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, 
-					 Ipv4Mask networkMask, 
-					 Ipv4Address nextHop, 
-					 uint32_t interface);
-  static Ipv4Route CreateNetworkRouteTo (Ipv4Address network, 
-					 Ipv4Mask networkMask, 
-					 uint32_t interface);
-  static Ipv4Route CreateDefaultRoute (Ipv4Address nextHop, 
-				       uint32_t interface);
-  
+#ifdef NOTYET
+  // rtable.idev
+  void SetInputIfIndex (uint32_t iif);
+  uint32_t GetInputIfIndex (void) const;
+#endif
+
 private:
-  Ipv4Route (Ipv4Address network,
-	     Ipv4Mask mask,
-	     Ipv4Address gateway,
-	     uint32_t interface);
-  Ipv4Route (Ipv4Address dest,
-	     Ipv4Mask mask,
-	     uint32_t interface);
-  Ipv4Route (Ipv4Address dest,
-	     Ipv4Address gateway,
-	     uint32_t interface);
-  Ipv4Route (Ipv4Address dest,
-	     uint32_t interface);
-
   Ipv4Address m_dest;
-  Ipv4Mask m_destNetworkMask;
+  Ipv4Address m_source;
   Ipv4Address m_gateway;
-  uint32_t m_interface;
+  Ptr<NetDevice> m_outputDevice;
+#ifdef NOTYET
+  uint32_t m_inputIfIndex;
+#endif
 };
 
 std::ostream& operator<< (std::ostream& os, Ipv4Route const& route);
 
 /**
- * \ingroup ipv4 
- * \brief A record of an IPv4 multicast route
+ *\brief Ipv4 multicast route cache entry (similar to Linux struct mfc_cache)
  */
-class Ipv4MulticastRoute {
+class Ipv4MulticastRoute : public RefCountBase {
 public:
-  /**
-   * \brief This constructor does nothing
-   */
   Ipv4MulticastRoute ();
 
-  /**
-   * \brief Copy Constructor
-   * \param route The route to copy
-   */
-  Ipv4MulticastRoute (Ipv4MulticastRoute const &route);
-
-  /**
-   * \brief Copy Constructor
-   * \param route The route to copy
-   */
-  Ipv4MulticastRoute (Ipv4MulticastRoute const *route);
-
-  /**
-   * \return The IPv4 address of the source of this route
-   */
-  Ipv4Address GetOrigin (void) const;
-
-  /**
-   * \return The IPv4 address of the multicast group of this route
-   */
-  Ipv4Address GetGroup (void) const;
+  void SetGroup (const Ipv4Address group);
+  Ipv4Address GetGroup (void) const; 
 
-  /**
-   * \return The IPv4 address of the input interface of this route
-   */
-  uint32_t GetInputInterface (void) const;
-
-  /**
-   * \return The number of output interfaces of this route
-   */
-  uint32_t GetNOutputInterfaces (void) const;
+  void SetOrigin (const Ipv4Address group);
+  Ipv4Address GetOrigin (void) const; 
+  
+  void SetParent (uint32_t iif);
+  uint32_t GetParent (void) const;
 
-  /**
-   * \return A specified output interface.
-   */
-  uint32_t GetOutputInterface (uint32_t n) const;
-
-  /**
-   * \return A vector of all of the output interfaces of this route.
-   */
-  std::vector<uint32_t> GetOutputInterfaces (void) const;
-
-  static Ipv4MulticastRoute CreateMulticastRoute (Ipv4Address origin, 
-    Ipv4Address group, uint32_t inputInterface,
-    std::vector<uint32_t> outputInterfaces);
+  void SetOutputTtl (uint32_t oif, uint32_t ttl);
+  uint32_t GetOutputTtl (uint32_t oif) const;
+  
+  static const uint32_t MAX_INTERFACES = 16;
+  static const uint32_t MAX_TTL = 255;
 
 private:
-  Ipv4MulticastRoute (Ipv4Address origin, Ipv4Address group, 
-    uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
-
-  Ipv4Address m_origin;
-  Ipv4Address m_group;
-  uint32_t m_inputInterface;
-  std::vector<uint32_t> m_outputInterfaces;
+  Ipv4Address m_group;      // Group 
+  Ipv4Address m_origin;     // Source of packet
+  uint32_t m_parent;        // Source interface
+  std::vector<uint32_t> m_ttls;
 };
 
-std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoute const& route);
-
 }//namespace ns3
 
 #endif /* IPV4_ROUTE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-routing-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,35 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ns3/assert.h"
+#include "ipv4-route.h"
+#include "ipv4-routing-protocol.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4RoutingProtocol);
+
+TypeId Ipv4RoutingProtocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4RoutingProtocol")
+    .SetParent<Object> ()
+    ;
+  return tid;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-routing-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,96 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef IPV4_ROUTING_PROTOCOL_H
+#define IPV4_ROUTING_PROTOCOL_H
+
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/object.h"
+#include "ns3/socket.h"
+#include "ipv4-header.h"
+
+namespace ns3 {
+
+class Ipv4MulticastRoute;
+class Ipv4Route;
+class NetDevice;
+
+/**
+ * \ingroup ipv4 
+ * Abstract base class for Ipv4 routing protocols.  Defines two
+ * virtual functions for packet routing and forwarding.  The first, 
+ * RouteOutput(), is used for locally originated packets, and the second,
+ * RouteInput(), is used for forwarding and/or delivering received packets. 
+ * Also defines the signatures of four callbacks used in RouteInput().
+ *
+ */
+class Ipv4RoutingProtocol : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  typedef Callback<void, Ptr<Ipv4Route>, Ptr<const Packet>, const Ipv4Header &> UnicastForwardCallback;
+  typedef Callback<void, Ptr<Ipv4MulticastRoute>, Ptr<const Packet>, const Ipv4Header &> MulticastForwardCallback;
+  typedef Callback<void, Ptr<const Packet>, const Ipv4Header &, uint32_t > LocalDeliverCallback;
+  typedef Callback<void, Ptr<const Packet>, const Ipv4Header &> ErrorCallback;
+  
+  /**
+   * \brief Query routing cache for an existing route, for an outbound packet
+   *
+   * This lookup is used by transport protocols.  It does not cause any
+   * packet to be forwarded, and is synchronous.  Can be used for
+   * multicast or unicast.  The Linux equivalent is ip_route_output()
+   *
+   * \param header input parameter (used to form key to search for the route)
+   * \param oif Output interface index.  May be zero, or may be bound via
+   *            socket options to a particular output interface.
+   * \param sockerr Output parameter; socket errno 
+   *
+   * \returns a code that indicates what happened in the lookup
+   */
+  virtual Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr) = 0;
+  
+  /**
+   * \brief Route an input packet (to be forwarded or locally delivered)
+   *
+   * This lookup is used in the forwarding process.  The packet is
+   * handed over to the Ipv4RoutingProtocol, and will get forwarded onward
+   * by one of the callbacks.  The Linux equivalent is ip_route_input().
+   * There are four valid outcomes, and a matching callbacks to handle each.
+   *
+   * \param p received packet
+   * \param header input parameter used to form a search key for a route
+   * \param idev Pointer to ingress network device
+   * \param ucb Callback for the case in which the packet is to be forwarded
+   *            as unicast
+   * \param mcb Callback for the case in which the packet is to be forwarded
+   *            as multicast
+   * \param lcb Callback for the case in which the packet is to be locally
+   *            delivered
+   * \param ecb Callback to call if there is an error in forwarding
+   * \returns true if the Ipv4RoutingProtocol takes responsibility for 
+   *          forwarding or delivering the packet, false otherwise
+   */ 
+  virtual bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, 
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+                             LocalDeliverCallback lcb, ErrorCallback ecb) = 0;
+};
+
+} //namespace ns3
+
+#endif /* IPV4_ROUTING_PROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-routing-table-entry.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,333 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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 "ipv4-routing-table-entry.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+/*****************************************************
+ *     Network Ipv4RoutingTableEntry
+ *****************************************************/
+
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry ()
+{}
+
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const &route)
+  : m_dest (route.m_dest),
+    m_destNetworkMask (route.m_destNetworkMask),
+    m_gateway (route.m_gateway),
+    m_interface (route.m_interface)
+{}
+
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const *route)
+  : m_dest (route->m_dest),
+    m_destNetworkMask (route->m_destNetworkMask),
+    m_gateway (route->m_gateway),
+    m_interface (route->m_interface)
+{}
+
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address dest,
+                      Ipv4Address gateway,
+                      uint32_t interface)
+  : m_dest (dest),
+    m_destNetworkMask (Ipv4Mask::GetZero ()),
+    m_gateway (gateway),
+    m_interface (interface)
+{}
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address dest,
+                      uint32_t interface)
+  : m_dest (dest),
+    m_destNetworkMask (Ipv4Mask::GetZero ()),
+    m_gateway (Ipv4Address::GetZero ()),
+    m_interface (interface)
+{}
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address network,
+                      Ipv4Mask networkMask,
+                      Ipv4Address gateway,
+                      uint32_t interface)
+  : m_dest (network),
+    m_destNetworkMask (networkMask),
+    m_gateway (gateway),
+    m_interface (interface)
+{}
+Ipv4RoutingTableEntry::Ipv4RoutingTableEntry (Ipv4Address network,
+                      Ipv4Mask networkMask,
+                      uint32_t interface)
+  : m_dest (network),
+    m_destNetworkMask (networkMask),
+    m_gateway (Ipv4Address::GetZero ()),
+    m_interface (interface)
+{}
+
+bool 
+Ipv4RoutingTableEntry::IsHost (void) const
+{
+  if (m_destNetworkMask.IsEqual (Ipv4Mask::GetZero ())) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+Ipv4Address 
+Ipv4RoutingTableEntry::GetDest (void) const
+{
+  return m_dest;
+}
+bool 
+Ipv4RoutingTableEntry::IsNetwork (void) const
+{
+  return !IsHost ();
+}
+bool 
+Ipv4RoutingTableEntry::IsDefault (void) const
+{
+  if (m_dest.IsEqual (Ipv4Address::GetZero ())) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+Ipv4Address 
+Ipv4RoutingTableEntry::GetDestNetwork (void) const
+{
+  return m_dest;
+}
+Ipv4Mask 
+Ipv4RoutingTableEntry::GetDestNetworkMask (void) const
+{
+  return m_destNetworkMask;
+}
+bool 
+Ipv4RoutingTableEntry::IsGateway (void) const
+{
+  if (m_gateway.IsEqual (Ipv4Address::GetZero ())) 
+    {
+      return false;
+    } 
+  else 
+    {
+      return true;
+    }
+}
+Ipv4Address 
+Ipv4RoutingTableEntry::GetGateway (void) const
+{
+  return m_gateway;
+}
+uint32_t
+Ipv4RoutingTableEntry::GetInterface (void) const
+{
+  return m_interface;
+}
+
+Ipv4RoutingTableEntry 
+Ipv4RoutingTableEntry::CreateHostRouteTo (Ipv4Address dest, 
+			      Ipv4Address nextHop, 
+			      uint32_t interface)
+{
+  return Ipv4RoutingTableEntry (dest, nextHop, interface);
+}
+Ipv4RoutingTableEntry 
+Ipv4RoutingTableEntry::CreateHostRouteTo (Ipv4Address dest,
+			      uint32_t interface)
+{
+  return Ipv4RoutingTableEntry (dest, interface);
+}
+Ipv4RoutingTableEntry 
+Ipv4RoutingTableEntry::CreateNetworkRouteTo (Ipv4Address network, 
+				 Ipv4Mask networkMask, 
+				 Ipv4Address nextHop, 
+				 uint32_t interface)
+{
+  return Ipv4RoutingTableEntry (network, networkMask, 
+                    nextHop, interface);
+}
+Ipv4RoutingTableEntry 
+Ipv4RoutingTableEntry::CreateNetworkRouteTo (Ipv4Address network, 
+				 Ipv4Mask networkMask, 
+				 uint32_t interface)
+{
+  return Ipv4RoutingTableEntry (network, networkMask, 
+                    interface);
+}
+Ipv4RoutingTableEntry 
+Ipv4RoutingTableEntry::CreateDefaultRoute (Ipv4Address nextHop, 
+			       uint32_t interface)
+{
+  return Ipv4RoutingTableEntry (Ipv4Address::GetZero (), nextHop, interface);
+}
+
+
+std::ostream& operator<< (std::ostream& os, Ipv4RoutingTableEntry const& route)
+{
+  if (route.IsDefault ())
+    {
+      NS_ASSERT (route.IsGateway ());
+      os << "default out=" << route.GetInterface () << ", next hop=" << route.GetGateway ();
+    }
+  else if (route.IsHost ())
+    {
+      if (route.IsGateway ())
+        {
+          os << "host="<< route.GetDest () << 
+            ", out=" << route.GetInterface () << 
+            ", next hop=" << route.GetGateway ();
+        }
+      else
+        {
+          os << "host="<< route.GetDest () << 
+            ", out=" << route.GetInterface ();
+        }
+    }
+  else if (route.IsNetwork ()) 
+    {
+      if (route.IsGateway ())
+        {
+          os << "network=" << route.GetDestNetwork () <<
+            ", mask=" << route.GetDestNetworkMask () <<
+            ",out=" << route.GetInterface () <<
+            ", next hop=" << route.GetGateway ();
+        }
+      else
+        {
+          os << "network=" << route.GetDestNetwork () <<
+            ", mask=" << route.GetDestNetworkMask () <<
+            ",out=" << route.GetInterface ();
+        }
+    }
+  else
+    {
+      NS_ASSERT (false);
+    }
+  return os;
+}
+
+/*****************************************************
+ *     Ipv4MulticastRoutingTableEntry
+ *****************************************************/
+
+Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry ()
+{
+}
+
+Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const &route)
+: 
+  m_origin (route.m_origin),
+  m_group (route.m_group),
+  m_inputInterface (route.m_inputInterface),
+  m_outputInterfaces (route.m_outputInterfaces)
+{
+}
+
+Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const *route)
+: 
+  m_origin (route->m_origin),
+  m_group (route->m_group),
+  m_inputInterface (route->m_inputInterface),
+  m_outputInterfaces (route->m_outputInterfaces)
+{
+}
+
+Ipv4MulticastRoutingTableEntry::Ipv4MulticastRoutingTableEntry (
+  Ipv4Address origin, 
+  Ipv4Address group, 
+  uint32_t inputInterface, 
+  std::vector<uint32_t> outputInterfaces)
+{
+  m_origin = origin;
+  m_group = group;
+  m_inputInterface = inputInterface;
+  m_outputInterfaces = outputInterfaces;
+}
+
+Ipv4Address 
+Ipv4MulticastRoutingTableEntry::GetOrigin (void) const
+{
+  return m_origin;
+}
+
+Ipv4Address 
+Ipv4MulticastRoutingTableEntry::GetGroup (void) const
+{
+  return m_group;
+}
+
+uint32_t 
+Ipv4MulticastRoutingTableEntry::GetInputInterface (void) const
+{
+  return m_inputInterface;
+}
+
+uint32_t
+Ipv4MulticastRoutingTableEntry::GetNOutputInterfaces (void) const
+{
+  return m_outputInterfaces.size ();
+}
+
+uint32_t
+Ipv4MulticastRoutingTableEntry::GetOutputInterface (uint32_t n) const
+{
+  NS_ASSERT_MSG(n < m_outputInterfaces.size (), 
+    "Ipv4MulticastRoutingTableEntry::GetOutputInterface (): index out of bounds");
+
+  return m_outputInterfaces[n];
+}
+
+std::vector<uint32_t>
+Ipv4MulticastRoutingTableEntry::GetOutputInterfaces (void) const
+{
+  return m_outputInterfaces;
+}
+
+Ipv4MulticastRoutingTableEntry 
+Ipv4MulticastRoutingTableEntry::CreateMulticastRoute (
+  Ipv4Address origin, 
+  Ipv4Address group, 
+  uint32_t inputInterface,
+  std::vector<uint32_t> outputInterfaces)
+{
+  return Ipv4MulticastRoutingTableEntry (origin, group, inputInterface, outputInterfaces);
+}
+
+std::ostream& 
+operator<< (std::ostream& os, Ipv4MulticastRoutingTableEntry const& route)
+{
+  os << "origin=" << route.GetOrigin () << 
+    ", group=" << route.GetGroup () <<
+    ", input interface=" << route.GetInputInterface () <<
+    ", output interfaces=";
+
+  for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i)
+    {
+      os << route.GetOutputInterface (i) << " ";
+
+    }
+
+  return os;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-routing-table-entry.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,181 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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 IPV4_ROUTING_TABLE_ENTRY_H
+#define IPV4_ROUTING_TABLE_ENTRY_H
+
+#include <list>
+#include <vector>
+#include <ostream>
+
+#include "ns3/ipv4-address.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup internetStack
+ * \brief A record of an IPv4 routing table entry for Ipv4GlobalRouting and Ipv4StaticRouting
+ */
+class Ipv4RoutingTableEntry {
+public:
+  /**
+   * \brief This constructor does nothing
+   */
+  Ipv4RoutingTableEntry ();
+
+  /**
+   * \brief Copy Constructor
+   * \param route The route to copy
+   */
+  Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const &route);
+
+  /**
+   * \brief Copy Constructor
+   * \param route The route to copy
+   */
+  Ipv4RoutingTableEntry (Ipv4RoutingTableEntry const *route);
+
+  bool IsHost (void) const;
+  /**
+   * \return The IPv4 address of the destination of this route
+   */
+  Ipv4Address GetDest (void) const;
+
+  bool IsNetwork (void) const;
+  Ipv4Address GetDestNetwork (void) const;
+  Ipv4Mask GetDestNetworkMask (void) const;
+  /**
+   * \return True if this route is a default route; false otherwise
+   */
+  bool IsDefault (void) const;
+
+  bool IsGateway (void) const;
+  Ipv4Address GetGateway (void) const;
+
+  uint32_t GetInterface (void) const;
+
+  static Ipv4RoutingTableEntry CreateHostRouteTo (Ipv4Address dest, 
+				      Ipv4Address nextHop, 
+				      uint32_t interface);
+  static Ipv4RoutingTableEntry CreateHostRouteTo (Ipv4Address dest, 
+				      uint32_t interface);
+  static Ipv4RoutingTableEntry CreateNetworkRouteTo (Ipv4Address network, 
+					 Ipv4Mask networkMask, 
+					 Ipv4Address nextHop, 
+					 uint32_t interface);
+  static Ipv4RoutingTableEntry CreateNetworkRouteTo (Ipv4Address network, 
+					 Ipv4Mask networkMask, 
+					 uint32_t interface);
+  static Ipv4RoutingTableEntry CreateDefaultRoute (Ipv4Address nextHop, 
+				       uint32_t interface);
+  
+private:
+  Ipv4RoutingTableEntry (Ipv4Address network,
+	     Ipv4Mask mask,
+	     Ipv4Address gateway,
+	     uint32_t interface);
+  Ipv4RoutingTableEntry (Ipv4Address dest,
+	     Ipv4Mask mask,
+	     uint32_t interface);
+  Ipv4RoutingTableEntry (Ipv4Address dest,
+	     Ipv4Address gateway,
+	     uint32_t interface);
+  Ipv4RoutingTableEntry (Ipv4Address dest,
+	     uint32_t interface);
+
+  Ipv4Address m_dest;
+  Ipv4Mask m_destNetworkMask;
+  Ipv4Address m_gateway;
+  uint32_t m_interface;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv4RoutingTableEntry const& route);
+
+/**
+ * \ingroup internetStack
+ * \brief A record of an IPv4 multicast route for Ipv4GlobalRouting and Ipv4StaticRouting
+ */
+class Ipv4MulticastRoutingTableEntry {
+public:
+  /**
+   * \brief This constructor does nothing
+   */
+  Ipv4MulticastRoutingTableEntry ();
+
+  /**
+   * \brief Copy Constructor
+   * \param route The route to copy
+   */
+  Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const &route);
+
+  /**
+   * \brief Copy Constructor
+   * \param route The route to copy
+   */
+  Ipv4MulticastRoutingTableEntry (Ipv4MulticastRoutingTableEntry const *route);
+
+  /**
+   * \return The IPv4 address of the source of this route
+   */
+  Ipv4Address GetOrigin (void) const;
+
+  /**
+   * \return The IPv4 address of the multicast group of this route
+   */
+  Ipv4Address GetGroup (void) const;
+
+  /**
+   * \return The IPv4 address of the input interface of this route
+   */
+  uint32_t GetInputInterface (void) const;
+
+  /**
+   * \return The number of output interfaces of this route
+   */
+  uint32_t GetNOutputInterfaces (void) const;
+
+  /**
+   * \return A specified output interface.
+   */
+  uint32_t GetOutputInterface (uint32_t n) const;
+
+  /**
+   * \return A vector of all of the output interfaces of this route.
+   */
+  std::vector<uint32_t> GetOutputInterfaces (void) const;
+
+  static Ipv4MulticastRoutingTableEntry CreateMulticastRoute (Ipv4Address origin, 
+    Ipv4Address group, uint32_t inputInterface,
+    std::vector<uint32_t> outputInterfaces);
+
+private:
+  Ipv4MulticastRoutingTableEntry (Ipv4Address origin, Ipv4Address group, 
+    uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
+
+  Ipv4Address m_origin;
+  Ipv4Address m_group;
+  uint32_t m_inputInterface;
+  std::vector<uint32_t> m_outputInterfaces;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv4MulticastRoutingTableEntry const& route);
+
+}//namespace ns3
+
+#endif /* IPV4_ROUTING_TABLE_ENTRY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-static-routing.cc	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ipv4-static-routing.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4StaticRouting);
+
+TypeId 
+Ipv4StaticRouting::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4StaticRouting")
+    .SetParent<Ipv4RoutingProtocol> ()
+    ;
+  return tid;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-static-routing.h	Sat May 30 17:37:38 2009 +0100
@@ -0,0 +1,366 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 Georgia Tech Research Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: George F. Riley<riley@ece.gatech.edu>
+ *         Gustavo Carneiro <gjc@inescporto.pt>
+ */
+
+#ifndef IPV4_STATIC_ROUTING_H
+#define IPV4_STATIC_ROUTING_H
+
+#include <list>
+#include <stdint.h>
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/socket.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-routing-protocol.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Ipv4Interface;
+class Ipv4Address;
+class Ipv4Header;
+class Node;
+
+class Ipv4RoutingTableEntry;
+class Ipv4MulticastRoutingTableEntry;
+
+/**
+ * \brief Static routing protocol for IP version 4 stacks.
+ *
+ * In ns-3 we have the concept of a pluggable routing protocol.  Routing
+ * protocols are added to a list maintained by the Ipv4L3Protocol.  Every 
+ * stack gets one routing protocol for free -- the Ipv4StaticRouting routing
+ * protocol is added in the constructor of the Ipv4L3Protocol (this is the 
+ * piece of code that implements the functionality of the IP layer).
+ *
+ * The Ipv4StaticRouting class inherits from the abstract base class 
+ * Ipv4RoutingProtocol that defines the interface methods that a routing 
+ * protocol must support.
+ *
+ * When a packet arrives in the Ipv4L3Protocol for transmission, it comes
+ * either from a local source via Ipv4L3Protocol::Send or from a remote 
+ * source via Ipv4L3Protocol::Forwarding.  In both cases, a function is called
+ * (Ipv4L3Protocol::Lookup) to look up the routing information for the packet.
+ *
+ * The lookup function iterates through the list of routing protocols asking
+ * each to see if it can find a route and send the packet.  A callback is 
+ * provided during each of these calls that should be considered a pre-
+ * packaged send call.  This is done to allow asynchronous calls into 
+ * routing subsystems in order to support on-demand routing, for example.  The
+ * method for requesting this operation is Ipv4StaticRouting::RequestRoute for
+ * the static routing protocol.
+ *
+ * Each routing protocol is also free to implement its own methods for managing
+ * routes which you will find below.  This class manages a set of "static" or
+ * manually configured routes for host, network and multicast routes.
+ *
+ * \see Ipv4RoutingProtocol
+ * \see Ipv4L3Protocol::AddRoutingProtocol
+ * \see Ipv4L3Protocol::Ipv4L3Protocol
+ */
+class Ipv4StaticRouting : public Ipv4RoutingProtocol
+{
+public:
+  static TypeId GetTypeId (void);
+
+/**
+ * \brief Add a host route to the static routing table.
+ *
+ * \param dest The Ipv4Address destination for this route.
+ * \param nextHop The Ipv4Address of the next hop in the route.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  virtual void AddHostRouteTo (Ipv4Address dest, 
+                       Ipv4Address nextHop, 
+                       uint32_t interface) = 0;
+/**
+ * \brief Add a host route to the static routing table.
+ *
+ * \param dest The Ipv4Address destination for this route.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  virtual void AddHostRouteTo (Ipv4Address dest, uint32_t interface) = 0;
+
+/**
+ * \brief Add a network route to the static routing table.
+ *
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param nextHop The next hop in the route to the destination network.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  virtual void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          Ipv4Address nextHop, 
+                          uint32_t interface) = 0;
+
+/**
+ * \brief Add a network route to the static routing table.
+ *
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ *
+ * \see Ipv4Address
+ */
+  virtual void AddNetworkRouteTo (Ipv4Address network, 
+                          Ipv4Mask networkMask, 
+                          uint32_t interface) = 0;
+
+/**
+ * \brief Add a default route to the static routing table.
+ *
+ * This method tells the routing system what to do in the case where a specific
+ * route to a destination is not found.  The system forwards packets to the
+ * specified node in the hope that it knows better how to route the packet.
+ * 
+ * If the default route is set, it is returned as the selected route from 
+ * LookupStatic irrespective of destination address if no specific route is
+ * found.
+ *
+ * \param nextHop The Ipv4Address to send packets to in the hope that they
+ * will be forwarded correctly.
+ * \param interface The network interface index used to send packets.
+ *
+ * \see Ipv4Address
+ * \see Ipv4StaticRouting::Lookup
+ */
+  virtual void SetDefaultRoute (Ipv4Address nextHop, uint32_t interface) = 0;
+
+/**
+ * \brief Get the number of individual unicast routes that have been added
+ * to the routing table.
+ *
+ * \warning The default route counts as one of the routes.
+ */
+  virtual uint32_t GetNRoutes (void) = 0;
+
+/**
+ * \brief Get the default route from the static routing table.
+ *
+ * \return If the default route is set, a pointer to that Ipv4RoutingTableEntry is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * \see Ipv4RoutingTableEntry
+ */
+  virtual Ipv4RoutingTableEntry GetDefaultRoute (void) = 0;
+
+/**
+ * \brief Get a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries.  The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table.  This means that if you
+ * add only a default route, the table will have one entry that can be accessed
+ * either by explicity calling GetDefaultRoute () or by calling GetRoute (0).
+ *
+ * Similarly, if the default route has been set, calling RemoveRoute (0) will
+ * remove the default route.
+ *
+ * \param i The index (into the routing table) of the route to retrieve.  If
+ * the default route has been set, it will occupy index zero.
+ * \return If route is set, a pointer to that Ipv4RoutingTableEntry is returned, otherwise
+ * a zero pointer is returned.
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::RemoveRoute
+ */
+  virtual Ipv4RoutingTableEntry GetRoute (uint32_t i) = 0;
+
+/**
+ * \brief Remove a route from the static unicast routing table.
+ *
+ * Externally, the unicast static routing table appears simply as a table with
+ * n entries.  The one sublety of note is that if a default route has been set
+ * it will appear as the zeroth entry in the table.  This means that if the
+ * default route has been set, calling RemoveRoute (0) will remove the
+ * default route.
+ *
+ * \param i The index (into the routing table) of the route to remove.  If
+ * the default route has been set, it will occupy index zero.
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::GetRoute
+ * \see Ipv4StaticRouting::AddRoute
+ */
+  virtual void RemoveRoute (uint32_t i) = 0;
+
+/**
+ * \brief Add a multicast route to the static routing table.
+ *
+ * A multicast route must specify an origin IP address, a multicast group and
+ * an input network interface index as conditions and provide a vector of
+ * output network interface indices over which packets matching the conditions
+ * are sent.
+ *
+ * Typically there are two main types of multicast routes:  routes of the 
+ * first kind are used during forwarding.  All of the conditions must be
+ * exlicitly provided.  The second kind of routes are used to get packets off
+ * of a local node.  The difference is in the input interface.  Routes for
+ * forwarding will always have an explicit input interface specified.  Routes
+ * off of a node will always set the input interface to a wildcard specified
+ * by the index Ipv4RoutingProtocol::INTERFACE_ANY.
+ *
+ * For routes off of a local node wildcards may be used in the origin and
+ * multicast group addresses.  The wildcard used for Ipv4Adresses is that 
+ * address returned by Ipv4Address::GetAny () -- typically "0.0.0.0".  Usage
+ * of a wildcard allows one to specify default behavior to varying degrees.
+ *
+ * For example, making the origin address a wildcard, but leaving the 
+ * multicast group specific allows one (in the case of a node with multiple
+ * interfaces) to create different routes using different output interfaces
+ * for each multicast group.
+ *
+ * If the origin and multicast addresses are made wildcards, you have created
+ * essentially a default multicast address that can forward to multiple 
+ * interfaces.  Compare this to the actual default multicast address that is
+ * limited to specifying a single output interface for compatibility with
+ * existing functionality in other systems.
+ * 
+ * \param origin The Ipv4Address of the origin of packets for this route.  May
+ * be Ipv4Address:GetAny for open groups.
+ * \param group The Ipv4Address of the multicast group or this route.
+ * \param inputInterface The input network interface index over which to 
+ * expect packets destined for this route.  May be
+ * Ipv4RoutingProtocol::INTERFACE_ANY for packets of local origin.
+ * \param outputInterfaces A vector of network interface indices used to specify
+ * how to send packets to the destination(s).
+ *
+ * \see Ipv4Address
+ */
+  virtual void AddMulticastRoute (Ipv4Address origin,
+                          Ipv4Address group,
+                          uint32_t inputInterface,
+                          std::vector<uint32_t> outputInterfaces) = 0;
+
+/**
+ * \brief Add a default multicast route to the static routing table.
+ *
+ * This is the multicast equivalent of the unicast version SetDefaultRoute.
+ * We tell the routing system what to do in the case where a specific route
+ * to a destination multicast group is not found.  The system forwards 
+ * packets out the specified interface in the hope that "something out there"
+ * knows better how to route the packet.  This method is only used in 
+ * initially sending packets off of a host.  The default multicast route is
+ * not consulted during forwarding -- exact routes must be specified using
+ * AddMulticastRoute for that case.
+ *
+ * Since we're basically sending packets to some entity we think may know
+ * better what to do, we don't pay attention to "subtleties" like origin
+ * address, nor do we worry about forwarding out multiple  interfaces.  If the
+ * default multicast route is set, it is returned as the selected route from 
+ * LookupStatic irrespective of origin or multicast group if another specific
+ * route is not found.
+ *
+ * \param outputInterface The network interface index used to specify where
+ * to send packets in the case of unknown routes.
+ *
+ * \see Ipv4Address
+ */
+  virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0;
+
+/**
+ * \brief Get the number of individual multicast routes that have been added
+ * to the routing table.
+ *
+ * \warning The default multicast route counts as one of the routes.
+ */
+  virtual uint32_t GetNMulticastRoutes (void) const = 0;
+
+/**
+ * \brief Get a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ * 
+ * \param i The index (into the routing table) of the multicast route to
+ * retrieve.  
+ * \return If route \e i is set, a pointer to that Ipv4MulticastRoutingTableEntry is
+ * returned, otherwise a zero pointer is returned.
+ *
+ * \see Ipv4MulticastRoutingTableEntry
+ * \see Ipv4StaticRouting::RemoveRoute
+ */
+  virtual Ipv4MulticastRoutingTableEntry GetMulticastRoute (uint32_t i) const = 0;
+
+/**
+ * \brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ * This method causes the multicast routing table to be searched for the first
+ * route that matches the parameters and removes it.
+ *
+ * Wildcards may be provided to this function, but the wildcards are used to
+ * exacly match wildcards in the routes (see AddMulticastRoute).  That is,
+ * calling RemoveMulticastRoute with the origin set to "0.0.0.0" will not
+ * remove routes with any address in the origin, but will only remove routes
+ * with "0.0.0.0" set as the the origin.
+ *
+ * \param origin The IP address specified as the origin of packets for the
+ * route.
+ * \param group The IP address specified as the multicast group addres of
+ * the route.
+ * \param inputInterface The network interface index specified as the expected
+ * input interface for the route.
+ * \returns true if a route was found and removed, false otherwise.
+ *
+ * \see Ipv4MulticastRoutingTableEntry
+ * \see Ipv4StaticRouting::AddMulticastRoute
+ */
+  virtual bool RemoveMulticastRoute (Ipv4Address origin,
+                             Ipv4Address group,
+                             uint32_t inputInterface) = 0;
+
+/**
+ * \brief Remove a route from the static multicast routing table.
+ *
+ * Externally, the multicast static routing table appears simply as a table 
+ * with n entries.  
+ *
+ * \param index The index (into the multicast routing table) of the route to
+ * remove.  
+ *
+ * \see Ipv4RoutingTableEntry
+ * \see Ipv4StaticRouting::GetRoute
+ * \see Ipv4StaticRouting::AddRoute
+ */
+  virtual void RemoveMulticastRoute (uint32_t index) = 0;
+
+  virtual void SetNode (Ptr<Node> node) = 0;
+  virtual Ptr<Node> GetNode (void) const = 0;
+
+};
+
+} // Namespace ns3
+
+#endif /* IPV4_STATIC_ROUTING_H */
--- a/src/node/ipv4.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/ipv4.cc	Sat May 30 17:37:38 2009 +0100
@@ -20,6 +20,7 @@
 
 #include "ns3/assert.h" 
 #include "ns3/node.h" 
+#include "ns3/boolean.h"
 #include "ipv4.h"
 
 namespace ns3 {
@@ -30,7 +31,20 @@
 Ipv4::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::Ipv4")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("IpForward", "If enabled, node can act as unicast router.",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&Ipv4::SetIpForward,
+                                        &Ipv4::GetIpForward),
+                   MakeBooleanChecker ())
+#if 0
+    .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&UdpSocket::SetMtuDiscover,
+                                        &UdpSocket::GetMtuDiscover),
+                   MakeBooleanChecker ())
+#endif
+    ;
   return tid;
 }
 
@@ -40,23 +54,4 @@
 Ipv4::~Ipv4 ()
 {}
 
-uint32_t 
-Ipv4::GetInterfaceByAddress (Ipv4Address addr, Ipv4Mask mask)
-{
-  for (uint32_t i = 0; i < GetNInterfaces (); i++)
-    {
-      for (uint32_t j = 0; j < GetNAddresses (i); j++)
-        {
-          Ipv4InterfaceAddress ipv4InAddr = GetAddress (i, j);
-          if (ipv4InAddr.GetLocal ().CombineMask(mask) == addr.CombineMask(mask) )
-            {
-              return i;
-            }
-        }
-    }
-  // Mapping not found
-  NS_ASSERT_MSG (false, "Ipv4::GetInterfaceByAddress failed");
-  return 0;
-}
-
 } // namespace ns3
--- a/src/node/ipv4.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/ipv4.h	Sat May 30 17:37:38 2009 +0100
@@ -21,19 +21,18 @@
 #define IPV4_H
 
 #include <stdint.h>
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4-interface-address.h"
 #include "ns3/object.h"
+#include "ns3/socket.h"
 #include "ns3/callback.h"
-#include "ipv4-route.h"
+#include "ipv4-routing-protocol.h"
+#include "ipv4-address.h"
+#include "ipv4-interface-address.h"
 
 namespace ns3 {
 
 class Node;
 class NetDevice;
 class Packet;
-class Ipv4Route;
-class Ipv4Header;
 
 /**
  * \ingroup node
@@ -41,129 +40,35 @@
  */
 
 /**
- * \ingroup ipv4
- *
- * \brief Base class for IPv4 routing protocols.
+ * \brief Access to the Ipv4 forwarding table, interfaces, and configuration
  *
- * This class represents the interface between the IPv4 routing core
- * and a specific IPv4 routing protocol.  The interface is
- * asynchronous (callback based) in order to support reactive routing
- * protocols (e.g. AODV).
- */
-class Ipv4RoutingProtocol : public Object
-{
-public:
-  // void (*RouteReply) (bool found, Ipv4Route route, Packet packet, Ipv4Header const &ipHeader);
-
-
-  /**
-   * \brief Callback to be invoked when route discovery is completed
-   *
-   * \param bool flag indicating whether a route was actually found;
-   * when this is false, the Ipv4Route parameter is ignored
-   *
-   * \param Ipv4Route the route found
-   *
-   * \param Packet the packet for which a route was requested; can be
-   * modified by the routing protocol
-   *
-   * \param Ipv4Header the IP header supplied to the route request
-   * method (possibly modified in case a new routing header is
-   * inserted and consequently the protocol type has to change).
-   *
-   */
-  typedef Callback<void, bool, const Ipv4Route&, Ptr<Packet>, const Ipv4Header&> RouteReplyCallback;
-
-  /**
-   * \brief Request that a packet be routed.
-   *
-   * \param interface The interface index on which the packet was received.
-   * \param ipHeader IP header of the packet
-   * \param packet packet that is being sent or forwarded
-   * \param routeReply callback that will receive the route reply
-   *
-   * \returns true if the routing protocol should be able to get the
-   * route, false otherwise.
-   *
-   * This method is called whenever a node's IPv4 forwarding engine
-   * needs to lookup a route for a given packet and IP header.
-   *
-   * The routing protocol implementation may determine immediately it
-   * should not be handling this particular the route request.  For
-   * instance, a routing protocol may decline to search for routes for
-   * certain classes of addresses, like link-local.  In this case,
-   * RequestRoute() should return false and the routeReply callback
-   * must not be invoked.
-   *
-   * If the routing protocol implementation assumes that it can provide
-   * the requested route, then it should return true, and the
-   * routeReply callback must be invoked, either immediately before
-   * returning true (synchronously), or in the future (asynchronous).
-   * The routing protocol may use any information available in the IP
-   * header and packet as routing key, although most routing protocols
-   * use only the destination address (as given by
-   * ipHeader.GetDestination ()).  The routing protocol is also
-   * allowed to add a new header to the packet, which will appear
-   * immediately after the IP header, although most routing do not
-   * insert any extra header.
-   *
-   * Multicast routing is expected to be supported in this method.  If a
-   * multicast route is encountered, all routes to a given multicast
-   * destination will be serviced by cloning the packet and calling the 
-   * route reply callback once for each outgoing interface in the route.
-   */
-  virtual bool RequestRoute (uint32_t interface,
-                             const Ipv4Header &ipHeader,
-                             Ptr<Packet> packet,
-                             RouteReplyCallback routeReply) = 0;
-
-/**
- * \brief Synchronously check to see if we can determine the interface index 
- * that will be used if a packet is sent to this destination.
+ * This class defines the API to manipulate the following aspects of
+ * the Ipv4 implementation:  
+ * -# set/get an Ipv4RoutingProtocol 
+ * -# register a NetDevice for use by the Ipv4 layer (basically, to
+ * create Ipv4-related state such as addressing and neighbor cache that 
+ * is associated with a NetDevice)
+ * -# manipulate the status of the NetDevice from the Ipv4 perspective, 
+ * such as marking it as Up or Down, 
+ * -# adding, deleting, and getting addresses associated to the Ipv4 
+ * interfaces.
+ * -# exporting Ipv4 configuration attributes
+ * 
+ * Each NetDevice has conceptually a single Ipv4 interface associated
+ * with it (the corresponding structure in the Linux Ipv4 implementation
+ * is struct in_device).  Each interface may have one or more Ipv4
+ * addresses associated with it.  Each Ipv4 address may have different
+ * subnet mask, scope, etc., so all of this per-address information 
+ * is stored in an Ipv4InterfaceAddress class (the corresponding 
+ * structure in Linux is struct in_ifaddr)
  *
- * This method addresses a problem in the IP stack where a destination address
- * must be present and checksummed into the IP header before the actual 
- * interface over which the packet is sent can be determined.  The answer is
- * to implement a known and intentional cross-layer violation.  This is the
- * endpoint of a call chain that started up quite high in the stack (sockets)
- * and has found its way down to the Ipv4L3Protocol which is consulting the
- * routing protocols for what they would do if presented with a packet of the
- * given destination.
- *
- * Note that the a single interface index is returned.  This means that if
- * the destination address is a multicast, and an explicit route is present
- * that includeds multiple output interfaces, that route cannot be used.
- * 
- * If there are multiple paths out of the node, the resolution is performed
- * by Ipv4L3Protocol::GetInterfaceforDestination which has access to more 
- * contextual information that is useful for making a determination.
+ * Ipv4 attributes such as whether IP forwarding is enabled and disabled
+ * are also stored in this class
  *
- * \param destination The Ipv4Address if the destination of a hypothetical 
- * packet.  This may be a multicast group address.
- * \param interface A reference to the interface index over which a packet
- * sent to this destination would be sent.
- * \return Returns true if a route is found to the destination that involves
- * a single output interface index, otherwise false.
+ * TO DO:  Add API to allow access to the Ipv4 neighbor table
  *
- * \see Ipv4StaticRouting
  * \see Ipv4RoutingProtocol
- * \see Ipv4L3Protocol
- */
-  virtual bool RequestInterface (Ipv4Address destination, 
-                              uint32_t& interface) = 0;
-
-  static const uint32_t INTERFACE_ANY = 0xffffffff;
-};
-
-/**
- * \brief Access to the Ipv4 forwarding table and to the ipv4 interfaces
- *
- * This class allows you to create ipv4 interfaces based on a NetDevice.
- * Multiple interfaces can be created for a single NetDevice, hence
- * achieving multihoming.
- *
- * This class also allows you to control the content of the ipv4 
- * forwarding table.
+ * \see Ipv4InterfaceAddress
  */
 class Ipv4 : public Object
 {
@@ -173,143 +78,27 @@
   virtual ~Ipv4 ();
 
   /**
-   * \brief Register a new routing protocol to be used in this IPv4 stack
+   * \brief Register a new routing protocol to be used by this Ipv4 stack
+   *   
+   * This call will replace any routing protocol that has been previously 
+   * registered.  If you want to add multiple routing protocols, you must
+   * add them to a Ipv4ListRoutingProtocol directly.
    * 
-   * \param routingProtocol new routing protocol implementation object
-   * \param priority priority to give to this routing protocol.
-   * Values may range between -32768 and +32767.  The priority 0
-   * corresponds to static routing table lookups, higher values have
-   * more priority.  The order by which routing protocols with the
-   * same priority value are consulted is undefined.
-   */
-  virtual void AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
-                                   int16_t priority) = 0;
-  
-  /**
-   * \param dest destination address
-   * \param nextHop address of next hop.
-   * \param interface interface of next hop.
-   *
-   * Add route to host dest through host nextHop 
-   * on interface.
-   */
-  virtual void AddHostRouteTo (Ipv4Address dest, 
-			       Ipv4Address nextHop, 
-			       uint32_t interface) = 0;
-  /**
-   * \param dest destination address
-   * \param interface of next hop
-   *
-   * add route to host dest on interface.
+   * \param routing smart pointer to Ipv4RoutingProtocol object
    */
-  virtual void AddHostRouteTo (Ipv4Address dest, 
-			       uint32_t interface) = 0;
-
-  /**
-   * \param network destination network
-   * \param networkMask netmask of destination network
-   * \param nextHop address of next hop
-   * \param interface interface of next hop
-   * 
-   * add route to network dest with netmask 
-   * through host nextHop on interface
-   */
-  virtual void AddNetworkRouteTo (Ipv4Address network, 
-				  Ipv4Mask networkMask, 
-				  Ipv4Address nextHop, 
-				  uint32_t interface) = 0;
-
-  /**
-   * \param network destination network
-   * \param networkMask netmask of destination network
-   * \param interface interface of next hop
-   *
-   * add route to network dest with netmask 
-   * on interface
-   */
-  virtual void AddNetworkRouteTo (Ipv4Address network, 
-				  Ipv4Mask networkMask, 
-				  uint32_t interface) = 0;
-  /**
-   * \param nextHop address of default next hop
-   * \param interface interface of default next hop.
-   * 
-   * set the default route to host nextHop on
-   * interface. 
-   */
-  virtual void SetDefaultRoute (Ipv4Address nextHop, 
-				uint32_t interface) = 0;
+  virtual void SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol) = 0;
 
   /**
-   * \returns the number of entries in the routing table.
+   * \brief Get the routing protocol to be used by this Ipv4 stack
+   * 
+   * \returns smart pointer to Ipv4RoutingProtocol object, or null pointer if none
    */
-  virtual uint32_t GetNRoutes (void) = 0;
-
-  /**
-   * \param i index of route to return
-   * \returns the route whose index is i
-   */
-  virtual Ipv4Route GetRoute (uint32_t i) = 0;
-
-  /**
-   * \param i index of route to remove from routing table.
-   */
-  virtual void RemoveRoute (uint32_t i) = 0;
+  virtual Ptr<Ipv4RoutingProtocol> GetRoutingProtocol (void) const = 0;
 
   /**
-   * \brief Add a static multicast route for a given multicast source and 
-   *        group.
-   *
-   * \param origin The Ipv4 address of the multicast source.
-   * \param group The multicast group address.
-   * \param inputInterface The interface index over which the packet arrived.
-   * \param outputInterfaces The list of output interface indices over which 
-   *        the packet should be sent (excluding the inputInterface).
-   */
-  virtual void AddMulticastRoute (Ipv4Address origin,
-                                  Ipv4Address group,
-                                  uint32_t inputInterface,
-                                  std::vector<uint32_t> outputInterfaces) = 0;
-  /**
-   * \brief Remove a static multicast route for a given multicast source and
-   *        group.
-   *
-   * \param origin The Ipv4 address of the multicast source.
-   * \param group The multicast group address.
-   * \param inputInterface The interface index over which the packet arrived.
-   */
-  virtual void RemoveMulticastRoute (Ipv4Address origin,
-                                     Ipv4Address group,
-                                     uint32_t inputInterface) = 0;
-  
-  /**
-   * \brief Set the default static multicast route.
-   *
-   * \param outputInterface The network output interface index over which 
-   *        packets without specific routes should be sent.
-   */
-  virtual void SetDefaultMulticastRoute (uint32_t outputInterface) = 0;
-
-  /**
-   * \returns the number of entries in the multicast routing table.
-   */
-  virtual uint32_t GetNMulticastRoutes (void) const = 0;
-
-  /**
-   * \param i index of route to return
-   * \returns the route whose index is i
-   */
-  virtual Ipv4MulticastRoute GetMulticastRoute (uint32_t i) const = 0;
-
-  /**
-   * \param i index of route to remove from routing table.
-   */
-  virtual void RemoveMulticastRoute (uint32_t i) = 0;
-
-  /**
-   * \param device device to add to the list of ipv4 interfaces
+   * \param device device to add to the list of Ipv4 interfaces
    *        which can be used as output interfaces during packet forwarding.
-   * \returns the index of the ipv4 interface added.
+   * \returns the index of the Ipv4 interface added.
    *
    * Once a device has been added, it can never be removed: if you want
    * to disable it, you can invoke Ipv4::SetDown which will
@@ -323,73 +112,50 @@
   virtual uint32_t GetNInterfaces (void) const = 0;  
 
   /**
-   * \brief Find and return the interface ID of the interface that has been
+   * \brief Return the interface number of the interface that has been
    *        assigned the specified IP address.
-   * \param addr The IP address assigned to the interface of interest.
-   * \returns The index of the ipv4 interface with the given address.
+   *
+   * \param address The IP address being searched for
+   * \returns The interface number of the Ipv4 interface with the given 
+   *          address or -1 if not found.
    *
-   * Each IP interface has an IP address associated with it.  It is often 
-   * useful to search the list of interfaces for one that corresponds to 
-   * a known IP Address.  This call takes an IP address as a parameter and
-   * returns the interface index of the first interface that has been assigned
-   * that address.  If the address is not found, this function asserts.
+   * Each IP interface has one or more IP addresses associated with it.  
+   * This method searches the list of interfaces for one that holds a
+   * particular address.  This call takes an IP address as a parameter and
+   * returns the interface number of the first interface that has been assigned
+   * that address, or -1 if not found.  There must be an exact match.
    */
-  virtual uint32_t FindInterfaceForAddr (Ipv4Address addr) const = 0;
+  virtual int32_t GetInterfaceForAddress (Ipv4Address address) const = 0;
 
   /**
-   * \brief Find and return the interface ID of the interface that has been
-   *        assigned the specified (masked) IP address.
+   * \brief Return the interface number of first interface found that 
+   *  has an Ipv4 address within the prefix specified by the input
+   *  address and mask parameters
+   *
    * \param addr The IP address assigned to the interface of interest.
-   * \param mask The address mask to be used in address matching.
-   * \returns The index of the ipv4 interface with the given address.
+   * \returns The interface number of the Ipv4 interface with the given 
+   *          address or -1 if not found.
    *
-   * Each IP interface has an IP address associated with it.  It is often 
-   * useful to search the list of interfaces for one that corresponds to 
-   * a known IP Address.  This call takes an IP address and an IP address
-   * mask as parameters and returns the interface index of the first interface
-   * that matches the masked IP address.
+   * Each IP interface has one or more IP addresses associated with it.  
+   * This method searches the list of interfaces for the first one found
+   * that holds an address that is included within the prefix 
+   * formed by the input address and mask parameters.  The value -1 is
+   * returned if no match is found.
    */
-  virtual uint32_t FindInterfaceForAddr (Ipv4Address addr, 
+  virtual int32_t GetInterfaceForPrefix (Ipv4Address address,
     Ipv4Mask mask) const = 0;
 
   /**
-   * \brief Find and return the interface ID of the interface that has been
-   *        associated with the specified (masked) NetDevice
-   * \param nd The net device of the interface of interest.
-   * \returns The index of the ipv4 interface associated with the given net 
-   *          device or -1 if not found.
-   *
-   * Each IP interface is associated with a net device.  It is often 
-   * useful to search the list of interfaces for one that corresponds to 
-   * a known net device.  This call takes an smart pointer to a net device
-   * and returns the interface index of the first interface that matches the
-   * net device.
+   * \param interface The interface number of an Ipv4 interface.
+   * \returns The NetDevice associated with the Ipv4 interface number.
    */
-  virtual int32_t FindInterfaceForDevice(Ptr<NetDevice> nd) const = 0;
+  virtual Ptr<NetDevice> GetNetDevice (uint32_t interface) = 0;
 
   /**
-   * \param i index of ipv4 interface
-   * \returns the NetDevice associated with the ipv4 interface index
+   * \param device The NetDevice for an Ipv4Interface
+   * \returns The interface number of an Ipv4 interface or -1 if not found.
    */
-  virtual Ptr<NetDevice> GetNetDevice (uint32_t i) = 0;
-
-  /**
-   * \brief Join a multicast group for a given multicast source and 
-   *        group.
-   *
-   * \param origin The Ipv4 address of the multicast source.
-   * \param group The multicast group address.
-   */
-  virtual void JoinMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
-
-  /**
-   * \brief Leave a multicast group for a given multicast source and 
-   *        group.
-   *
-   * \param origin The Ipv4 address of the multicast source.
-   * \param group The multicast group address.
-   */
-  virtual void LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group) = 0;
+  virtual int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const = 0;
 
   /**
    * \param interface Interface number of an Ipv4 interface
@@ -406,86 +172,61 @@
 
   /**
    * \param interface Interface number of an Ipv4 interface
-   * \param addressIndex index of Ipv4InterfaceAddress
+   * \param addressIndex index of Ipv4InterfaceAddress 
    * \returns the Ipv4InterfaceAddress associated to the interface and addresIndex
    */
   virtual Ipv4InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0;
 
   /**
-   * \param i index of ipv4 interface
+   * \param interface The interface number of an Ipv4 interface
    * \param metric routing metric (cost) associated to the underlying 
-   *          ipv4 interface
+   *          Ipv4 interface
    */
-  virtual void SetMetric (uint32_t i, uint16_t metric) = 0;
-
-  /**
-   * \param i index of ipv4 interface
-   * \returns routing metric (cost) associated to the underlying 
-   *          ipv4 interface
-   */
-  virtual uint16_t GetMetric (uint32_t i) const = 0;
+  virtual void SetMetric (uint32_t interface, uint16_t metric) = 0;
 
   /**
-   * \param destination The IP address of a hypothetical destination.
-   * \returns The IP address assigned to the interface that will be used
-   * if we were to send a packet to destination.
-   *
-   * Note that the broadcast address for this interface may be fetched
-   * from the Ipv4Address object returned here using
-   * Ipv4Address::GetSubnetDirectedBroadcast(mask), where the mask for
-   * the interface may be retrived using Ipv4::GetNetworkMask(i).
+   * \param interface The interface number of an Ipv4 interface
+   * \returns routing metric (cost) associated to the underlying 
+   *          Ipv4 interface
    */
-  virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0;
+  virtual uint16_t GetMetric (uint32_t interface) const = 0;
 
   /**
-   * \param dest The IP address of a hypothetical destination.
-   * \param interface filled in with the interface index that will be used to
-   *        send a packet to the hypothetical destination.
-   * \returns true if a single interface can be identified, false otherwise.
+   * \param interface Interface number of Ipv4 interface
+   * \returns the Maximum Transmission Unit (in bytes) associated
+   *          to the underlying Ipv4 interface
    */
-  virtual bool GetInterfaceForDestination (Ipv4Address dest,
-                                         uint32_t &interface) const = 0;
+  virtual uint16_t GetMtu (uint32_t interface) const = 0;
 
   /**
-   * \param i index of ipv4 interface
-   * \returns the Maximum Transmission Unit (in bytes) associated
-   *          to the underlying ipv4 interface
-   */
-  virtual uint16_t GetMtu (uint32_t i) const = 0;
-
-  /**
-   * \param i index of ipv4 interface
+   * \param interface Interface number of Ipv4 interface
    * \returns true if the underlying interface is in the "up" state,
    *          false otherwise.
    */
-  virtual bool IsUp (uint32_t i) const = 0;
+  virtual bool IsUp (uint32_t interface) const = 0;
 
   /**
-   * \param i index of ipv4 interface
+   * \param i interface Interface number of Ipv4 interface
    * 
    * Set the interface into the "up" state. In this state, it is
-   * considered valid during ipv4 forwarding.
+   * considered valid during Ipv4 forwarding.
    */
-  virtual void SetUp (uint32_t i) = 0;
+  virtual void SetUp (uint32_t interface) = 0;
 
   /**
-   * \param i index of ipv4 interface
+   * \param interface Interface number of Ipv4 interface
    *
    * Set the interface into the "down" state. In this state, it is
-   * ignored during ipv4 forwarding.
+   * ignored during Ipv4 forwarding.
    */
-  virtual void SetDown (uint32_t i) = 0;
+  virtual void SetDown (uint32_t interface) = 0;
 
-  /**
-   * \brief Convenience function to return the interface corresponding
-   * to the Ipv4Address provided
-   *
-   * \param addr Ipv4Address
-   * \param mask corresponding Ipv4Mask
-   * \returns interface corresponding to a/amask
-   */
-  virtual uint32_t GetInterfaceByAddress (Ipv4Address addr, 
-    Ipv4Mask mask = Ipv4Mask("255.255.255.255"));
+  static const uint32_t IF_ANY = 0xffffffff;
+
+private:
+  // Indirect the Ipv4 attributes through private pure virtual methods
+  virtual void SetIpForward (bool forward) = 0;
+  virtual bool GetIpForward (void) const = 0;
 };
 
 } // namespace ns3 
--- a/src/node/udp-socket.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/udp-socket.cc	Sat May 30 17:37:38 2009 +0100
@@ -21,6 +21,7 @@
 #include "ns3/object.h"
 #include "ns3/log.h"
 #include "ns3/uinteger.h"
+#include "ns3/integer.h"
 #include "ns3/boolean.h"
 #include "ns3/trace-source-accessor.h"
 #include "udp-socket.h"
@@ -47,13 +48,25 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&UdpSocket::GetIpTtl,
                                          &UdpSocket::SetIpTtl),
-                   MakeUintegerChecker<uint32_t> ())
+                   MakeUintegerChecker<uint8_t> ())
     .AddAttribute ("IpMulticastTtl",
                    "socket-specific TTL for multicast IP packets (if non-zero)",
                    UintegerValue (0),
                    MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl,
                                          &UdpSocket::SetIpMulticastTtl),
-                   MakeUintegerChecker<uint32_t> ())
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("IpMulticastIf",
+                   "interface index for outgoing multicast on this socket; -1 indicates to use default interface",
+                   IntegerValue (-1),
+                   MakeUintegerAccessor (&UdpSocket::GetIpMulticastTtl,
+                                         &UdpSocket::SetIpMulticastTtl),
+                   MakeIntegerChecker<int32_t> ())
+    .AddAttribute ("IpMulticastLoop",
+                   "whether outgoing multicast sent also to loopback interface",
+                   BooleanValue (false),
+                   MakeUintegerAccessor (&UdpSocket::GetIpMulticastLoop,
+                                         &UdpSocket::SetIpMulticastLoop),
+                   MakeBooleanChecker ())
     .AddAttribute ("MtuDiscover", "If enabled, every outgoing ip packet will have the DF flag set.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&UdpSocket::SetMtuDiscover,
--- a/src/node/udp-socket.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/udp-socket.h	Sat May 30 17:37:38 2009 +0100
@@ -40,7 +40,8 @@
  * \brief (abstract) base class of all UdpSockets
  *
  * This class exists solely for hosting UdpSocket attributes that can
- * be reused across different implementations.
+ * be reused across different implementations, and for declaring
+ * UDP-specific multicast API.
  */
 class UdpSocket : public Socket
 {
@@ -50,14 +51,64 @@
   UdpSocket (void);
   virtual ~UdpSocket (void);
 
+  /**
+   * \brief Corresponds to socket option MCAST_JOIN_GROUP
+   *
+   * \param interface interface number, or 0
+   * \param groupAddress multicast group address
+   * \returns on success, zero is returned.  On error, -1 is returned,
+   *          and errno is set appropriately
+   *
+   * Enable reception of multicast datagrams for this socket on the
+   * interface number specified.  If zero is specified as
+   * the interface, then a single local interface is chosen by
+   * system.  In the future, this function will generate trigger IGMP
+   * joins as necessary when IGMP is implemented, but for now, this
+   * just enables multicast datagram reception in the system if not already
+   * enabled for this interface/groupAddress combination.
+   *
+   * \attention IGMP is not yet implemented in ns-3
+   *
+   * This function may be called repeatedly on a given socket but each
+   * join must be for a different multicast address, or for the same
+   * multicast address but on a different interface from previous joins.
+   * This enables host multihoming, and the ability to join the same 
+   * group on different interfaces.
+   */
+  virtual int MulticastJoinGroup (uint32_t interface, const Address &groupAddress) = 0;
+
+  /**
+   * \brief Corresponds to socket option MCAST_LEAVE_GROUP
+   *
+   * \param interface interface number, or 0
+   * \param groupAddress multicast group address
+   * \returns on success, zero is returned.  On error, -1 is returned,
+   *          and errno is set appropriately
+   *
+   * Disable reception of multicast datagrams for this socket on the
+   * interface number specified.  If zero is specified as
+   * the interfaceIndex, then a single local interface is chosen by
+   * system.  In the future, this function will generate trigger IGMP
+   * leaves as necessary when IGMP is implemented, but for now, this
+   * just disables multicast datagram reception in the system if this
+   * socket is the last for this interface/groupAddress combination.
+   *
+   * \attention IGMP is not yet implemented in ns-3
+   */
+  virtual int MulticastLeaveGroup (uint32_t interface, const Address &groupAddress) = 0;
+
 private:
   // Indirect the attribute setting and getting through private virtual methods
   virtual void SetRcvBufSize (uint32_t size) = 0;
   virtual uint32_t GetRcvBufSize (void) const = 0;
-  virtual void SetIpTtl (uint32_t ipTtl) = 0;
-  virtual uint32_t GetIpTtl (void) const = 0;
-  virtual void SetIpMulticastTtl (uint32_t ipTtl) = 0;
-  virtual uint32_t GetIpMulticastTtl (void) const = 0;
+  virtual void SetIpTtl (uint8_t ipTtl) = 0;
+  virtual uint8_t GetIpTtl (void) const = 0;
+  virtual void SetIpMulticastTtl (uint8_t ipTtl) = 0;
+  virtual uint8_t GetIpMulticastTtl (void) const = 0;
+  virtual void SetIpMulticastIf (int32_t ipIf) = 0;
+  virtual int32_t GetIpMulticastIf (void) const = 0;
+  virtual void SetIpMulticastLoop (bool loop) = 0;
+  virtual bool GetIpMulticastLoop (void) const = 0;
   virtual void SetMtuDiscover (bool discover) = 0;
   virtual bool GetMtuDiscover (void) const = 0;
 };
--- a/src/node/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/src/node/wscript	Sat May 30 17:37:38 2009 +0100
@@ -19,6 +19,10 @@
         'ethernet-header.cc',
         'ethernet-trailer.cc',
         'ipv4-route.cc',
+        'ipv4-routing-protocol.cc',
+        'ipv4-list-routing.cc',
+        'ipv4-static-routing.cc',
+        'ipv4-routing-table-entry.cc',
         'queue.cc',
         'drop-tail-queue.cc',
         'channel.cc',
@@ -52,11 +56,16 @@
         'packet-socket-address.h',
         'node.h',
         'ipv4-address.h',
+        'ipv4-interface-address.h',
         'ipv4-address-generator.h',
         'ipv4-header.h',
         'net-device.h',
 	'address-utils.h',
         'ipv4-route.h',
+        'ipv4-routing-protocol.h',
+        'ipv4-list-routing.h',
+        'ipv4-static-routing.h',
+        'ipv4-routing-table-entry.h',
         'queue.h',
         'drop-tail-queue.h',
         'llc-snap-header.h',
--- a/src/routing/global-routing/global-route-manager-impl.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Sat May 30 17:37:38 2009 +0100
@@ -31,6 +31,8 @@
 #include "ns3/node-list.h"
 #include "ns3/ipv4.h"
 #include "ns3/ipv4-global-routing.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv4-list-routing.h"
 #include "global-router-interface.h"
 #include "global-route-manager-impl.h"
 #include "candidate-queue.h"
@@ -154,7 +156,7 @@
 }
 
   void 
-SPFVertex::SetOutgoingInterfaceId (uint32_t id)
+SPFVertex::SetOutgoingInterfaceId (int32_t id)
 {
   NS_LOG_FUNCTION (id);
   m_rootOif = id;
@@ -414,15 +416,22 @@
 
       NS_LOG_LOGIC ("Adding GlobalRouting Protocol to node " << node->GetId ());
       Ptr<Ipv4GlobalRouting> globalRouting = CreateObject<Ipv4GlobalRouting> ();
+      globalRouting->SetNode (node);
+      // Here, we check whether there is an existing Ipv4RoutingProtocol object
+      // to add this protocol to.
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): GetObject for <Ipv4> interface failed");
+      // Now, we add this to an Ipv4ListRouting object.  
+      // XXX in the future, we may want to allow this to be added to Ipv4
+      // directly
+      Ptr<Ipv4ListRouting> ipv4ListRouting = DynamicCast<Ipv4ListRouting> (ipv4->GetRoutingProtocol ());
+      NS_ASSERT_MSG (ipv4ListRouting, "GlobalRouteManagerImpl::SelectRouterNodes (): Ipv4ListRouting not found"); 
       // This is the object that will keep the global routes.  We insert it
       // at slightly higher priority than static routing (which is at zero).
       // This means that global routes (e.g. host routes) will be consulted
       // before static routes
-      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-      NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): "
-        "GetObject for <Ipv4> interface failed");
       // XXX make the below  priority value an attribute
-      ipv4->AddRoutingProtocol (globalRouting, 3);  
+      ipv4ListRouting->AddRoutingProtocol (globalRouting, 3);  
       // Locally cache the globalRouting pointer; we'll need it later
       // when we add routes
       AddGlobalRoutingProtocol (node->GetId (), globalRouting);
@@ -451,8 +460,10 @@
       Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
       NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): "
         "GetObject for <Ipv4> interface failed");
+      Ptr<Ipv4ListRouting> ipv4ListRouting = DynamicCast<Ipv4ListRouting> (ipv4->GetRoutingProtocol ());
+      NS_ASSERT_MSG (ipv4ListRouting, "GlobalRouteManagerImpl::SelectRouterNodes (): Ipv4ListRouting not found"); 
       // XXX make the below  priority value an attribute
-      ipv4->AddRoutingProtocol (globalRouting, 3);  
+      ipv4ListRouting->AddRoutingProtocol (globalRouting, 3);  
       // Locally cache the globalRouting pointer; we'll need it later
       // when we add routes
       AddGlobalRoutingProtocol (node->GetId (), globalRouting);
@@ -1344,18 +1355,34 @@
 //
           Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
           NS_ASSERT (gr);
-          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
+          if (v->GetOutgoingInterfaceId () >= 0)
+            {
+              gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                " add network route to " << tempip <<
+                " using next hop " << v->GetNextHop () <<
+                " via interface " << v->GetOutgoingInterfaceId ());
+            }
+          else
+            {
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                " NOT able to add network route to " << tempip <<
+                " using next hop " << v->GetNextHop () <<
+                " since outgoing interface id is negative");
+            }
           return;
         } // if
     } // for
 }
 
 //
-// Return the interface index corresponding to a given IP address
-// This is a wrapper around GetInterfaceByIpv4Address(), but we first
+// Return the interface number corresponding to a given IP address and mask
+// This is a wrapper around GetInterfaceForPrefix(), but we first
 // have to find the right node pointer to pass to that function.
+// If no such interface is found, return -1 (note:  unit test framework
+// for routing assumes -1 to be a legal return value)
 //
-  uint32_t
+int32_t
 GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask)
 {
   NS_LOG_FUNCTION (a << amask);
@@ -1400,19 +1427,29 @@
           Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
           NS_ASSERT_MSG (ipv4, 
             "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
-            "QI for <Ipv4> interface failed");
+            "GetObject for <Ipv4> interface failed");
 //
 // Look through the interfaces on this node for one that has the IP address
 // we're looking for.  If we find one, return the corresponding interface
-// index.
+// index, or -1 if not found.
 //
-          return (ipv4->GetInterfaceByAddress (a, amask) );
+          int32_t interface = ipv4->GetInterfaceForPrefix (a, amask);
+
+#if 0
+          if (interface < 0)
+            {
+              NS_FATAL_ERROR ("GlobalRouteManagerImpl::FindOutgoingInterfaceId(): "
+                "Expected an interface associated with address a:" << a);
+            }
+#endif 
+          return interface;
         }
     }
 //
 // Couldn't find it.
 //
-  return 0;
+  NS_LOG_LOGIC ("FindOutgoingInterfaceId():Can't find root node " << routerId);
+  return -1;
 }
 
 //
@@ -1459,8 +1496,8 @@
       Ptr<Node> node = *i;
 //
 // The router ID is accessible through the GlobalRouter interface, so we need
-// to QI for that interface.  If there's no GlobalRouter interface, the node
-// in question cannot be the router we want, so we continue.
+// to GetObject for that interface.  If there's no GlobalRouter interface, 
+// the node in question cannot be the router we want, so we continue.
 // 
       Ptr<GlobalRouter> rtr = 
         node->GetObject<GlobalRouter> ();
@@ -1482,14 +1519,14 @@
         {
           NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
 //
-// Routing information is updated using the Ipv4 interface.  We need to QI
-// for that interface.  If the node is acting as an IP version 4 router, it
-// should absolutely have an Ipv4 interface.
+// Routing information is updated using the Ipv4 interface.  We need to 
+// GetObject for that interface.  If the node is acting as an IP version 4 
+// router, it should absolutely have an Ipv4 interface.
 //
           Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
           NS_ASSERT_MSG (ipv4, 
             "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
-            "QI for <Ipv4> interface failed");
+            "GetObject for <Ipv4> interface failed");
 //
 // Get the Global Router Link State Advertisement from the vertex we're
 // adding the routes to.  The LSA will have a number of attached Global Router
@@ -1542,8 +1579,22 @@
 //
               Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
               NS_ASSERT (gr);
-              gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
-                v->GetOutgoingInterfaceId ());
+              if (v->GetOutgoingInterfaceId () >= 0)
+                {
+                  gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
+                    v->GetOutgoingInterfaceId ());
+                  NS_LOG_LOGIC ("Node " << node->GetId () <<
+                    " adding host route to " << lr->GetLinkData () <<
+                    " using next hop " << v->GetNextHop () <<
+                    " and outgoing interface " << v->GetOutgoingInterfaceId ());
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("Node " << node->GetId () <<
+                    " NOT able to add host route to " << lr->GetLinkData () <<
+                    " using next hop " << v->GetNextHop () <<
+                    " since outgoing interface id is negative");
+                }
             }
 //
 // Done adding the routes for the selected node.
@@ -1580,8 +1631,8 @@
       Ptr<Node> node = *i;
 //
 // The router ID is accessible through the GlobalRouter interface, so we need
-// to QI for that interface.  If there's no GlobalRouter interface, the node
-// in question cannot be the router we want, so we continue.
+// to GetObject for that interface.  If there's no GlobalRouter interface, 
+// the node in question cannot be the router we want, so we continue.
 // 
       Ptr<GlobalRouter> rtr = 
         node->GetObject<GlobalRouter> ();
@@ -1603,14 +1654,14 @@
         {
           NS_LOG_LOGIC ("setting routes for node " << node->GetId ());
 //
-// Routing information is updated using the Ipv4 interface.  We need to QI
-// for that interface.  If the node is acting as an IP version 4 router, it
-// should absolutely have an Ipv4 interface.
+// Routing information is updated using the Ipv4 interface.  We need to 
+// GetObject for that interface.  If the node is acting as an IP version 4 
+// router, it should absolutely have an Ipv4 interface.
 //
           Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
           NS_ASSERT_MSG (ipv4, 
             "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
-            "QI for <Ipv4> interface failed");
+            "GetObject for <Ipv4> interface failed");
 //
 // Get the Global Router Link State Advertisement from the vertex we're
 // adding the routes to.  The LSA will have a number of attached Global Router
@@ -1626,12 +1677,22 @@
           tempip = tempip.CombineMask (tempmask);
           Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
           NS_ASSERT (gr);
-          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
-            v->GetOutgoingInterfaceId ());
-          NS_LOG_LOGIC ("Node " << node->GetId () <<
-            " add network route to " << tempip <<
-            " using next hop " << v->GetNextHop () <<
-            " via interface " << v->GetOutgoingInterfaceId ());
+          if (v->GetOutgoingInterfaceId () >= 0)
+            {
+              gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
+                v->GetOutgoingInterfaceId ());
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                " add network route to " << tempip <<
+                " using next hop " << v->GetNextHop () <<
+                " via interface " << v->GetOutgoingInterfaceId ());
+            }
+          else
+            {
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                " NOT able to add network route to " << tempip <<
+                " using next hop " << v->GetNextHop () <<
+                " since outgoing interface id is negative");
+            }
         }
     } 
 }
--- a/src/routing/global-routing/global-route-manager-impl.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/routing/global-routing/global-route-manager-impl.h	Sat May 30 17:37:38 2009 +0100
@@ -337,7 +337,7 @@
  * @param id The interface index to use when forwarding packets to the host or
  * network represented by "this" SPFVertex.
  */
-  void SetOutgoingInterfaceId (uint32_t id);
+  void SetOutgoingInterfaceId (int32_t id);
 
 /**
  * @brief Get the IP address that should be used to begin forwarding packets 
@@ -569,7 +569,7 @@
   Ipv4Address m_vertexId;
   GlobalRoutingLSA* m_lsa;
   uint32_t m_distanceFromRoot;
-  uint32_t m_rootOif;
+  int32_t m_rootOif;
   Ipv4Address m_nextHop;
   SPFVertex* m_parent;
   typedef std::list<SPFVertex*> ListOfSPFVertex_t;
@@ -799,7 +799,7 @@
   void SPFIntraAddRouter (SPFVertex* v);
   void SPFIntraAddTransit (SPFVertex* v);
   void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);
-  uint32_t FindOutgoingInterfaceId (Ipv4Address a, 
+  int32_t FindOutgoingInterfaceId (Ipv4Address a, 
     Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
 
   // Local cache of the Ipv4GlobalRouting objects, indexed by nodeId
--- a/src/routing/olsr/olsr-routing-protocol.cc	Sat May 30 17:36:50 2009 +0100
+++ b/src/routing/olsr/olsr-routing-protocol.cc	Sat May 30 17:37:38 2009 +0100
@@ -40,6 +40,8 @@
 #include "ns3/log.h"
 #include "ns3/random-variable.h"
 #include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv4-route.h"
 #include "ns3/boolean.h"
 #include "ns3/uinteger.h"
 #include "ns3/enum.h"
@@ -722,7 +724,7 @@
     os << "]";
     NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ());
   }
-#endif
+#endif  //NS3_LOG_ENABLE
 
   m_state.SetMprSet (mprSet);
 }
@@ -1024,7 +1026,7 @@
       }
     NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress);
   }
-#endif
+#endif // NS3_LOG_ENABLE
 
   PopulateNeighborSet (msg, hello);
   PopulateTwoHopNeighborSet (msg, hello);
@@ -1041,7 +1043,7 @@
       }
     NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
   }
-#endif
+#endif // NS3_LOG_ENABLE
 
   MprComputation ();
   PopulateMprSelectorSet (msg, hello);
@@ -1139,7 +1141,7 @@
       }
     NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress);
   }
-#endif
+#endif // NS3_LOG_ENABLE
 }
 
 ///
@@ -1631,7 +1633,7 @@
                     << lt << " (" << linkTypeName
                     << ") and Neighbor Type " << nt
                     << " (" << neighborTypeName << ")");
-#endif
+#endif // NS3_LOG_ENABLE
 
       // We must not process invalid advertised links
       if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
@@ -1755,7 +1757,7 @@
                                           : "(invalid value)");
           NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType="
                         << neighborType << " (" << neighborTypeName << ")");
-#endif
+#endif // NS3_LOG_ENABLE
 
           for (std::vector<Ipv4Address>::const_iterator nb2hop_addr_iter =
                  linkMessage->neighborInterfaceAddresses.begin ();
@@ -2038,7 +2040,7 @@
     {
 #ifdef NS3_LOG_ENABLE
       int statusBefore = nb_tuple->status;
-#endif
+#endif // NS3_LOG_ENABLE
       if (tuple.symTime >= Simulator::Now ())
         {
           nb_tuple->status = NeighborTuple::STATUS_SYM;
@@ -2547,65 +2549,105 @@
   return true;
 }
 
-
-bool
-RoutingProtocol::RequestRoute (uint32_t ifIndex,
-                            const Ipv4Header &ipHeader,
-                            Ptr<Packet> packet,
-                            RouteReplyCallback routeReply)
-{
+Ptr<Ipv4Route>
+RoutingProtocol::RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
+{  
+  NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject<Node> ()->GetId() << " " << header.GetDestination () << " " << oif);
+  // TBD:  oif is unused; can be used to restrict the outgoing interface
+  // of the found route if application bound to a source interface
+  Ptr<Ipv4Route> rtentry;
   RoutingTableEntry entry1, entry2;
-  if (Lookup (ipHeader.GetDestination (), entry1))
+  if (Lookup (header.GetDestination (), entry1) != 0)
     {
       bool foundSendEntry = FindSendEntry (entry1, entry2);
       if (!foundSendEntry)
-        NS_FATAL_ERROR ("FindSendEntry failure");
+        {
+          NS_FATAL_ERROR ("FindSendEntry failure");
+        }
+      rtentry = Create<Ipv4Route> ();
+      rtentry->SetDestination (header.GetDestination ());
+      uint32_t interfaceIdx = entry2.interface;
+      // the source address is the interface address that matches
+      // the destination address (when multiple are present on the 
+      // outgoing interface, one is selected via scoping rules)
+      NS_ASSERT (m_ipv4);  
+      uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceIdx);
+      NS_ASSERT (numOifAddresses > 0);
+      Ipv4InterfaceAddress ifAddr;
+      if (numOifAddresses == 1) {
+        ifAddr = m_ipv4->GetAddress (interfaceIdx, 0);
+      } else {
+        NS_FATAL_ERROR ("XXX Not implemented yet:  IP aliasing and OLSR");
+      }
+      rtentry->SetSource (ifAddr.GetLocal ());
+      rtentry->SetGateway (entry2.nextAddr);
+      rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
+      sockerr = Socket::ERROR_NOTERROR;
+      NS_LOG_DEBUG ("Olsr node " << m_mainAddress 
+                    << ": RouteRequest for dest=" << header.GetDestination ()
+                    << " --> nextHop=" << entry2.nextAddr
+                    << " interface=" << entry2.interface);      NS_LOG_DEBUG ("Found route to " << rtentry->GetDestination () << " via nh " << rtentry->GetGateway () << " with source addr " << rtentry->GetSource () << " and output dev " << rtentry->GetOutputDevice());
+    }
+  else
+    { 
+      sockerr = Socket::ERROR_NOROUTETOHOST;
+    }
+  return rtentry;
+}
 
-      Ipv4Route route = Ipv4Route::CreateHostRouteTo
-        (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface);
-
+bool RoutingProtocol::RouteInput  (Ptr<const Packet> p, 
+  const Ipv4Header &header, Ptr<const NetDevice> idev,                            UnicastForwardCallback ucb, MulticastForwardCallback mcb,             
+  LocalDeliverCallback lcb, ErrorCallback ecb)
+{   
+  NS_LOG_FUNCTION (this << " " << m_ipv4->GetObject<Node> ()->GetId() << " " << header.GetDestination ());
+  
+  Ptr<Ipv4Route> rtentry;
+  RoutingTableEntry entry1, entry2; 
+  if (Lookup (header.GetDestination (), entry1))
+    { 
+      bool foundSendEntry = FindSendEntry (entry1, entry2);
+      if (!foundSendEntry)
+        NS_FATAL_ERROR ("FindSendEntry failure");
+      rtentry = Create<Ipv4Route> ();
+      rtentry->SetDestination (header.GetDestination ());
+      uint32_t interfaceIdx = entry2.interface;
+      // the source address is the interface address that matches
+      // the destination address (when multiple are present on the
+      // outgoing interface, one is selected via scoping rules)
+      NS_ASSERT (m_ipv4);
+      uint32_t numOifAddresses = m_ipv4->GetNAddresses (interfaceIdx);
+      NS_ASSERT (numOifAddresses > 0);
+      Ipv4InterfaceAddress ifAddr;
+      if (numOifAddresses == 1) {
+        ifAddr = m_ipv4->GetAddress (interfaceIdx, 0);
+      } else {
+        NS_FATAL_ERROR ("XXX Not implemented yet:  IP aliasing and OLSR");
+      }
+      rtentry->SetSource (ifAddr.GetLocal ());
+      rtentry->SetGateway (entry2.nextAddr);
+      rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
+      
       NS_LOG_DEBUG ("Olsr node " << m_mainAddress
-                    << ": RouteRequest for dest=" << ipHeader.GetDestination ()
-                    << " --> nestHop=" << entry2.nextAddr
+                    << ": RouteRequest for dest=" << header.GetDestination ()
+                    << " --> nextHop=" << entry2.nextAddr
                     << " interface=" << entry2.interface);
       
-      routeReply (true, route, packet, ipHeader);
+      ucb (rtentry, p, header);
       return true;
     }
   else
     {
 #ifdef NS3_LOG_ENABLE
-      NS_LOG_DEBUG ("Olsr node " << m_mainAddress
-                    << ": RouteRequest for dest=" << ipHeader.GetDestination ()
-                    << " --> NOT FOUND; ** Dumping routing table...");
-      for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin ();
+      NS_LOG_DEBUG ("Olsr node " << m_mainAddress 
+                    << ": RouteRequest for dest=" << header.GetDestination ()
+                    << " --> NOT FOUND; ** Dumping routing table...");      for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator iter = m_table.begin ();
            iter != m_table.end (); iter++)
-        {
-          NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr
+        {           NS_LOG_DEBUG ("dest=" << iter->first << " --> next=" << iter->second.nextAddr                 
                         << " via interface " << iter->second.interface);
         }
-
+      
       NS_LOG_DEBUG ("** Routing table dump end.");
-#endif
-      return false;
-    }
-}
-
-bool
-RoutingProtocol::RequestInterface (Ipv4Address destination,
-                              uint32_t& ifIndex)
-{
-  RoutingTableEntry entry1, entry2;
-  if (Lookup (destination, entry1))
-    {
-      bool foundSendEntry = FindSendEntry (entry1, entry2);
-      if (!foundSendEntry)
-        NS_FATAL_ERROR ("FindSendEntry failure");
-      ifIndex = entry2.interface;
-      return true;
-    }
-  else
-    {
+#endif // NS3_LOG_ENABLE
       return false;
     }
 }
--- a/src/routing/olsr/olsr-routing-protocol.h	Sat May 30 17:36:50 2009 +0100
+++ b/src/routing/olsr/olsr-routing-protocol.h	Sat May 30 17:37:38 2009 +0100
@@ -121,13 +121,10 @@
                       RoutingTableEntry &outEntry) const;
 
   // From Ipv4RoutingProtocol
-  virtual bool RequestRoute (uint32_t ifIndex,
-                             const Ipv4Header &ipHeader,
-                             Ptr<Packet> packet,
-                             RouteReplyCallback routeReply);
-  virtual bool RequestInterface (Ipv4Address destination, 
-                               uint32_t& ifIndex);
-
+  virtual Ptr<Ipv4Route> RouteOutput (const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+   virtual bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb);  
 
   void DoDispose ();
 
--- a/src/wscript	Sat May 30 17:36:50 2009 +0100
+++ b/src/wscript	Sat May 30 17:37:38 2009 +0100
@@ -54,6 +54,7 @@
     conf.sub_config('core')
     conf.sub_config('simulator')
     conf.sub_config('devices/emu')
+    conf.sub_config('devices/wifi')
     conf.sub_config('devices/tap-bridge')
     conf.sub_config('contrib')
     conf.sub_config('internet-stack')
--- a/utils/python-unit-tests.py	Sat May 30 17:36:50 2009 +0100
+++ b/utils/python-unit-tests.py	Sat May 30 17:37:38 2009 +0100
@@ -62,7 +62,8 @@
 
     def testSocket(self):
         node = ns3.Node()
-        ns3.AddInternetStack(node)
+        internet = ns3.InternetStackHelper()
+        internet.Install(node)
         self._received_packet = None
 
         def rx_callback(socket):