merge with tip
authorTom Henderson <tomh@tomh.org>
Fri, 17 Apr 2009 12:33:17 -0700
changeset 4379 44c7757fb216
parent 4378 3ad10f8db106 (current diff)
parent 4366 1c3138bce75e (diff)
child 4380 bbbc2e622f50
merge with tip
src/devices/tap-bridge/tap-bridge.cc
src/internet-stack/ipv4-l3-protocol.cc
src/routing/olsr/olsr-agent-impl.cc
src/routing/olsr/olsr-agent-impl.h
src/routing/olsr/olsr-agent.cc
src/routing/olsr/olsr-agent.h
src/routing/olsr/olsr-routing-protocol.cc
src/routing/olsr/olsr-routing-table.cc
src/routing/olsr/olsr-routing-table.h
src/routing/olsr/repositories.h
--- a/bindings/python/ns3_module_bridge.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_bridge.py	Fri Apr 17 12:33:17 2009 -0700
@@ -103,16 +103,6 @@
                    'ns3::Ptr< ns3::NetDevice >', 
                    [param('uint32_t', 'n')], 
                    is_const=True)
-    ## bridge-net-device.h: void ns3::BridgeNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## bridge-net-device.h: std::string ns3::BridgeNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## bridge-net-device.h: void ns3::BridgeNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_core.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_core.py	Fri Apr 17 12:33:17 2009 -0700
@@ -115,8 +115,12 @@
     module.add_class('EnumChecker', parent=root_module['ns3::AttributeChecker'])
     ## enum.h: ns3::EnumValue [class]
     module.add_class('EnumValue', parent=root_module['ns3::AttributeValue'])
+    ## random-variable.h: ns3::ErlangVariable [class]
+    module.add_class('ErlangVariable', parent=root_module['ns3::RandomVariable'])
     ## random-variable.h: ns3::ExponentialVariable [class]
     module.add_class('ExponentialVariable', parent=root_module['ns3::RandomVariable'])
+    ## random-variable.h: ns3::GammaVariable [class]
+    module.add_class('GammaVariable', parent=root_module['ns3::RandomVariable'])
     ## random-variable.h: ns3::IntEmpiricalVariable [class]
     module.add_class('IntEmpiricalVariable', parent=root_module['ns3::EmpiricalVariable'])
     ## integer.h: ns3::IntegerValue [class]
@@ -261,7 +265,9 @@
     register_Ns3EmptyAttributeValue_methods(root_module, root_module['ns3::EmptyAttributeValue'])
     register_Ns3EnumChecker_methods(root_module, root_module['ns3::EnumChecker'])
     register_Ns3EnumValue_methods(root_module, root_module['ns3::EnumValue'])
+    register_Ns3ErlangVariable_methods(root_module, root_module['ns3::ErlangVariable'])
     register_Ns3ExponentialVariable_methods(root_module, root_module['ns3::ExponentialVariable'])
+    register_Ns3GammaVariable_methods(root_module, root_module['ns3::GammaVariable'])
     register_Ns3IntEmpiricalVariable_methods(root_module, root_module['ns3::IntEmpiricalVariable'])
     register_Ns3IntegerValue_methods(root_module, root_module['ns3::IntegerValue'])
     register_Ns3LogNormalVariable_methods(root_module, root_module['ns3::LogNormalVariable'])
@@ -1497,6 +1503,25 @@
                    is_virtual=True)
     return
 
+def register_Ns3ErlangVariable_methods(root_module, cls):
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable(ns3::ErlangVariable const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::ErlangVariable const &', 'arg0')])
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable() [constructor]
+    cls.add_constructor([])
+    ## random-variable.h: ns3::ErlangVariable::ErlangVariable(unsigned int k, double lambda) [constructor]
+    cls.add_constructor([param('unsigned int', 'k'), param('double', 'lambda')])
+    ## random-variable.h: double ns3::ErlangVariable::GetValue() const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [], 
+                   is_const=True)
+    ## random-variable.h: double ns3::ErlangVariable::GetValue(unsigned int k, double lambda) const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [param('unsigned int', 'k'), param('double', 'lambda')], 
+                   is_const=True)
+    return
+
 def register_Ns3ExponentialVariable_methods(root_module, cls):
     ## random-variable.h: ns3::ExponentialVariable::ExponentialVariable(ns3::ExponentialVariable const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::ExponentialVariable const &', 'arg0')])
@@ -1508,6 +1533,25 @@
     cls.add_constructor([param('double', 'm'), param('double', 'b')])
     return
 
+def register_Ns3GammaVariable_methods(root_module, cls):
+    ## random-variable.h: ns3::GammaVariable::GammaVariable(ns3::GammaVariable const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::GammaVariable const &', 'arg0')])
+    ## random-variable.h: ns3::GammaVariable::GammaVariable() [constructor]
+    cls.add_constructor([])
+    ## random-variable.h: ns3::GammaVariable::GammaVariable(double alpha, double beta) [constructor]
+    cls.add_constructor([param('double', 'alpha'), param('double', 'beta')])
+    ## random-variable.h: double ns3::GammaVariable::GetValue() const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [], 
+                   is_const=True)
+    ## random-variable.h: double ns3::GammaVariable::GetValue(double alpha, double beta) const [member function]
+    cls.add_method('GetValue', 
+                   'double', 
+                   [param('double', 'alpha'), param('double', 'beta')], 
+                   is_const=True)
+    return
+
 def register_Ns3IntEmpiricalVariable_methods(root_module, cls):
     ## random-variable.h: ns3::IntEmpiricalVariable::IntEmpiricalVariable(ns3::IntEmpiricalVariable const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::IntEmpiricalVariable const &', 'arg0')])
@@ -1984,7 +2028,7 @@
     cls.add_method('ConnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Connect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Connect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -1992,7 +2036,7 @@
     cls.add_method('DisconnectWithoutContext', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb')])
-    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::basic_string<char,std::char_traits<char>,std::allocator<char> > path) [member function]
+    ## traced-value.h: void ns3::TracedValue<unsigned int>::Disconnect(ns3::CallbackBase const & cb, std::string path) [member function]
     cls.add_method('Disconnect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -2140,7 +2184,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['long'])
+                        template_parameters=['long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
@@ -2160,7 +2204,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['unsigned long'])
+                        template_parameters=['unsigned long long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
--- a/bindings/python/ns3_module_csma.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_csma.py	Fri Apr 17 12:33:17 2009 -0700
@@ -273,16 +273,6 @@
     cls.add_method('GetEncapsulationMode', 
                    'ns3::CsmaNetDevice::EncapsulationMode', 
                    [])
-    ## csma-net-device.h: void ns3::CsmaNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## csma-net-device.h: std::string ns3::CsmaNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## csma-net-device.h: void ns3::CsmaNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_emu.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_emu.py	Fri Apr 17 12:33:17 2009 -0700
@@ -80,16 +80,6 @@
     cls.add_method('SetAddress', 
                    'void', 
                    [param('ns3::Mac48Address', 'addr')])
-    ## emu-net-device.h: void ns3::EmuNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## emu-net-device.h: std::string ns3::EmuNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## emu-net-device.h: void ns3::EmuNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_node.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_node.py	Fri Apr 17 12:33:17 2009 -0700
@@ -133,6 +133,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'])
+    module.add_container('ns3::olsr::MprSet', 'ns3::Ipv4Address', container_type='set')
+    module.add_container('std::vector< ns3::Ipv4Address >', 'ns3::Ipv4Address', container_type='vector')
     
     ## Register a nested module for the namespace Config
     
@@ -173,7 +175,6 @@
 def register_types_ns3_olsr(module):
     root_module = module.get_root()
     
-    module.add_container('std::vector< ns3::Ipv4Address >', 'ns3::Ipv4Address', container_type='vector')
 
 def register_methods(root_module):
     register_Ns3Address_methods(root_module, root_module['ns3::Address'])
@@ -2310,16 +2311,6 @@
                    is_static=True)
     ## channel.h: ns3::Channel::Channel() [constructor]
     cls.add_constructor([])
-    ## channel.h: ns3::Channel::Channel(std::string name) [constructor]
-    cls.add_constructor([param('std::string', 'name')])
-    ## channel.h: void ns3::Channel::SetName(std::string arg0) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string', 'arg0')])
-    ## channel.h: std::string ns3::Channel::GetName() [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [])
     ## channel.h: uint32_t ns3::Channel::GetNDevices() const [member function]
     cls.add_method('GetNDevices', 
                    'uint32_t', 
@@ -2749,16 +2740,6 @@
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## net-device.h: void ns3::NetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## net-device.h: std::string ns3::NetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
     ## net-device.h: void ns3::NetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
@@ -3015,16 +2996,6 @@
     cls.add_method('SetAddress', 
                    'void', 
                    [param('ns3::Mac48Address', 'address')])
-    ## simple-net-device.h: void ns3::SimpleNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## simple-net-device.h: std::string ns3::SimpleNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## simple-net-device.h: void ns3::SimpleNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_olsr.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_olsr.py	Fri Apr 17 12:33:17 2009 -0700
@@ -3,6 +3,14 @@
 def register_types(module):
     root_module = module.get_root()
     
+    ## olsr-state.h: ns3::OlsrState [class]
+    module.add_class('OlsrState')
+    module.add_container('std::vector< ns3::olsr::MprSelectorTuple >', 'ns3::olsr::MprSelectorTuple', container_type='vector')
+    module.add_container('std::vector< ns3::olsr::NeighborTuple >', 'ns3::olsr::NeighborTuple', container_type='vector')
+    module.add_container('std::vector< ns3::olsr::TwoHopNeighborTuple >', 'ns3::olsr::TwoHopNeighborTuple', container_type='vector')
+    module.add_container('std::vector< ns3::olsr::LinkTuple >', 'ns3::olsr::LinkTuple', container_type='vector')
+    module.add_container('std::vector< ns3::olsr::TopologyTuple >', 'ns3::olsr::TopologyTuple', container_type='vector')
+    module.add_container('std::vector< ns3::olsr::IfaceAssocTuple >', 'ns3::olsr::IfaceAssocTuple', container_type='vector')
     
     ## Register a nested module for the namespace Config
     
@@ -43,8 +51,12 @@
 def register_types_ns3_olsr(module):
     root_module = module.get_root()
     
-    ## olsr-agent.h: ns3::olsr::Agent [class]
-    module.add_class('Agent', parent=root_module['ns3::Object'])
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple [struct]
+    module.add_class('DuplicateTuple')
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple [struct]
+    module.add_class('IfaceAssocTuple')
+    ## olsr-repositories.h: ns3::olsr::LinkTuple [struct]
+    module.add_class('LinkTuple')
     ## olsr-header.h: ns3::olsr::MessageHeader [class]
     module.add_class('MessageHeader', parent=root_module['ns3::Header'])
     ## olsr-header.h: ns3::olsr::MessageHeader::MessageType [enumeration]
@@ -61,18 +73,30 @@
     module.add_class('Mid', outer_class=root_module['ns3::olsr::MessageHeader'])
     ## olsr-header.h: ns3::olsr::MessageHeader::Tc [struct]
     module.add_class('Tc', outer_class=root_module['ns3::olsr::MessageHeader'])
+    ## olsr-repositories.h: ns3::olsr::MprSelectorTuple [struct]
+    module.add_class('MprSelectorTuple')
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple [struct]
+    module.add_class('NeighborTuple')
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::Status [enumeration]
+    module.add_enum('Status', ['STATUS_NOT_SYM', 'STATUS_SYM'], outer_class=root_module['ns3::olsr::NeighborTuple'])
     ## olsr-header.h: ns3::olsr::PacketHeader [class]
     module.add_class('PacketHeader', parent=root_module['ns3::Header'])
-    ## olsr-routing-table.h: ns3::olsr::RoutingTable [class]
-    module.add_class('RoutingTable', parent=root_module['ns3::Ipv4RoutingProtocol'])
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry [struct]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingProtocol [class]
+    module.add_class('RoutingProtocol', parent=root_module['ns3::Ipv4RoutingProtocol'])
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry [struct]
     module.add_class('RoutingTableEntry')
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple [struct]
+    module.add_class('TopologyTuple')
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple [struct]
+    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')
-    module.add_container('std::vector< ns3::olsr::RoutingTableEntry >', 'ns3::olsr::RoutingTableEntry', container_type='vector')
 
 def register_methods(root_module):
-    register_Ns3OlsrAgent_methods(root_module, root_module['ns3::olsr::Agent'])
+    register_Ns3OlsrState_methods(root_module, root_module['ns3::OlsrState'])
+    register_Ns3OlsrDuplicateTuple_methods(root_module, root_module['ns3::olsr::DuplicateTuple'])
+    register_Ns3OlsrIfaceAssocTuple_methods(root_module, root_module['ns3::olsr::IfaceAssocTuple'])
+    register_Ns3OlsrLinkTuple_methods(root_module, root_module['ns3::olsr::LinkTuple'])
     register_Ns3OlsrMessageHeader_methods(root_module, root_module['ns3::olsr::MessageHeader'])
     register_Ns3OlsrMessageHeaderHello_methods(root_module, root_module['ns3::olsr::MessageHeader::Hello'])
     register_Ns3OlsrMessageHeaderHelloLinkMessage_methods(root_module, root_module['ns3::olsr::MessageHeader::Hello::LinkMessage'])
@@ -80,41 +104,258 @@
     register_Ns3OlsrMessageHeaderHnaAssociation_methods(root_module, root_module['ns3::olsr::MessageHeader::Hna::Association'])
     register_Ns3OlsrMessageHeaderMid_methods(root_module, root_module['ns3::olsr::MessageHeader::Mid'])
     register_Ns3OlsrMessageHeaderTc_methods(root_module, root_module['ns3::olsr::MessageHeader::Tc'])
+    register_Ns3OlsrMprSelectorTuple_methods(root_module, root_module['ns3::olsr::MprSelectorTuple'])
+    register_Ns3OlsrNeighborTuple_methods(root_module, root_module['ns3::olsr::NeighborTuple'])
     register_Ns3OlsrPacketHeader_methods(root_module, root_module['ns3::olsr::PacketHeader'])
-    register_Ns3OlsrRoutingTable_methods(root_module, root_module['ns3::olsr::RoutingTable'])
+    register_Ns3OlsrRoutingProtocol_methods(root_module, root_module['ns3::olsr::RoutingProtocol'])
     register_Ns3OlsrRoutingTableEntry_methods(root_module, root_module['ns3::olsr::RoutingTableEntry'])
+    register_Ns3OlsrTopologyTuple_methods(root_module, root_module['ns3::olsr::TopologyTuple'])
+    register_Ns3OlsrTwoHopNeighborTuple_methods(root_module, root_module['ns3::olsr::TwoHopNeighborTuple'])
     return
 
-def register_Ns3OlsrAgent_methods(root_module, cls):
-    ## olsr-agent.h: ns3::olsr::Agent::Agent(ns3::olsr::Agent const & arg0) [copy constructor]
-    cls.add_constructor([param('ns3::olsr::Agent const &', 'arg0')])
-    ## olsr-agent.h: ns3::olsr::Agent::Agent() [constructor]
+def register_Ns3OlsrState_methods(root_module, cls):
+    ## olsr-state.h: ns3::OlsrState::OlsrState(ns3::OlsrState const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::OlsrState const &', 'arg0')])
+    ## olsr-state.h: ns3::OlsrState::OlsrState() [constructor]
     cls.add_constructor([])
-    ## olsr-agent.h: static ns3::TypeId ns3::olsr::Agent::GetTypeId() [member function]
-    cls.add_method('GetTypeId', 
-                   'ns3::TypeId', 
+    ## olsr-state.h: ns3::olsr::MprSelectorSet const & ns3::OlsrState::GetMprSelectors() const [member function]
+    cls.add_method('GetMprSelectors', 
+                   'ns3::olsr::MprSelectorSet const &', 
+                   [], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::MprSelectorTuple * ns3::OlsrState::FindMprSelectorTuple(ns3::Ipv4Address const & mainAddr) [member function]
+    cls.add_method('FindMprSelectorTuple', 
+                   'ns3::olsr::MprSelectorTuple *', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr')])
+    ## olsr-state.h: void ns3::OlsrState::EraseMprSelectorTuple(ns3::olsr::MprSelectorTuple const & tuple) [member function]
+    cls.add_method('EraseMprSelectorTuple', 
+                   'void', 
+                   [param('ns3::olsr::MprSelectorTuple const &', 'tuple')])
+    ## olsr-state.h: void ns3::OlsrState::EraseMprSelectorTuples(ns3::Ipv4Address const & mainAddr) [member function]
+    cls.add_method('EraseMprSelectorTuples', 
+                   'void', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr')])
+    ## olsr-state.h: void ns3::OlsrState::InsertMprSelectorTuple(ns3::olsr::MprSelectorTuple const & tuple) [member function]
+    cls.add_method('InsertMprSelectorTuple', 
+                   'void', 
+                   [param('ns3::olsr::MprSelectorTuple const &', 'tuple')])
+    ## olsr-state.h: std::string ns3::OlsrState::PrintMprSelectorSet() const [member function]
+    cls.add_method('PrintMprSelectorSet', 
+                   'std::string', 
+                   [], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::NeighborSet const & ns3::OlsrState::GetNeighbors() const [member function]
+    cls.add_method('GetNeighbors', 
+                   'ns3::olsr::NeighborSet const &', 
                    [], 
-                   is_static=True)
-    ## olsr-agent.h: void ns3::olsr::Agent::SetNode(ns3::Ptr<ns3::Node> node) [member function]
-    cls.add_method('SetNode', 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::NeighborSet & ns3::OlsrState::GetNeighbors() [member function]
+    cls.add_method('GetNeighbors', 
+                   'ns3::olsr::NeighborSet &', 
+                   [])
+    ## olsr-state.h: ns3::olsr::NeighborTuple * ns3::OlsrState::FindNeighborTuple(ns3::Ipv4Address const & mainAddr) [member function]
+    cls.add_method('FindNeighborTuple', 
+                   'ns3::olsr::NeighborTuple *', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr')])
+    ## olsr-state.h: ns3::olsr::NeighborTuple const * ns3::OlsrState::FindSymNeighborTuple(ns3::Ipv4Address const & mainAddr) const [member function]
+    cls.add_method('FindSymNeighborTuple', 
+                   'ns3::olsr::NeighborTuple const *', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr')], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::NeighborTuple * ns3::OlsrState::FindNeighborTuple(ns3::Ipv4Address const & mainAddr, uint8_t willingness) [member function]
+    cls.add_method('FindNeighborTuple', 
+                   'ns3::olsr::NeighborTuple *', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr'), param('uint8_t', 'willingness')])
+    ## olsr-state.h: void ns3::OlsrState::EraseNeighborTuple(ns3::olsr::NeighborTuple const & neighborTuple) [member function]
+    cls.add_method('EraseNeighborTuple', 
+                   'void', 
+                   [param('ns3::olsr::NeighborTuple const &', 'neighborTuple')])
+    ## olsr-state.h: void ns3::OlsrState::EraseNeighborTuple(ns3::Ipv4Address const & mainAddr) [member function]
+    cls.add_method('EraseNeighborTuple', 
+                   'void', 
+                   [param('ns3::Ipv4Address const &', 'mainAddr')])
+    ## olsr-state.h: void ns3::OlsrState::InsertNeighborTuple(ns3::olsr::NeighborTuple const & tuple) [member function]
+    cls.add_method('InsertNeighborTuple', 
+                   'void', 
+                   [param('ns3::olsr::NeighborTuple const &', 'tuple')])
+    ## olsr-state.h: ns3::olsr::TwoHopNeighborSet const & ns3::OlsrState::GetTwoHopNeighbors() const [member function]
+    cls.add_method('GetTwoHopNeighbors', 
+                   'ns3::olsr::TwoHopNeighborSet const &', 
+                   [], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::TwoHopNeighborSet & ns3::OlsrState::GetTwoHopNeighbors() [member function]
+    cls.add_method('GetTwoHopNeighbors', 
+                   'ns3::olsr::TwoHopNeighborSet &', 
+                   [])
+    ## olsr-state.h: ns3::olsr::TwoHopNeighborTuple * ns3::OlsrState::FindTwoHopNeighborTuple(ns3::Ipv4Address const & neighbor, ns3::Ipv4Address const & twoHopNeighbor) [member function]
+    cls.add_method('FindTwoHopNeighborTuple', 
+                   'ns3::olsr::TwoHopNeighborTuple *', 
+                   [param('ns3::Ipv4Address const &', 'neighbor'), param('ns3::Ipv4Address const &', 'twoHopNeighbor')])
+    ## olsr-state.h: void ns3::OlsrState::EraseTwoHopNeighborTuple(ns3::olsr::TwoHopNeighborTuple const & tuple) [member function]
+    cls.add_method('EraseTwoHopNeighborTuple', 
+                   'void', 
+                   [param('ns3::olsr::TwoHopNeighborTuple const &', 'tuple')])
+    ## olsr-state.h: void ns3::OlsrState::EraseTwoHopNeighborTuples(ns3::Ipv4Address const & neighbor) [member function]
+    cls.add_method('EraseTwoHopNeighborTuples', 
+                   'void', 
+                   [param('ns3::Ipv4Address const &', 'neighbor')])
+    ## olsr-state.h: void ns3::OlsrState::EraseTwoHopNeighborTuples(ns3::Ipv4Address const & neighbor, ns3::Ipv4Address const & twoHopNeighbor) [member function]
+    cls.add_method('EraseTwoHopNeighborTuples', 
+                   'void', 
+                   [param('ns3::Ipv4Address const &', 'neighbor'), param('ns3::Ipv4Address const &', 'twoHopNeighbor')])
+    ## olsr-state.h: void ns3::OlsrState::InsertTwoHopNeighborTuple(ns3::olsr::TwoHopNeighborTuple const & tuple) [member function]
+    cls.add_method('InsertTwoHopNeighborTuple', 
+                   'void', 
+                   [param('ns3::olsr::TwoHopNeighborTuple const &', 'tuple')])
+    ## olsr-state.h: bool ns3::OlsrState::FindMprAddress(ns3::Ipv4Address const & address) [member function]
+    cls.add_method('FindMprAddress', 
+                   'bool', 
+                   [param('ns3::Ipv4Address const &', 'address')])
+    ## olsr-state.h: void ns3::OlsrState::SetMprSet(ns3::olsr::MprSet mprSet) [member function]
+    cls.add_method('SetMprSet', 
+                   'void', 
+                   [param('ns3::olsr::MprSet', 'mprSet')])
+    ## olsr-state.h: ns3::olsr::DuplicateTuple * ns3::OlsrState::FindDuplicateTuple(ns3::Ipv4Address const & address, uint16_t sequenceNumber) [member function]
+    cls.add_method('FindDuplicateTuple', 
+                   'ns3::olsr::DuplicateTuple *', 
+                   [param('ns3::Ipv4Address const &', 'address'), param('uint16_t', 'sequenceNumber')])
+    ## olsr-state.h: void ns3::OlsrState::EraseDuplicateTuple(ns3::olsr::DuplicateTuple const & tuple) [member function]
+    cls.add_method('EraseDuplicateTuple', 
+                   'void', 
+                   [param('ns3::olsr::DuplicateTuple const &', 'tuple')])
+    ## olsr-state.h: void ns3::OlsrState::InsertDuplicateTuple(ns3::olsr::DuplicateTuple const & tuple) [member function]
+    cls.add_method('InsertDuplicateTuple', 
                    'void', 
-                   [param('ns3::Ptr< ns3::Node >', 'node')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## olsr-agent.h: void ns3::olsr::Agent::SetMainInterface(uint32_t interface) [member function]
-    cls.add_method('SetMainInterface', 
+                   [param('ns3::olsr::DuplicateTuple const &', 'tuple')])
+    ## olsr-state.h: ns3::olsr::LinkSet const & ns3::OlsrState::GetLinks() const [member function]
+    cls.add_method('GetLinks', 
+                   'ns3::olsr::LinkSet const &', 
+                   [], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::LinkTuple * ns3::OlsrState::FindLinkTuple(ns3::Ipv4Address const & ifaceAddr) [member function]
+    cls.add_method('FindLinkTuple', 
+                   'ns3::olsr::LinkTuple *', 
+                   [param('ns3::Ipv4Address const &', 'ifaceAddr')])
+    ## olsr-state.h: ns3::olsr::LinkTuple * ns3::OlsrState::FindSymLinkTuple(ns3::Ipv4Address const & ifaceAddr, ns3::Time time) [member function]
+    cls.add_method('FindSymLinkTuple', 
+                   'ns3::olsr::LinkTuple *', 
+                   [param('ns3::Ipv4Address const &', 'ifaceAddr'), param('ns3::Time', 'time')])
+    ## olsr-state.h: void ns3::OlsrState::EraseLinkTuple(ns3::olsr::LinkTuple const & tuple) [member function]
+    cls.add_method('EraseLinkTuple', 
+                   'void', 
+                   [param('ns3::olsr::LinkTuple const &', 'tuple')])
+    ## olsr-state.h: ns3::olsr::LinkTuple & ns3::OlsrState::InsertLinkTuple(ns3::olsr::LinkTuple const & tuple) [member function]
+    cls.add_method('InsertLinkTuple', 
+                   'ns3::olsr::LinkTuple &', 
+                   [param('ns3::olsr::LinkTuple const &', 'tuple')])
+    ## olsr-state.h: ns3::olsr::TopologySet const & ns3::OlsrState::GetTopologySet() const [member function]
+    cls.add_method('GetTopologySet', 
+                   'ns3::olsr::TopologySet const &', 
+                   [], 
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::TopologyTuple * ns3::OlsrState::FindTopologyTuple(ns3::Ipv4Address const & destAddr, ns3::Ipv4Address const & lastAddr) [member function]
+    cls.add_method('FindTopologyTuple', 
+                   'ns3::olsr::TopologyTuple *', 
+                   [param('ns3::Ipv4Address const &', 'destAddr'), param('ns3::Ipv4Address const &', 'lastAddr')])
+    ## olsr-state.h: ns3::olsr::TopologyTuple * ns3::OlsrState::FindNewerTopologyTuple(ns3::Ipv4Address const & lastAddr, uint16_t ansn) [member function]
+    cls.add_method('FindNewerTopologyTuple', 
+                   'ns3::olsr::TopologyTuple *', 
+                   [param('ns3::Ipv4Address const &', 'lastAddr'), param('uint16_t', 'ansn')])
+    ## olsr-state.h: void ns3::OlsrState::EraseTopologyTuple(ns3::olsr::TopologyTuple const & tuple) [member function]
+    cls.add_method('EraseTopologyTuple', 
+                   'void', 
+                   [param('ns3::olsr::TopologyTuple const &', 'tuple')])
+    ## olsr-state.h: void ns3::OlsrState::EraseOlderTopologyTuples(ns3::Ipv4Address const & lastAddr, uint16_t ansn) [member function]
+    cls.add_method('EraseOlderTopologyTuples', 
+                   'void', 
+                   [param('ns3::Ipv4Address const &', 'lastAddr'), param('uint16_t', 'ansn')])
+    ## olsr-state.h: void ns3::OlsrState::InsertTopologyTuple(ns3::olsr::TopologyTuple const & tuple) [member function]
+    cls.add_method('InsertTopologyTuple', 
                    'void', 
-                   [param('uint32_t', 'interface')], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## olsr-agent.h: void ns3::olsr::Agent::Start() [member function]
-    cls.add_method('Start', 
-                   'void', 
+                   [param('ns3::olsr::TopologyTuple const &', 'tuple')])
+    ## olsr-state.h: ns3::olsr::IfaceAssocSet const & ns3::OlsrState::GetIfaceAssocSet() const [member function]
+    cls.add_method('GetIfaceAssocSet', 
+                   'ns3::olsr::IfaceAssocSet const &', 
                    [], 
-                   is_pure_virtual=True, is_virtual=True)
-    ## olsr-agent.h: ns3::Ptr<const ns3::olsr::RoutingTable> ns3::olsr::Agent::GetRoutingTable() const [member function]
-    cls.add_method('GetRoutingTable', 
-                   'ns3::Ptr< ns3::olsr::RoutingTable const >', 
-                   [], 
-                   is_pure_virtual=True, is_const=True, is_virtual=True)
+                   is_const=True)
+    ## olsr-state.h: ns3::olsr::IfaceAssocSet & ns3::OlsrState::GetIfaceAssocSetMutable() [member function]
+    cls.add_method('GetIfaceAssocSetMutable', 
+                   'ns3::olsr::IfaceAssocSet &', 
+                   [])
+    ## olsr-state.h: ns3::olsr::IfaceAssocTuple * ns3::OlsrState::FindIfaceAssocTuple(ns3::Ipv4Address const & ifaceAddr) [member function]
+    cls.add_method('FindIfaceAssocTuple', 
+                   'ns3::olsr::IfaceAssocTuple *', 
+                   [param('ns3::Ipv4Address const &', 'ifaceAddr')])
+    ## olsr-state.h: ns3::olsr::IfaceAssocTuple const * ns3::OlsrState::FindIfaceAssocTuple(ns3::Ipv4Address const & ifaceAddr) const [member function]
+    cls.add_method('FindIfaceAssocTuple', 
+                   'ns3::olsr::IfaceAssocTuple const *', 
+                   [param('ns3::Ipv4Address const &', 'ifaceAddr')], 
+                   is_const=True)
+    ## olsr-state.h: void ns3::OlsrState::EraseIfaceAssocTuple(ns3::olsr::IfaceAssocTuple const & tuple) [member function]
+    cls.add_method('EraseIfaceAssocTuple', 
+                   'void', 
+                   [param('ns3::olsr::IfaceAssocTuple const &', 'tuple')])
+    ## olsr-state.h: void ns3::OlsrState::InsertIfaceAssocTuple(ns3::olsr::IfaceAssocTuple const & tuple) [member function]
+    cls.add_method('InsertIfaceAssocTuple', 
+                   'void', 
+                   [param('ns3::olsr::IfaceAssocTuple const &', 'tuple')])
+    ## olsr-state.h: std::vector<ns3::Ipv4Address, std::allocator<ns3::Ipv4Address> > ns3::OlsrState::FindNeighborInterfaces(ns3::Ipv4Address const & neighborMainAddr) const [member function]
+    cls.add_method('FindNeighborInterfaces', 
+                   'std::vector< ns3::Ipv4Address >', 
+                   [param('ns3::Ipv4Address const &', 'neighborMainAddr')], 
+                   is_const=True)
+    return
+
+def register_Ns3OlsrDuplicateTuple_methods(root_module, cls):
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::DuplicateTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::DuplicateTuple(ns3::olsr::DuplicateTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::DuplicateTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::address [variable]
+    cls.add_instance_attribute('address', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::expirationTime [variable]
+    cls.add_instance_attribute('expirationTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::ifaceList [variable]
+    cls.add_instance_attribute('ifaceList', 'std::vector< ns3::Ipv4Address >', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::retransmitted [variable]
+    cls.add_instance_attribute('retransmitted', 'bool', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::DuplicateTuple::sequenceNumber [variable]
+    cls.add_instance_attribute('sequenceNumber', 'uint16_t', is_const=False)
+    return
+
+def register_Ns3OlsrIfaceAssocTuple_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple::IfaceAssocTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple::IfaceAssocTuple(ns3::olsr::IfaceAssocTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::IfaceAssocTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple::ifaceAddr [variable]
+    cls.add_instance_attribute('ifaceAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple::mainAddr [variable]
+    cls.add_instance_attribute('mainAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::IfaceAssocTuple::time [variable]
+    cls.add_instance_attribute('time', 'ns3::Time', is_const=False)
+    return
+
+def register_Ns3OlsrLinkTuple_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::LinkTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::LinkTuple(ns3::olsr::LinkTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::LinkTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::asymTime [variable]
+    cls.add_instance_attribute('asymTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::localIfaceAddr [variable]
+    cls.add_instance_attribute('localIfaceAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::neighborIfaceAddr [variable]
+    cls.add_instance_attribute('neighborIfaceAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::symTime [variable]
+    cls.add_instance_attribute('symTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::LinkTuple::time [variable]
+    cls.add_instance_attribute('time', 'ns3::Time', is_const=False)
     return
 
 def register_Ns3OlsrMessageHeader_methods(root_module, cls):
@@ -394,6 +635,33 @@
     cls.add_instance_attribute('neighborAddresses', 'std::vector< ns3::Ipv4Address >', is_const=False)
     return
 
+def register_Ns3OlsrMprSelectorTuple_methods(root_module, cls):
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::MprSelectorTuple::MprSelectorTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::MprSelectorTuple::MprSelectorTuple(ns3::olsr::MprSelectorTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::MprSelectorTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::MprSelectorTuple::expirationTime [variable]
+    cls.add_instance_attribute('expirationTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::MprSelectorTuple::mainAddr [variable]
+    cls.add_instance_attribute('mainAddr', 'ns3::Ipv4Address', is_const=False)
+    return
+
+def register_Ns3OlsrNeighborTuple_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::NeighborTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::NeighborTuple(ns3::olsr::NeighborTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::NeighborTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::neighborMainAddr [variable]
+    cls.add_instance_attribute('neighborMainAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::status [variable]
+    cls.add_instance_attribute('status', 'ns3::olsr::NeighborTuple::Status', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::NeighborTuple::willingness [variable]
+    cls.add_instance_attribute('willingness', 'uint8_t', is_const=False)
+    return
+
 def register_Ns3OlsrPacketHeader_methods(root_module, cls):
     cls.add_output_stream_operator()
     ## olsr-header.h: ns3::olsr::PacketHeader::PacketHeader(ns3::olsr::PacketHeader const & arg0) [copy constructor]
@@ -450,66 +718,39 @@
                    [param('uint16_t', 'seqnum')])
     return
 
-def register_Ns3OlsrRoutingTable_methods(root_module, cls):
-    ## olsr-routing-table.h: ns3::olsr::RoutingTable::RoutingTable(ns3::olsr::RoutingTable const & arg0) [copy constructor]
-    cls.add_constructor([param('ns3::olsr::RoutingTable const &', 'arg0')])
-    ## olsr-routing-table.h: ns3::olsr::RoutingTable::RoutingTable() [constructor]
+def register_Ns3OlsrRoutingProtocol_methods(root_module, cls):
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingProtocol::RoutingProtocol(ns3::olsr::RoutingProtocol const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::RoutingProtocol const &', 'arg0')])
+    ## olsr-routing-protocol.h: static ns3::TypeId ns3::olsr::RoutingProtocol::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingProtocol::RoutingProtocol() [constructor]
     cls.add_constructor([])
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::SetIpv4(ns3::Ptr<ns3::Ipv4> ipv4) [member function]
-    cls.add_method('SetIpv4', 
+    ## olsr-routing-protocol.h: void ns3::olsr::RoutingProtocol::SetNode(ns3::Ptr<ns3::Node> node) [member function]
+    cls.add_method('SetNode', 
                    'void', 
-                   [param('ns3::Ptr< ns3::Ipv4 >', 'ipv4')])
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::SetMainAddress(ns3::Ipv4Address mainAddress) [member function]
-    cls.add_method('SetMainAddress', 
-                   'void', 
-                   [param('ns3::Ipv4Address', 'mainAddress')])
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::Clear() [member function]
-    cls.add_method('Clear', 
+                   [param('ns3::Ptr< ns3::Node >', 'node')])
+    ## olsr-routing-protocol.h: void ns3::olsr::RoutingProtocol::Start() [member function]
+    cls.add_method('Start', 
                    'void', 
                    [])
-    ## olsr-routing-table.h: uint32_t ns3::olsr::RoutingTable::GetSize() const [member function]
-    cls.add_method('GetSize', 
-                   'uint32_t', 
-                   [], 
-                   is_const=True)
-    ## olsr-routing-table.h: std::vector<ns3::olsr::RoutingTableEntry,std::allocator<ns3::olsr::RoutingTableEntry> > ns3::olsr::RoutingTable::GetEntries() const [member function]
-    cls.add_method('GetEntries', 
-                   'std::vector< ns3::olsr::RoutingTableEntry >', 
-                   [], 
-                   is_const=True)
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::RemoveEntry(ns3::Ipv4Address const & dest) [member function]
-    cls.add_method('RemoveEntry', 
-                   'void', 
-                   [param('ns3::Ipv4Address const &', 'dest')])
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::AddEntry(ns3::Ipv4Address const & dest, ns3::Ipv4Address const & next, uint32_t interface, uint32_t distance) [member function]
-    cls.add_method('AddEntry', 
+    ## olsr-routing-protocol.h: void ns3::olsr::RoutingProtocol::SetMainInterface(uint32_t interface) [member function]
+    cls.add_method('SetMainInterface', 
                    'void', 
-                   [param('ns3::Ipv4Address const &', 'dest'), param('ns3::Ipv4Address const &', 'next'), param('uint32_t', 'interface'), param('uint32_t', 'distance')])
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::AddEntry(ns3::Ipv4Address const & dest, ns3::Ipv4Address const & next, ns3::Ipv4Address const & interfaceAddress, uint32_t distance) [member function]
-    cls.add_method('AddEntry', 
-                   'void', 
-                   [param('ns3::Ipv4Address const &', 'dest'), param('ns3::Ipv4Address const &', 'next'), param('ns3::Ipv4Address const &', 'interfaceAddress'), param('uint32_t', 'distance')])
-    ## olsr-routing-table.h: bool ns3::olsr::RoutingTable::Lookup(ns3::Ipv4Address const & dest, ns3::olsr::RoutingTableEntry & outEntry) const [member function]
-    cls.add_method('Lookup', 
-                   'bool', 
-                   [param('ns3::Ipv4Address const &', 'dest'), param('ns3::olsr::RoutingTableEntry &', 'outEntry')], 
-                   is_const=True)
-    ## olsr-routing-table.h: bool ns3::olsr::RoutingTable::FindSendEntry(ns3::olsr::RoutingTableEntry const & entry, ns3::olsr::RoutingTableEntry & outEntry) const [member function]
-    cls.add_method('FindSendEntry', 
-                   'bool', 
-                   [param('ns3::olsr::RoutingTableEntry const &', 'entry'), param('ns3::olsr::RoutingTableEntry &', 'outEntry')], 
-                   is_const=True)
-    ## olsr-routing-table.h: bool ns3::olsr::RoutingTable::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]
+                   [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')], 
-                   is_virtual=True)
-    ## olsr-routing-table.h: bool ns3::olsr::RoutingTable::RequestIfIndex(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function]
+                   visibility='private', is_virtual=True)
+    ## olsr-routing-protocol.h: bool ns3::olsr::RoutingProtocol::RequestIfIndex(ns3::Ipv4Address destination, uint32_t & ifIndex) [member function]
     cls.add_method('RequestIfIndex', 
                    'bool', 
                    [param('ns3::Ipv4Address', 'destination'), param('uint32_t &', 'ifIndex')], 
-                   is_virtual=True)
-    ## olsr-routing-table.h: void ns3::olsr::RoutingTable::DoDispose() [member function]
+                   visibility='private', is_virtual=True)
+    ## olsr-routing-protocol.h: void ns3::olsr::RoutingProtocol::DoDispose() [member function]
     cls.add_method('DoDispose', 
                    'void', 
                    [], 
@@ -517,18 +758,50 @@
     return
 
 def register_Ns3OlsrRoutingTableEntry_methods(root_module, cls):
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::destAddr [variable]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::destAddr [variable]
     cls.add_instance_attribute('destAddr', 'ns3::Ipv4Address', is_const=False)
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::nextAddr [variable]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::nextAddr [variable]
     cls.add_instance_attribute('nextAddr', 'ns3::Ipv4Address', is_const=False)
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::interface [variable]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::interface [variable]
     cls.add_instance_attribute('interface', 'uint32_t', is_const=False)
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::distance [variable]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::distance [variable]
     cls.add_instance_attribute('distance', 'uint32_t', is_const=False)
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::RoutingTableEntry(ns3::olsr::RoutingTableEntry const & arg0) [copy constructor]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::RoutingTableEntry(ns3::olsr::RoutingTableEntry const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::olsr::RoutingTableEntry const &', 'arg0')])
-    ## olsr-routing-table.h: ns3::olsr::RoutingTableEntry::RoutingTableEntry() [constructor]
+    ## olsr-routing-protocol.h: ns3::olsr::RoutingTableEntry::RoutingTableEntry() [constructor]
+    cls.add_constructor([])
+    return
+
+def register_Ns3OlsrTopologyTuple_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::TopologyTuple() [constructor]
     cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::TopologyTuple(ns3::olsr::TopologyTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::TopologyTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::destAddr [variable]
+    cls.add_instance_attribute('destAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::expirationTime [variable]
+    cls.add_instance_attribute('expirationTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::lastAddr [variable]
+    cls.add_instance_attribute('lastAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::TopologyTuple::sequenceNumber [variable]
+    cls.add_instance_attribute('sequenceNumber', 'uint16_t', is_const=False)
+    return
+
+def register_Ns3OlsrTwoHopNeighborTuple_methods(root_module, cls):
+    cls.add_output_stream_operator()
+    cls.add_binary_comparison_operator('==')
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple::TwoHopNeighborTuple() [constructor]
+    cls.add_constructor([])
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple::TwoHopNeighborTuple(ns3::olsr::TwoHopNeighborTuple const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::olsr::TwoHopNeighborTuple const &', 'arg0')])
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple::expirationTime [variable]
+    cls.add_instance_attribute('expirationTime', 'ns3::Time', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple::neighborMainAddr [variable]
+    cls.add_instance_attribute('neighborMainAddr', 'ns3::Ipv4Address', is_const=False)
+    ## olsr-repositories.h: ns3::olsr::TwoHopNeighborTuple::twoHopNeighborAddr [variable]
+    cls.add_instance_attribute('twoHopNeighborAddr', 'ns3::Ipv4Address', is_const=False)
     return
 
 def register_functions(root_module):
--- a/bindings/python/ns3_module_point_to_point.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_point_to_point.py	Fri Apr 17 12:33:17 2009 -0700
@@ -175,16 +175,6 @@
                    'uint16_t', 
                    [], 
                    is_const=True)
-    ## point-to-point-net-device.h: void ns3::PointToPointNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## point-to-point-net-device.h: std::string ns3::PointToPointNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## point-to-point-net-device.h: void ns3::PointToPointNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_tap_bridge.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_tap_bridge.py	Fri Apr 17 12:33:17 2009 -0700
@@ -86,16 +86,6 @@
     cls.add_method('GetMode', 
                    'ns3::TapBridge::Mode', 
                    [])
-    ## tap-bridge.h: void ns3::TapBridge::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## tap-bridge.h: std::string ns3::TapBridge::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## tap-bridge.h: void ns3::TapBridge::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/ns3_module_wifi.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/ns3_module_wifi.py	Fri Apr 17 12:33:17 2009 -0700
@@ -228,8 +228,8 @@
                    'ns3::Ptr< ns3::ErrorRateModel >', 
                    [], 
                    is_const=True)
-    ## interference-helper.h: double ns3::InterferenceHelper::GetNoiseFloorW() const [member function]
-    cls.add_method('GetNoiseFloorW', 
+    ## interference-helper.h: double ns3::InterferenceHelper::GetNoiseFigure() const [member function]
+    cls.add_method('GetNoiseFigure', 
                    'double', 
                    [], 
                    is_const=True)
@@ -237,10 +237,10 @@
     cls.add_method('SetErrorRateModel', 
                    'void', 
                    [param('ns3::Ptr< ns3::ErrorRateModel >', 'rate')])
-    ## interference-helper.h: void ns3::InterferenceHelper::SetNoiseFloorW(double noiseFloor) [member function]
-    cls.add_method('SetNoiseFloorW', 
+    ## interference-helper.h: void ns3::InterferenceHelper::SetNoiseFigure(double value) [member function]
+    cls.add_method('SetNoiseFigure', 
                    'void', 
-                   [param('double', 'noiseFloor')])
+                   [param('double', 'value')])
     return
 
 def register_Ns3InterferenceHelperSnrPer_methods(root_module, cls):
@@ -727,8 +727,8 @@
 def register_Ns3ArfWifiRemoteStation_methods(root_module, cls):
     ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::ArfWifiRemoteStation const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::ArfWifiRemoteStation const &', 'arg0')])
-    ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::Ptr<ns3::ArfWifiManager> stations, int minTimerTimeout, int minSuccessThreshold) [constructor]
-    cls.add_constructor([param('ns3::Ptr< ns3::ArfWifiManager >', 'stations'), param('int', 'minTimerTimeout'), param('int', 'minSuccessThreshold')])
+    ## arf-wifi-manager.h: ns3::ArfWifiRemoteStation::ArfWifiRemoteStation(ns3::Ptr<ns3::ArfWifiManager> manager) [constructor]
+    cls.add_constructor([param('ns3::Ptr< ns3::ArfWifiManager >', 'manager')])
     ## arf-wifi-manager.h: void ns3::ArfWifiRemoteStation::DoReportRxOk(double rxSnr, ns3::WifiMode txMode) [member function]
     cls.add_method('DoReportRxOk', 
                    'void', 
@@ -1667,6 +1667,11 @@
                    'bool', 
                    [], 
                    is_const=True)
+    ## wifi-remote-station-manager.h: ns3::WifiMode ns3::WifiRemoteStationManager::GetNonUnicastMode() const [member function]
+    cls.add_method('GetNonUnicastMode', 
+                   'ns3::WifiMode', 
+                   [], 
+                   is_const=True)
     ## wifi-remote-station-manager.h: ns3::WifiRemoteStation * ns3::WifiRemoteStationManager::Lookup(ns3::Mac48Address address) [member function]
     cls.add_method('Lookup', 
                    'ns3::WifiRemoteStation *', 
@@ -1707,10 +1712,10 @@
     cls.add_method('SetStandard', 
                    'void', 
                    [param('ns3::WifiPhyStandard', 'standard')])
-    ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetRxNoise(double ratio) [member function]
-    cls.add_method('SetRxNoise', 
+    ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetRxNoiseFigure(double noiseFigureDb) [member function]
+    cls.add_method('SetRxNoiseFigure', 
                    'void', 
-                   [param('double', 'ratio')])
+                   [param('double', 'noiseFigureDb')])
     ## yans-wifi-phy.h: void ns3::YansWifiPhy::SetTxPowerStart(double start) [member function]
     cls.add_method('SetTxPowerStart', 
                    'void', 
@@ -1751,8 +1756,8 @@
     cls.add_method('SetMobility', 
                    'void', 
                    [param('ns3::Ptr< ns3::Object >', 'mobility')])
-    ## yans-wifi-phy.h: double ns3::YansWifiPhy::GetRxNoise() const [member function]
-    cls.add_method('GetRxNoise', 
+    ## yans-wifi-phy.h: double ns3::YansWifiPhy::GetRxNoiseFigure() const [member function]
+    cls.add_method('GetRxNoiseFigure', 
                    'double', 
                    [], 
                    is_const=True)
@@ -1900,8 +1905,8 @@
 def register_Ns3AarfWifiRemoteStation_methods(root_module, cls):
     ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::AarfWifiRemoteStation const & arg0) [copy constructor]
     cls.add_constructor([param('ns3::AarfWifiRemoteStation const &', 'arg0')])
-    ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::Ptr<ns3::AarfWifiManager> stations, uint32_t minTimerThreshold, uint32_t minSuccessThreshold, double successK, uint32_t maxSuccessThreshold, double timerK) [constructor]
-    cls.add_constructor([param('ns3::Ptr< ns3::AarfWifiManager >', 'stations'), param('uint32_t', 'minTimerThreshold'), param('uint32_t', 'minSuccessThreshold'), param('double', 'successK'), param('uint32_t', 'maxSuccessThreshold'), param('double', 'timerK')])
+    ## aarf-wifi-manager.h: ns3::AarfWifiRemoteStation::AarfWifiRemoteStation(ns3::Ptr<ns3::AarfWifiManager> stations) [constructor]
+    cls.add_constructor([param('ns3::Ptr< ns3::AarfWifiManager >', 'stations')])
     ## aarf-wifi-manager.h: void ns3::AarfWifiRemoteStation::ReportRecoveryFailure() [member function]
     cls.add_method('ReportRecoveryFailure', 
                    'void', 
@@ -1912,6 +1917,11 @@
                    'void', 
                    [], 
                    visibility='private', is_virtual=True)
+    ## aarf-wifi-manager.h: ns3::Ptr<ns3::WifiRemoteStationManager> ns3::AarfWifiRemoteStation::GetManager() const [member function]
+    cls.add_method('GetManager', 
+                   'ns3::Ptr< ns3::WifiRemoteStationManager >', 
+                   [], 
+                   is_const=True, visibility='private', is_virtual=True)
     return
 
 def register_Ns3AdhocWifiMac_methods(root_module, cls):
@@ -2697,16 +2707,6 @@
                    'ns3::Ptr< ns3::WifiRemoteStationManager >', 
                    [], 
                    is_const=True)
-    ## wifi-net-device.h: void ns3::WifiNetDevice::SetName(std::string const name) [member function]
-    cls.add_method('SetName', 
-                   'void', 
-                   [param('std::string const', 'name')], 
-                   is_virtual=True)
-    ## wifi-net-device.h: std::string ns3::WifiNetDevice::GetName() const [member function]
-    cls.add_method('GetName', 
-                   'std::string', 
-                   [], 
-                   is_const=True, is_virtual=True)
     ## wifi-net-device.h: void ns3::WifiNetDevice::SetIfIndex(uint32_t const index) [member function]
     cls.add_method('SetIfIndex', 
                    'void', 
--- a/bindings/python/wscript	Sun Apr 12 22:41:33 2009 -0700
+++ b/bindings/python/wscript	Fri Apr 17 12:33:17 2009 -0700
@@ -273,7 +273,7 @@
 
     def apply(self):
         ## get all of the ns3 headers
-        ns3_dir_node = Build.bld.path.find_dir("ns3")
+        ns3_dir_node = self.bld.path.find_dir("ns3")
         all_headers_inputs = []
 
         for filename in self.to_list(self.source):
@@ -284,7 +284,7 @@
 
         ## if self.source was empty, include all ns3 headers in enabled modules
         if not all_headers_inputs:
-            for ns3headers in Build.bld.all_task_gen:
+            for ns3headers in self.bld.all_task_gen:
                 if type(ns3headers).__name__ == 'ns3header_taskgen': # XXX: find less hackish way to compare
                     ## skip headers not part of enabled modules
                     if self.env['NS3_ENABLED_MODULES']:
@@ -307,7 +307,7 @@
         pass
 
 
-def get_modules_and_headers():
+def get_modules_and_headers(bld):
     """
     Gets a dict of
        module_name => ([module_dep1, module_dep2, ...], [module_header1, module_header2, ...])
@@ -315,13 +315,13 @@
     """
 
     retval = {}
-    for module in Build.bld.all_task_gen:
+    for module in bld.all_task_gen:
         if not module.name.startswith('ns3-'):
             continue
         module_name = module.name[4:] # strip the ns3- prefix
         ## find the headers object for this module
         headers = []
-        for ns3headers in Build.bld.all_task_gen:
+        for ns3headers in bld.all_task_gen:
             if type(ns3headers).__name__ != 'ns3header_taskgen': # XXX: find less hackish way to compare
                 continue
             if ns3headers.module != module_name:
@@ -338,8 +338,9 @@
     """
     after = 'gen_everything_h_task'
     before = 'cc cxx'
-    def __init__(self, curdirnode, env):
-        super(python_scan_task, self).__init__()
+    def __init__(self, curdirnode, env, bld):
+        self.bld = bld
+        super(python_scan_task, self).__init__(generator=self)
         self.curdirnode = curdirnode
         self.env = env
 
@@ -356,7 +357,7 @@
             os.path.join(self.curdirnode.abspath(), 'ns3modulegen_generated.py'), # output file
             ]
         scan = subprocess.Popen(argv, stdin=subprocess.PIPE)
-        scan.stdin.write(repr(get_modules_and_headers()))
+        scan.stdin.write(repr(get_modules_and_headers(self.bld)))
         scan.stdin.close()
         retval = scan.wait()
         print "Scan finished with exit code", retval
@@ -365,7 +366,7 @@
         # signal stop (we generated files into the source dir and WAF
         # can't cope with it, so we have to force the user to restart
         # WAF)
-        Build.bld.generator.stop = 1
+        self.bld.generator.stop = 1
         return 0
 
 
@@ -384,7 +385,7 @@
     if Options.options.python_scan:
         if not env['ENABLE_PYTHON_SCANNING']:
             raise Utils.WafError("Cannot re-scan python bindings: (py)gccxml not available")
-        python_scan_task(bld.path, env)
+        python_scan_task(bld.path, env, bld)
         return
 
     ## Get a list of scanned modules; the set of scanned modules
@@ -412,7 +413,7 @@
             'ns3modulegen.log',
             ]
         argv = ['NS3_ENABLED_FEATURES=${FEATURES}', '${PYTHON}', '${SRC[0]}', '${TGT[0]}']
-        argv.extend(get_modules_and_headers().iterkeys())
+        argv.extend(get_modules_and_headers(bld).iterkeys())
         for module in scanned_modules:
             source.append("ns3_module_%s.py" % module)
             local = "ns3_module_%s__local.py" % module
@@ -434,12 +435,8 @@
         bindgen.dep_vars = ['FEATURES']
         bindgen.before = 'cxx'
         bindgen.after = 'gen_everything_h_task'
+        bindgen.name = "pybindgen-command"
 
-    ## we build python bindings if either we have the tools to
-    ## generate them or if the pregenerated source file is already
-    ## present in the source dir.
-    if env['ENABLE_PYTHON_BINDINGS'] \
-            or os.path.exists(os.path.join(bld.path.abspath(), 'ns3module.cc')):
         pymod = bld.new_task_gen('cxx', 'shlib', 'pyext')
         pymod.source = ['ns3module.cc', 'ns3module_helpers.cc']
         pymod.includes = '.'
--- a/examples/wifi-adhoc.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/examples/wifi-adhoc.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -251,6 +251,24 @@
   dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
   gnuplot.AddDataset (dataset);
 
+  NS_LOG_DEBUG ("aarf-cd");
+  experiment = Experiment ("aarf-cd");
+  wifi.SetRemoteStationManager ("ns3::AarfcdWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
+  NS_LOG_DEBUG ("cara");
+  experiment = Experiment ("cara");
+  wifi.SetRemoteStationManager ("ns3::CaraWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
+  NS_LOG_DEBUG ("rraa");
+  experiment = Experiment ("rraa");
+  wifi.SetRemoteStationManager ("ns3::RraaWifiManager");
+  dataset = experiment.Run (wifi, wifiPhy, wifiChannel);
+  gnuplot.AddDataset (dataset);
+
   NS_LOG_DEBUG ("ideal");
   experiment = Experiment ("ideal");
   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
--- a/examples/wifi-ap.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/examples/wifi-ap.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -32,14 +32,14 @@
 using namespace ns3;
 
 void
-DevTxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+DevTxTrace (std::string context, Ptr<const Packet> p)
 {
-  std::cout << " TX to=" << address << " p: " << *p << std::endl;
+  std::cout << " TX p: " << *p << std::endl;
 }
 void
-DevRxTrace (std::string context, Ptr<const Packet> p, Mac48Address address)
+DevRxTrace (std::string context, Ptr<const Packet> p)
 {
-  std::cout << " RX from=" << address << " p: " << *p << std::endl;
+  std::cout << " RX p: " << *p << std::endl;
 }
 void
 PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
@@ -168,8 +168,8 @@
 
   Simulator::Stop (Seconds (44.0));
 
-  Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
-  Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
+  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacTx", MakeCallback (&DevTxTrace));
+  Config::Connect ("/NodeList/*/DeviceList/*/Mac/MacRx", MakeCallback (&DevRxTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxOk", MakeCallback (&PhyRxOkTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxError", MakeCallback (&PhyRxErrorTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/Tx", MakeCallback (&PhyTxTrace));
--- a/regression.py	Sun Apr 12 22:41:33 2009 -0700
+++ b/regression.py	Fri Apr 17 12:33:17 2009 -0700
@@ -6,7 +6,6 @@
 import errno
 
 # WAF modules
-import Build
 import Options
 import Utils
 import Task
@@ -66,9 +65,11 @@
     after = 'cc cxx cc_link cxx_link'
     color = 'BLUE'
 
-    def __init__(self, env, test_name, test_scripts_dir, build_traces_dir, reference_traces):
-        super(regression_test_task, self).__init__()
+    def __init__(self, bld, env, test_name, test_scripts_dir, build_traces_dir, reference_traces):
+        self.bld = bld
+        self.generator = self
         self.env = env
+        super(regression_test_task, self).__init__(generator=self, env=env)
         self.test_name = test_name
         self.test_scripts_dir = test_scripts_dir
         self.build_traces_dir = build_traces_dir
@@ -77,6 +78,9 @@
     def __str__(self):
         return 'regression-test (%s)\n' % self.test_name
 
+    def runnable_status(self):
+        return Task.RUN_ME
+
     def run(self):
         """Run a single test"""
         sys.path.insert(0, self.test_scripts_dir)
@@ -119,7 +123,7 @@
         if Options.options.regression_generate:
             # clean the target dir
             try:
-                shutil.rmtree(trace_output_path)
+                shutil.rmtree(reference_traces_path)
             except OSError, ex:
                 if ex.errno not in [errno.ENOENT]:
                     raise
@@ -155,13 +159,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                wutils.run_argv(argv, cwd=trace_output_path)
+                wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                wutils.run_program(program,
+                wutils.run_program(program, self.env,
                                    command_template=wutils.get_command_template(self.env, arguments),
                                    cwd=trace_output_path)
             except Utils.WafError, ex:
@@ -187,13 +191,13 @@
             script = os.path.abspath(os.path.join('..', *os.path.split(program)))
             argv = [self.env['PYTHON'], script] + arguments
             try:
-                retval = wutils.run_argv(argv, cwd=trace_output_path)
+                retval = wutils.run_argv(argv, self.env, cwd=trace_output_path)
             except Utils.WafError, ex:
                 print >> sys.stderr, ex
                 return 1
         else:
             try:
-                retval = wutils.run_program(program,
+                retval = wutils.run_program(program, self.env,
                                             command_template=wutils.get_command_template(self.env, arguments),
                                             cwd=trace_output_path)
             except Utils.WafError, ex:
@@ -206,13 +210,17 @@
     after = 'regression_test_task'
     color = 'BLUE'
 
-    def __init__(self, test_tasks):
-        super(regression_test_collector_task, self).__init__()
+    def __init__(self, bld, test_tasks):
+        self.bld = bld
+        super(regression_test_collector_task, self).__init__(generator=self)
         self.test_tasks = test_tasks
 
     def __str__(self):
         return 'regression-test-collector\n'
 
+    def runnable_status(self):
+        return Task.RUN_ME
+
     def run(self):
         failed_tests = [test for test in self.test_tasks if test.result is not None and test.result != 0]
         skipped_tests = [test for test in self.test_tasks if test.result is None]
@@ -256,5 +264,7 @@
     build_traces_dir = bld.path.find_or_declare('regression/traces').abspath(bld.env)
     tasks = []
     for test in tests:
-        tasks.append(regression_test_task(bld.env, test, test_scripts_dir, build_traces_dir, reference_traces))
-    regression_test_collector_task(tasks)
+        task = regression_test_task(bld, bld.env, test, test_scripts_dir, build_traces_dir, reference_traces)
+        #bld.task_manager.add_task(task)
+        tasks.append(task)
+    regression_test_collector_task(bld, tasks)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-random-variable.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,377 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Timo Bingmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Timo Bingmann <timo.bingmann@student.kit.edu>
+ */
+#include "ns3/random-variable.h"
+#include "ns3/gnuplot.h"
+#include <map>
+#include <cmath>
+
+using namespace ns3;
+
+/// Round a double number to the given precision. e.g. dround(0.234, 0.1) = 0.2
+/// and dround(0.257, 0.1) = 0.3
+double dround(double number, double precision)
+{
+  number /= precision;
+  if (number >= 0)
+    number = std::floor(number + 0.5);
+  else
+    number = std::ceil(number - 0.5);
+  number *= precision;
+  return number;
+}
+
+static GnuplotDataset
+Histogramm (RandomVariable rndvar, unsigned int probes, double precision, const std::string& title, bool notcontinous = false)
+{
+  typedef std::map<double, unsigned int> histogramm_maptype;
+  histogramm_maptype histogramm;
+
+  for(unsigned int i = 0; i < probes; ++i)
+    {
+      double val = dround( rndvar.GetValue(), precision );
+
+      ++histogramm[val];
+    }
+
+  Gnuplot2dDataset data;
+  data.SetTitle(title);
+
+  if (notcontinous)
+    {
+      data.SetStyle(Gnuplot2dDataset::IMPULSES);
+    }
+
+  for(histogramm_maptype::const_iterator hi = histogramm.begin();
+      hi != histogramm.end(); ++hi)
+    {
+      data.Add(hi->first, (double)hi->second / (double)probes / precision);
+    }
+
+  return data;
+}
+
+int main (int argc, char *argv[])
+{
+  unsigned int probes = 1000000;
+  double precision = 0.01;
+
+  GnuplotCollection gnuplots("main-random-variables.pdf");
+  gnuplots.SetTerminal("pdf enhanced");
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("UniformVariable");
+    plot.AppendExtra("set yrange [0:]");
+
+    plot.AddDataset( Histogramm(UniformVariable(0.0, 1.0), probes, precision,
+                                "UniformVariable [0.0 .. 1.0)") );
+
+    plot.AddDataset( Gnuplot2dFunction("0.1",
+                                       "0 <= x && x <= 1 ? 1.0 : 0") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ExponentialVariable");
+    plot.AppendExtra("set xrange [0:8]");
+    plot.AppendExtra("ExpDist(x,l) = 1/l * exp(-1/l * x)");
+
+    plot.AddDataset( Histogramm(ExponentialVariable(0.5), probes, precision,
+                                "ExponentialVariable m=0.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 0.5",
+                                       "ExpDist(x, 0.5)") );
+
+    plot.AddDataset( Histogramm(ExponentialVariable(1.0), probes, precision,
+                                "ExponentialVariable m=1") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 1.0",
+                                       "ExpDist(x, 1.0)") );
+
+    plot.AddDataset( Histogramm(ExponentialVariable(1.5), probes, precision,
+                                "ExponentialVariable m=1.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("ExponentialDistribution mean 1.5",
+                                       "ExpDist(x, 1.5)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ParetoVariable");
+    plot.AppendExtra("set xrange [0:2]");
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 1.5), probes, precision,
+                                "ParetoVariable m=1.0 s=1.5") );
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 2.0), probes, precision,
+                                "ParetoVariable m=1.0 s=2.0") );
+
+    plot.AddDataset( Histogramm(ParetoVariable(1.0, 2.5), probes, precision,
+                                "ParetoVariable m=1.0 s=2.5") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("WeibullVariable");
+    plot.AppendExtra("set xrange [0:3]");
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 1.0), probes, precision,
+                                "WeibullVariable m=1.0 s=1.0") );
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 2.0), probes, precision,
+                                "WeibullVariable m=1.0 s=2.0") );
+
+    plot.AddDataset( Histogramm(WeibullVariable(1.0, 3.0), probes, precision,
+                                "WeibullVariable m=1.0 s=3.0") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("NormalVariable");
+    plot.AppendExtra("set xrange [-3:3]");
+    plot.AppendExtra("NormalDist(x,m,s) = 1 / (s * sqrt(2*pi)) * exp(-1.0 / 2.0 * ((x-m) / s)**2)");
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 1.0), probes, precision,
+                                "NormalVariable m=0.0 v=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=1.0",
+                                       "NormalDist(x,0.0,1.0)") );
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 2.0), probes, precision,
+                                "NormalVariable m=0.0 v=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(2.0)",
+                                       "NormalDist(x,0.0,sqrt(2.0))") );
+
+    plot.AddDataset( Histogramm(NormalVariable(0.0, 3.0), probes, precision,
+                                "NormalVariable m=0.0 v=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("NormalDist {/Symbol m}=0.0 {/Symbol s}=sqrt(3.0)",
+                                       "NormalDist(x,0.0,sqrt(3.0))") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("EmpiricalVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    EmpiricalVariable emp1;
+    emp1.CDF(0.0,  0.0 / 15.0);
+    emp1.CDF(0.2,  1.0 / 15.0);
+    emp1.CDF(0.4,  3.0 / 15.0);
+    emp1.CDF(0.6,  6.0 / 15.0);
+    emp1.CDF(0.8, 10.0 / 15.0);
+    emp1.CDF(1.0, 15.0 / 15.0);
+
+    plot.AddDataset( Histogramm(emp1, probes, precision,
+                                "EmpiricalVariable (Stairs)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("DeterministicVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    double values[] = { 0.0, 0.2, 0.2, 0.4, 0.2, 0.6, 0.8, 0.8, 1.0 };
+    DeterministicVariable det1 (values, sizeof(values) / sizeof(values[0]));
+
+    plot.AddDataset( Histogramm(det1, probes, precision,
+                                "DeterministicVariable", true) );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("LogNormalVariable");
+    plot.AppendExtra("set xrange [0:3]");
+
+    plot.AppendExtra("LogNormalDist(x,m,s) = 1.0/x * NormalDist(log(x), m, s)");
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 1.0), probes, precision,
+                                "LogNormalVariable m=0.0 s=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 1.0)",
+                                       "LogNormalDist(x, 0.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.5), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.5") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.25), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.25") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 0.25)",
+                                       "LogNormalDist(x, 0.0, 0.25)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 0.125), probes, precision,
+                                "LogNormalVariable m=0.0 s=0.125") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 2.0), probes, precision,
+                                "LogNormalVariable m=0.0 s=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("LogNormalDist(x, 0.0, 2.0)",
+                                       "LogNormalDist(x, 0.0, 2.0)") );
+
+    plot.AddDataset( Histogramm(LogNormalVariable(0.0, 2.5), probes, precision,
+                                "LogNormalVariable m=0.0 s=2.5") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("TriangularVariable");
+    plot.AppendExtra("set xrange [*:*]");
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.5), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.5") );
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.4), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.4") );
+
+    plot.AddDataset( Histogramm(TriangularVariable(0.0, 1.0, 0.65), probes, precision,
+                                "TriangularVariable [0.0 .. 1.0) m=0.65") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("GammaVariable");
+    plot.AppendExtra("set xrange [0:10]");
+    plot.AppendExtra("set yrange [0:1]");
+    plot.AppendExtra("GammaDist(x,a,b) = x**(a-1) * 1/b**a * exp(-x/b) / gamma(a)");
+
+    plot.AppendExtra("set label 1 '{/Symbol g}(x,{/Symbol a},{/Symbol b}) = x^{/Symbol a-1} e^{-x {/Symbol b}^{-1}} ( {/Symbol b}^{/Symbol a} {/Symbol G}({/Symbol a}) )^{-1}' at 0.7, 0.9");
+
+    plot.AddDataset( Histogramm(GammaVariable(1.0, 1.0), probes, precision,
+                                "GammaVariable a=1.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 1.0, 1.0)",
+                                       "GammaDist(x, 1.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(1.5, 1.0), probes, precision,
+                                "GammaVariable a=1.5 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 1.5, 1.0)",
+                                       "GammaDist(x, 1.5, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.0, 1.0), probes, precision,
+                                "GammaVariable a=2.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.0, 1.0)",
+                                       "GammaDist(x, 2.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(4.0, 1.0), probes, precision,
+                                "GammaVariable a=4.0 b=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 4.0, 1.0)",
+                                       "GammaDist(x, 4.0, 1.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.0, 2.0), probes, precision,
+                                "GammaVariable a=2.0 b=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.0, 2.0)",
+                                       "GammaDist(x, 2.0, 2.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.5, 3.0), probes, precision,
+                                "GammaVariable a=2.5 b=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.5, 3.0)",
+                                       "GammaDist(x, 2.5, 3.0)") );
+
+    plot.AddDataset( Histogramm(GammaVariable(2.5, 4.5), probes, precision,
+                                "GammaVariable a=2.5 b=4.5") );
+
+    plot.AddDataset( Gnuplot2dFunction("{/Symbol g}(x, 2.5, 4.5)",
+                                       "GammaDist(x, 2.5, 4.5)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  {
+    Gnuplot plot;
+    plot.SetTitle("ErlangVariable");
+    plot.AppendExtra("set xrange [0:10]");
+    plot.AppendExtra("ErlangDist(x,k,l) = x**(k-1) * 1/l**k * exp(-x/l) / (k-1)!");
+
+    plot.AppendExtra("set label 1 'Erlang(x,k,{/Symbol l}) = x^{k-1} e^{-x {/Symbol l}^{-1}} ( {/Symbol l}^k (k-1)! )^{-1}' at 0.7, 0.9");
+
+    plot.AddDataset( Histogramm(ErlangVariable(1, 1.0), probes, precision,
+                                "ErlangVariable k=1 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 1, 1.0)",
+                                       "ErlangDist(x, 1, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 1.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 1.0)",
+                                       "ErlangDist(x, 2, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(3, 1.0), probes, precision,
+                                "ErlangVariable k=3 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 3, 1.0)",
+                                       "ErlangDist(x, 3, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(5, 1.0), probes, precision,
+                                "ErlangVariable k=5 {/Symbol l}=1.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 5, 1.0)",
+                                       "ErlangDist(x, 5, 1.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 2.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=2.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 2.0)",
+                                       "ErlangDist(x, 2, 2.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 3.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=3.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 3.0)",
+                                       "ErlangDist(x, 2, 3.0)") );
+
+    plot.AddDataset( Histogramm(ErlangVariable(2, 5.0), probes, precision,
+                                "ErlangVariable k=2 {/Symbol l}=5.0") );
+
+    plot.AddDataset( Gnuplot2dFunction("Erlang(x, 2, 5.0)",
+                                       "ErlangDist(x, 2, 5.0)") );
+
+    gnuplots.AddPlot(plot);
+  }
+
+  gnuplots.GenerateOutput(std::cout);
+
+  return 0;
+}
--- a/samples/wscript	Sun Apr 12 22:41:33 2009 -0700
+++ b/samples/wscript	Fri Apr 17 12:33:17 2009 -0700
@@ -10,6 +10,9 @@
     obj = bld.create_ns3_program('main-simulator')
     obj.source = 'main-simulator.cc'
 
+    obj = bld.create_ns3_program('main-random-variable')
+    obj.source = 'main-random-variable.cc'
+
     obj = bld.create_ns3_program('main-packet-header', ['common', 'simulator'])
     obj.source = 'main-packet-header.cc'
 
--- a/src/core/log.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/core/log.h	Fri Apr 17 12:33:17 2009 -0700
@@ -23,6 +23,7 @@
 
 #include <string>
 #include <iostream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/core/ptr.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/core/ptr.h	Fri Apr 17 12:33:17 2009 -0700
@@ -106,7 +106,7 @@
   T *operator -> () const;
   T *operator -> ();
   const T &operator * () const;
-  const T &operator * ();
+  T &operator * ();
   // allow if (!sp)
   bool operator! ();
   // allow if (sp)
@@ -472,7 +472,7 @@
 }
 
 template <typename T>
-const T &
+T &
 Ptr<T>::operator * ()
 {
   return *m_ptr;
--- a/src/core/random-variable.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/core/random-variable.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1220,6 +1220,230 @@
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
+// GammaVariableImpl
+class GammaVariableImpl : public RandomVariableBase
+{
+public:
+  /**
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   */
+  GammaVariableImpl (double alpha, double beta);
+
+  /**
+   * \return A random value from this distribution
+   */
+  virtual double GetValue ();
+
+  /**
+   * \return A random value from the gamma distribution with parameters alpha
+   * and beta
+   */
+  double GetValue(double alpha, double beta);
+
+  virtual RandomVariableBase* Copy(void) const;
+
+private:
+  double m_alpha;
+  double m_beta;
+  NormalVariable m_normal;
+};
+
+
+RandomVariableBase* GammaVariableImpl::Copy () const
+{
+  return new GammaVariableImpl (m_alpha, m_beta);
+}
+
+GammaVariableImpl::GammaVariableImpl (double alpha, double beta)
+  : m_alpha(alpha), m_beta(beta) 
+{
+}
+
+double
+GammaVariableImpl::GetValue ()
+{
+  return GetValue(m_alpha, m_beta);
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  Originally the algorithm was devised by Marsaglia in 2000:
+  G. Marsaglia, W. W. Tsang: A simple method for gereating Gamma variables
+  ACM Transactions on mathematical software, Vol. 26, No. 3, Sept. 2000
+
+  The Gamma distribution density function has the form 
+
+	                     x^(alpha-1) * exp(-x/beta)
+	p(x; alpha, beta) = ----------------------------
+                             beta^alpha * Gamma(alpha)
+
+  for x > 0.
+*/
+double
+GammaVariableImpl::GetValue (double alpha, double beta)
+{
+  if(!m_generator)
+    {
+      m_generator = new RngStream();
+    }
+
+  if (alpha < 1)
+    {
+      double u = m_generator->RandU01 ();
+      return GetValue(1.0 + alpha, beta) * pow (u, 1.0 / alpha);
+    }
+	
+  double x, v, u;
+  double d = alpha - 1.0 / 3.0;
+  double c = (1.0 / 3.0) / sqrt (d);
+
+  while (1)
+    {
+      do
+        {
+          x = m_normal.GetValue ();
+          v = 1.0 + c * x;
+        } while (v <= 0);
+
+      v = v * v * v;
+      u = m_generator->RandU01 ();
+      if (u < 1 - 0.0331 * x * x * x * x)
+        {
+          break;
+        }
+      if (log (u) < 0.5 * x * x + d * (1 - v + log (v)))
+        {
+          break;
+        }
+    }
+
+  return beta * d * v;
+}
+
+GammaVariable::GammaVariable ()
+  : RandomVariable (GammaVariableImpl (1.0, 1.0))
+{
+}
+
+GammaVariable::GammaVariable (double alpha, double beta)
+  : RandomVariable (GammaVariableImpl (alpha, beta))
+{
+}
+
+double GammaVariable::GetValue(void) const
+{
+  return this->RandomVariable::GetValue ();
+}
+
+double GammaVariable::GetValue(double alpha, double beta) const
+{
+  return ((GammaVariableImpl*)Peek())->GetValue(alpha, beta);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// ErlangVariableImpl
+
+class ErlangVariableImpl : public RandomVariableBase
+{
+public:
+  /**
+   * \param k k parameter of the Erlang distribution
+   * \param lambda lambda parameter of the Erlang distribution
+   */
+  ErlangVariableImpl (unsigned int k, double lambda);
+
+  /**
+   * \return A random value from this distribution
+   */
+  virtual double GetValue ();
+
+  /**
+   * \return A random value from the Erlang distribution with parameters k and
+   * lambda.
+   */
+  double GetValue(unsigned int k, double lambda);
+
+  virtual RandomVariableBase* Copy(void) const;
+
+private:
+  unsigned int m_k;
+  double m_lambda;
+};
+
+
+RandomVariableBase* ErlangVariableImpl::Copy () const
+{
+  return new ErlangVariableImpl (m_k, m_lambda);
+}
+
+ErlangVariableImpl::ErlangVariableImpl (unsigned int k, double lambda)
+  : m_k(k), m_lambda(lambda)
+{
+}
+
+double
+ErlangVariableImpl::GetValue ()
+{
+  return GetValue(m_k, m_lambda);
+}
+
+/*
+  The code for the following generator functions was adapted from ns-2
+  tools/ranvar.cc
+
+  The Erlang distribution density function has the form 
+
+	                   x^(k-1) * exp(-x/lambda)
+	p(x; k, lambda) = ---------------------------
+                             lambda^k * (k-1)!
+
+  for x > 0.
+*/
+double
+ErlangVariableImpl::GetValue (unsigned int k, double lambda)
+{
+  if(!m_generator)
+    {
+      m_generator = new RngStream();
+    }
+
+  ExponentialVariable exponential(lambda);
+
+  double result = 0;
+  for (unsigned int i = 0; i < k; ++i)
+    {
+      result += exponential.GetValue();
+    }
+
+  return result;
+}
+
+ErlangVariable::ErlangVariable ()
+  : RandomVariable (ErlangVariableImpl (1, 1.0))
+{
+}
+
+ErlangVariable::ErlangVariable (unsigned int k, double lambda)
+  : RandomVariable (ErlangVariableImpl (k, lambda))
+{
+}
+
+double ErlangVariable::GetValue(void) const
+{
+  return this->RandomVariable::GetValue ();
+}
+
+double ErlangVariable::GetValue(unsigned int k, double lambda) const
+{
+  return ((ErlangVariableImpl*)Peek())->GetValue(k, lambda);
+}
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // TriangularVariableImpl methods
 class TriangularVariableImpl : public RandomVariableBase {
 public:
--- a/src/core/random-variable.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/core/random-variable.h	Fri Apr 17 12:33:17 2009 -0700
@@ -36,7 +36,7 @@
  *
  */
 
-namespace ns3{
+namespace ns3 {
 
 class RandomVariableBase;
 
@@ -422,7 +422,7 @@
    * value and a shape (alpha) parameter of 1.5.
    * \param m mean value of the distribution
    */
-   WeibullVariable(double m) ;
+  WeibullVariable(double m) ;
 
   /**
    * Constructs a weibull random variable with the specified mean
@@ -560,7 +560,6 @@
   explicit DeterministicVariable(double* d, uint32_t c);
 };
 
-
 /**
  * \brief Log-normal Distributed random var
  * \ingroup randomvariable
@@ -594,6 +593,108 @@
 };
 
 /**
+ * \brief Gamma Distributed Random Variable
+ * \ingroup randomvariable
+ *
+ * GammaVariable defines a random variable with gamma distribution. 
+ *
+ * This class supports the creation of objects that return random numbers
+ * from a fixed gamma distribution. It also supports the generation of 
+ * single random numbers from various gamma distributions.
+ *
+ * The probability density function is defined over the interval [0,+inf) as:
+ * \f$ x^{\alpha-1} \frac{e^{-\frac{x}{\beta}}}{\beta^\alpha \Gamma(\alpha)}\f$
+ * where \f$ mean = \alpha\beta \f$ and 
+ * \f$ variance = \alpha \beta^2\f$
+ */
+class GammaVariable : public RandomVariable 
+{
+public:
+  /**
+   * Constructs a gamma random variable with alpha = 1.0 and beta = 1.0
+   */
+  GammaVariable ();
+
+  /**
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   */
+  GammaVariable (double alpha, double beta);
+
+  /**
+   * \brief call RandomVariable::GetValue
+   * \return A floating point random value 
+   *
+   * Note: we have to re-implement this method here because the method is
+   * overloaded below for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  double GetValue (void) const;
+  
+  /**
+   * \brief Returns a gamma random distributed double with parameters alpha and beta.
+   * \param alpha alpha parameter of the gamma distribution
+   * \param beta beta parameter of the gamma distribution
+   * \return A floating point random value
+   */
+  double GetValue(double alpha, double beta) const;
+};
+
+/**
+ * \brief Erlang Distributed Random Variable
+ * \ingroup randomvariable
+ *
+ * ErlangVariable defines a random variable with Erlang distribution.
+ *
+ * The Erlang distribution is a special case of the Gamma distribution where k
+ * (= alpha) is a non-negative integer. Erlang distributed variables can be
+ * generated using a much faster algorithm than gamma variables.
+ *
+ * This class supports the creation of objects that return random numbers from
+ * a fixed Erlang distribution. It also supports the generation of single
+ * random numbers from various Erlang distributions.
+ *
+ * The probability density function is defined over the interval [0,+inf) as:
+ * \f$ \frac{x^{k-1} e^{-\frac{x}{\lambda}}}{\lambda^k (k-1)!}\f$
+ * where \f$ mean = k \lambda \f$ and 
+ * \f$ variance = k \lambda^2\f$
+ */
+class ErlangVariable : public RandomVariable 
+{
+public:
+  /**
+   * Constructs an Erlang random variable with k = 1 and lambda = 1.0
+   */
+  ErlangVariable ();
+
+  /**
+   * \param k k parameter of the Erlang distribution. Must be a non-negative integer.
+   * \param lambda lambda parameter of the Erlang distribution
+   */
+  ErlangVariable (unsigned int k, double lambda);
+
+  /**
+   * \brief call RandomVariable::GetValue
+   * \return A floating point random value 
+   *
+   * Note: we have to re-implement this method here because the method is
+   * overloaded below for the two-argument variant and the c++ name resolution
+   * rules don't work well with overloads split between parent and child
+   * classes.
+   */
+  double GetValue (void) const;
+  
+  /**
+   * \brief Returns an Erlang random distributed double with parameters k and lambda.
+   * \param k k parameter of the Erlang distribution. Must be a non-negative integer.
+   * \param lambda lambda parameter of the Erlang distribution
+   * \return A floating point random value
+   */
+  double GetValue(unsigned int k, double lambda) const;
+};
+
+/**
  * \brief Triangularly Distributed random var
  * \ingroup randomvariable
  * 
--- a/src/core/type-id.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/core/type-id.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -71,6 +71,9 @@
   bool MustHideFromDocumentation (uint16_t uid) const;
 
 private:
+  bool HasTraceSource (uint16_t uid, std::string name);
+  bool HasAttribute (uint16_t uid, std::string name);
+
   struct AttributeInformation {
     std::string name;
     std::string help;
@@ -231,6 +234,33 @@
   return i + 1;
 }
 
+bool
+IidManager::HasAttribute (uint16_t uid,
+                          std::string name)
+{
+  struct IidInformation *information  = LookupInformation (uid);
+  while (true)
+    {
+      for (std::vector<struct AttributeInformation>::const_iterator i = information->attributes.begin ();
+           i != information->attributes.end (); ++i)
+        {
+          if (i->name == name)
+            {
+              return true;
+            }
+        }
+      struct IidInformation *parent = LookupInformation (information->parent);
+      if (parent == information)
+        {
+          // top of inheritance tree
+          return false;
+        }
+      // check parent
+      information = parent;
+    }
+  return false;
+}
+
 void 
 IidManager::AddAttribute (uint16_t uid, 
                           std::string name,
@@ -241,14 +271,10 @@
                           ns3::Ptr<const ns3::AttributeChecker> checker)
 {
   struct IidInformation *information = LookupInformation (uid);
-  for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
-       j != information->attributes.end (); j++)
+  if (HasAttribute (uid, name))
     {
-      if (j->name == name)
-        {
-          NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
-          return;
-        }
+      NS_FATAL_ERROR ("Attribute \"" << name << "\" already registered on tid=\"" << 
+                      information->name << "\"");
     }
   struct AttributeInformation param;
   param.name = name;
@@ -310,6 +336,33 @@
   return information->attributes[i].checker;
 }
 
+bool
+IidManager::HasTraceSource (uint16_t uid,
+                            std::string name)
+{
+  struct IidInformation *information  = LookupInformation (uid);
+  while (true)
+    {
+      for (std::vector<struct TraceSourceInformation>::const_iterator i = information->traceSources.begin ();
+           i != information->traceSources.end (); ++i)
+        {
+          if (i->name == name)
+            {
+              return true;
+            }
+        }
+      struct IidInformation *parent = LookupInformation (information->parent);
+      if (parent == information)
+        {
+          // top of inheritance tree
+          return false;
+        }
+      // check parent
+      information = parent;
+    }
+  return false;
+}
+
 void 
 IidManager::AddTraceSource (uint16_t uid,
                             std::string name, 
@@ -317,6 +370,11 @@
                             ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
 {
   struct IidInformation *information  = LookupInformation (uid);
+  if (HasTraceSource (uid, name))
+    {
+      NS_FATAL_ERROR ("Trace source \"" << name << "\" already registered on tid=\"" << 
+                      information->name << "\"");
+    }
   struct TraceSourceInformation source;
   source.name = name;
   source.help = help;
--- a/src/devices/bridge/bridge-channel.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/bridge/bridge-channel.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -34,7 +34,7 @@
 }
 
 BridgeChannel::BridgeChannel ()
-  : Channel ("BridgeChannel")
+  : Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
--- a/src/devices/bridge/bridge-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/bridge/bridge-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -53,7 +53,6 @@
 
 BridgeNetDevice::BridgeNetDevice ()
   : m_node (0),
-    m_name (""),
     m_ifIndex (0),
     m_mtu (0xffff)
 {
@@ -111,7 +110,14 @@
       break;
 
     case PACKET_OTHERHOST:
-      ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
+      if (dst48 == m_address)
+        {
+          m_rxCallback (this, packet, protocol, src);
+        }
+      else
+        {
+          ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
+        }
       break;
     }
 }
@@ -121,7 +127,7 @@
                                  uint16_t protocol, Mac48Address src, Mac48Address dst)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
+  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
                 << ", packet=" << packet << ", protocol="<<protocol
                 << ", src=" << src << ", dst=" << dst << ")");
 
@@ -129,7 +135,7 @@
   Ptr<NetDevice> outPort = GetLearnedState (dst);
   if (outPort != NULL && outPort != incomingPort)
     {
-      NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetName () << "'");
+      NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetInstanceTypeId ().GetName () << "'");
       outPort->SendFrom (packet->Copy (), src, dst, protocol);
     }
   else
@@ -141,8 +147,9 @@
           Ptr<NetDevice> port = *iter;
           if (port != incomingPort)
             {
-              NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
-                            << " --> " << port->GetName ()
+              NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " 
+                            << incomingPort->GetInstanceTypeId ().GetName ()
+                            << " --> " << port->GetInstanceTypeId ().GetName ()
                             << " (UID " << packet->GetUid () << ").");
               port->SendFrom (packet->Copy (), src, dst, protocol);
             }
@@ -155,7 +162,7 @@
                                         uint16_t protocol, Mac48Address src, Mac48Address dst)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
+  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetInstanceTypeId ().GetName ()
                 << ", packet=" << packet << ", protocol="<<protocol
                 << ", src=" << src << ", dst=" << dst << ")");
   Learn (src, incomingPort);
@@ -166,8 +173,9 @@
       Ptr<NetDevice> port = *iter;
       if (port != incomingPort)
         {
-          NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
-                        << " --> " << port->GetName ()
+          NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " 
+                        << incomingPort->GetInstanceTypeId ().GetName ()
+                        << " --> " << port->GetInstanceTypeId ().GetName ()
                         << " (UID " << packet->GetUid () << ").");
           port->SendFrom (packet->Copy (), src, dst, protocol);
         }
@@ -242,7 +250,7 @@
       m_address = Mac48Address::ConvertFrom (bridgePort->GetAddress ());
     }
 
-  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetName ());
+  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetInstanceTypeId ().GetName ());
   m_node->RegisterProtocolHandler (MakeCallback (&BridgeNetDevice::ReceiveFromDevice, this),
                                    0, bridgePort, true);
   m_ports.push_back (bridgePort);
@@ -250,20 +258,6 @@
 }
 
 void 
-BridgeNetDevice::SetName(const std::string name)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_name = name;
-}
-
-std::string 
-BridgeNetDevice::GetName(void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-void 
 BridgeNetDevice::SetIfIndex(const uint32_t index)
 {
   NS_LOG_FUNCTION_NOARGS ();
--- a/src/devices/bridge/bridge-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/bridge/bridge-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -88,8 +88,6 @@
   Ptr<NetDevice> GetBridgePort (uint32_t n) const;
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -140,7 +138,6 @@
   std::map<Mac48Address, LearnedState> m_learnState;
   Ptr<Node> m_node;
   Ptr<BridgeChannel> m_channel;
-  std::string m_name;
   std::vector< Ptr<NetDevice> > m_ports;
   uint32_t m_ifIndex;
   uint16_t m_mtu;
--- a/src/devices/csma/csma-channel.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/csma/csma-channel.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -51,7 +51,7 @@
 
 CsmaChannel::CsmaChannel ()
 : 
-  Channel ("Csma Channel")
+  Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_state = IDLE;
--- a/src/devices/csma/csma-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/csma/csma-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -154,8 +154,7 @@
 }
 
 CsmaNetDevice::CsmaNetDevice ()
-  : m_name (""),
-    m_linkUp (false)
+ : m_linkUp (false)
 {
   NS_LOG_FUNCTION (this);
   m_txMachineState = READY;
@@ -874,20 +873,6 @@
 }
 
   void 
-CsmaNetDevice::SetName (const std::string name)
-{
-  NS_LOG_FUNCTION (name);
-  m_name = name;
-}
-
-  std::string 
-CsmaNetDevice::GetName (void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-  void 
 CsmaNetDevice::SetIfIndex (const uint32_t index)
 {
   NS_LOG_FUNCTION (index);
@@ -1054,25 +1039,6 @@
   NS_LOG_FUNCTION (node);
 
   m_node = node;
-  int count = -1;
-  if (m_name.size () == 0)
-    {
-      for (uint32_t i = 0; i < node->GetNDevices (); i++)
-        {
-          Ptr<NetDevice> dev = node->GetDevice (i);
-          if (dynamic_cast<CsmaNetDevice*> (PeekPointer (dev)))
-            {
-              count++;
-              if (dev == this)
-                {
-                  break;
-                }
-            }
-        }
-      std::ostringstream s;
-      s << "eth" << count;
-      m_name = s.str ();
-    }
 }
 
   bool 
--- a/src/devices/csma/csma-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/csma/csma-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -305,8 +305,6 @@
   //
   // The following methods are inherited from NetDevice base class.
   //
-  virtual void SetName (const std::string name);
-  virtual std::string GetName (void) const;
   virtual void SetIfIndex (const uint32_t index);
   virtual uint32_t GetIfIndex (void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -808,11 +806,6 @@
   uint32_t m_ifIndex;
 
   /**
-   * The human readable name of this device.
-   */
-  std::string m_name;
-
-  /**
    * Flag indicating whether or not the link is up.  In this case,
    * whether or not the device is connected to a channel.
    */
--- a/src/devices/emu/emu-encode-decode.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/emu/emu-encode-decode.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -20,6 +20,7 @@
 #include <iostream>
 #include <iomanip>
 #include <sstream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/devices/emu/emu-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/emu/emu-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -68,11 +68,6 @@
                    Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
                    MakeMac48AddressAccessor (&EmuNetDevice::m_address),
                    MakeMac48AddressChecker ())
-    .AddAttribute ("DeviceName", 
-                   "The name of the underlying real device (e.g. eth1).",
-                   StringValue ("eth1"),
-                   MakeStringAccessor (&EmuNetDevice::m_deviceName),
-                   MakeStringChecker ())
     .AddAttribute ("Start", 
                    "The simulation time at which to spin up the device thread.",
                    TimeValue (Seconds (0.)),
@@ -173,8 +168,7 @@
   m_sock (-1),
   m_readThread (0),
   m_ifIndex (std::numeric_limits<uint32_t>::max ()),  // absurdly large value
-  m_sll_ifindex (-1),
-  m_name ("Emu NetDevice")
+  m_sll_ifindex (-1)
 {
   NS_LOG_FUNCTION (this);
   Start (m_tStart);
@@ -844,18 +838,6 @@
 }
 
 void 
-EmuNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-
-std::string 
-EmuNetDevice::GetName(void) const
-{
-  return m_name;
-}
-
-void 
 EmuNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/emu/emu-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/emu/emu-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -105,9 +105,6 @@
 //
 // Pure virtual methods inherited from NetDevice we must implement.
 //
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
-
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
 
@@ -450,11 +447,6 @@
   int32_t m_sll_ifindex;
 
   /**
-   * The human readable name of this device.
-   */
-  std::string m_name;
-
-  /**
    * Flag indicating whether or not the link is up.  In this case,
    * whether or not the device is connected to a channel.
    */
--- a/src/devices/point-to-point/point-to-point-channel.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/point-to-point/point-to-point-channel.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -43,11 +43,11 @@
 }
 
 //
-// By default, you get a channel with the name "PointToPoint Channel" that 
+// By default, you get a channel that 
 // has an "infitely" fast transmission speed and zero delay.
 PointToPointChannel::PointToPointChannel()
 : 
-  Channel ("PointToPoint Channel"), 
+  Channel (), 
   m_delay (Seconds (0.)),
   m_nDevices (0)
 {
--- a/src/devices/point-to-point/point-to-point-channel.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/point-to-point/point-to-point-channel.h	Fri Apr 17 12:33:17 2009 -0700
@@ -50,7 +50,7 @@
   /**
    * \brief Create a PointToPointChannel
    *
-   * By default, you get a channel with the name "PointToPoint Channel" that
+   * By default, you get a channel that
    * has zero transmission delay.
    */
   PointToPointChannel ();
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -148,7 +148,6 @@
 : 
   m_txMachineState (READY),
   m_channel (0), 
-  m_name (""),
   m_linkUp (false),
   m_currentPkt (0)
 {
@@ -374,18 +373,6 @@
 }
 
   void 
-PointToPointNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-
-  std::string 
-PointToPointNetDevice::GetName(void) const
-{
-  return m_name;
-}
-
-  void 
 PointToPointNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/point-to-point/point-to-point-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -226,12 +226,6 @@
    */
   uint16_t GetFrameSize (void) const;
 
-//
-// Pure virtual methods inherited from NetDevice we must implement.
-//
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
-
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
 
@@ -531,7 +525,6 @@
   NetDevice::ReceiveCallback m_rxCallback;
   NetDevice::PromiscReceiveCallback m_promiscCallback;
   uint32_t m_ifIndex;
-  std::string m_name;
   bool m_linkUp;
   Callback<void> m_linkChangeCallback;
 
--- a/src/devices/tap-bridge/tap-bridge.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/tap-bridge/tap-bridge.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -962,20 +962,6 @@
 }
 
 void 
-TapBridge::SetName(const std::string name)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_name = name;
-}
-
-std::string 
-TapBridge::GetName(void) const
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
-void 
 TapBridge::SetIfIndex(const uint32_t index)
 {
   NS_LOG_FUNCTION_NOARGS ();
--- a/src/devices/tap-bridge/tap-bridge.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/tap-bridge/tap-bridge.h	Fri Apr 17 12:33:17 2009 -0700
@@ -173,8 +173,6 @@
   // The following methods are inherited from NetDevice base class and are
   // documented there.
   //
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -318,12 +316,6 @@
    */
   Ptr<Node> m_node;
 
-  /**
-   * \internal
-   *
-   * A possible name for the (ghost) Node to which we are connected.
-   */
-  std::string m_name;
 
   /**
    * \internal
--- a/src/devices/tap-bridge/tap-creator.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/tap-bridge/tap-creator.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -138,13 +138,17 @@
     }
 }
 
-static void
-SetInetAddress (sockaddr *ad, uint32_t networkOrder)
+static sockaddr
+CreateInetAddress (uint32_t networkOrder)
 {
-  struct sockaddr_in *sin = (struct sockaddr_in*)ad;
-  sin->sin_family = AF_INET;
-  sin->sin_port = 0; // unused
-  sin->sin_addr.s_addr = htonl (networkOrder);
+  union {
+    struct sockaddr any_socket;
+    struct sockaddr_in si;
+  } s;
+  s.si.sin_family = AF_INET;
+  s.si.sin_port = 0; // unused
+  s.si.sin_addr.s_addr = htonl (networkOrder);
+  return s.any_socket;
 }
 
   static void
@@ -330,7 +334,7 @@
   //
   // Set the IP address of the new interface/device.
   //
-  SetInetAddress (&ifr.ifr_addr, AsciiToIpv4 (ip));
+  ifr.ifr_addr = CreateInetAddress (AsciiToIpv4 (ip));
   status = ioctl (fd, SIOCSIFADDR, &ifr);
   ABORT_IF (status == -1, "Could not set IP address", true);
   LOG ("Set device IP address to " << ip);
@@ -338,7 +342,7 @@
   //
   // Set the net mask of the new interface/device
   //
-  SetInetAddress (&ifr.ifr_netmask, AsciiToIpv4 (netmask));
+  ifr.ifr_netmask = CreateInetAddress (AsciiToIpv4 (netmask));
   status = ioctl (fd, SIOCSIFNETMASK, &ifr);
   ABORT_IF (status == -1, "Could not set net mask", true);
   LOG ("Set device Net Mask to " << netmask);
--- a/src/devices/tap-bridge/tap-encode-decode.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/tap-bridge/tap-encode-decode.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -20,6 +20,7 @@
 #include <iostream>
 #include <iomanip>
 #include <sstream>
+#include <stdint.h>
 
 namespace ns3 {
 
--- a/src/devices/wifi/aarf-wifi-manager.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/aarf-wifi-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -71,39 +71,34 @@
 WifiRemoteStation *
 AarfWifiManager::CreateStation (void)
 {
-  return new AarfWifiRemoteStation (this, m_minTimerThreshold,
-                                    m_minSuccessThreshold,
-                                    m_successK,
-                                    m_maxSuccessThreshold,
-                                    m_timerK);
+  return new AarfWifiRemoteStation (this);
 }
 
 
 
 
-AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
-                                              uint32_t minTimerThreshold,
-                                              uint32_t minSuccessThreshold,
-                                              double successK,
-                                              uint32_t maxSuccessThreshold,
-                                              double timerK)
-  : ArfWifiRemoteStation (stations, minTimerThreshold, minSuccessThreshold),
-    m_successK (successK),
-    m_maxSuccessThreshold (maxSuccessThreshold),
-    m_timerK (timerK)
+AarfWifiRemoteStation::AarfWifiRemoteStation (Ptr<AarfWifiManager> manager)
+  : ArfWifiRemoteStation (manager),
+    m_manager (manager)
 {}
 
 
 AarfWifiRemoteStation::~AarfWifiRemoteStation ()
 {}
 
+Ptr<WifiRemoteStationManager> 
+AarfWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
 void 
 AarfWifiRemoteStation::ReportRecoveryFailure (void)
 {
-  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_successK,
-                                  m_maxSuccessThreshold)));
+  SetSuccessThreshold ((int)(Min (GetSuccessThreshold () * m_manager->m_successK,
+                                  m_manager->m_maxSuccessThreshold)));
   SetTimerTimeout ((int)(Max (GetMinTimerTimeout (),
-                              GetSuccessThreshold () * m_timerK)));
+                              GetSuccessThreshold () * m_manager->m_timerK)));
 }
 
 void 
--- a/src/devices/wifi/aarf-wifi-manager.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/aarf-wifi-manager.h	Fri Apr 17 12:33:17 2009 -0700
@@ -17,8 +17,8 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#ifndef AARF_MAC_STATIONS_H
-#define AARF_MAC_STATIONS_H
+#ifndef AARF_WIFI_MANAGER_H
+#define AARF_WIFI_MANAGER_H
 
 #include "arf-wifi-manager.h"
 
@@ -39,6 +39,7 @@
   AarfWifiManager ();
   virtual ~AarfWifiManager ();
 private:
+  friend class AarfWifiRemoteStation;
   virtual class WifiRemoteStation *CreateStation (void);
   uint32_t m_minTimerThreshold;
   uint32_t m_minSuccessThreshold;
@@ -50,24 +51,18 @@
 class AarfWifiRemoteStation : public ArfWifiRemoteStation
 {
 public:
-  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations,
-                         uint32_t minTimerThreshold,
-                         uint32_t minSuccessThreshold,
-                         double successK,
-                         uint32_t maxSuccessThreshold,
-                         double timerK);
+  AarfWifiRemoteStation (Ptr<AarfWifiManager> stations);
   virtual ~AarfWifiRemoteStation ();
 
 private:
   virtual void ReportRecoveryFailure (void);
   virtual void ReportFailure (void);
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
 
-  double m_successK;
-  uint32_t m_maxSuccessThreshold;
-  double m_timerK;
+  Ptr<AarfWifiManager> m_manager;
 };
 
 } // namespace ns3
 
 
-#endif /* AARF_MAC_STATIONS_H */
+#endif /* AARF_WIFI_MANAGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarfcd-wifi-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,410 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+
+#include "aarfcd-wifi-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/boolean.h"
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("Aarfcd");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(AarfcdWifiManager);
+
+AarfcdWifiRemoteStation::AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager)
+  : m_manager (manager)
+{
+  m_timerTimeout = m_manager->m_minTimerThreshold;
+  m_successThreshold = m_manager->m_minSuccessThreshold;
+  m_rate = GetMinRate ();
+
+  m_success = 0;
+  m_failed = 0;
+  m_recovery = false;
+  m_retry = 0;
+  m_timer = 0;
+  m_rtsOn = false;
+  m_rtsWnd = m_manager->m_minRtsWnd;
+  m_rtsCounter = 0;
+  m_justModifyRate = true;
+  m_haveASuccess = false;
+}
+AarfcdWifiRemoteStation::~AarfcdWifiRemoteStation ()
+{}
+
+uint32_t
+AarfcdWifiRemoteStation::GetMaxRate (void)
+{
+  return GetNSupportedModes () - 1;
+}
+uint32_t
+AarfcdWifiRemoteStation::GetMinRate (void)
+{
+  return 0;
+}
+
+void
+AarfcdWifiRemoteStation::ReportRecoveryFailure (void)
+{
+  m_successThreshold = (int)(std::min ((uint32_t)(m_successThreshold * m_manager->m_successK),
+                                       m_manager->m_maxSuccessThreshold));
+  m_timerTimeout = (int)(std::max (m_manager->m_minTimerThreshold,
+                                   (uint32_t)(m_successThreshold * m_manager->m_timerK)));
+}
+
+void
+AarfcdWifiRemoteStation::ReportFailure (void)
+{
+  m_timerTimeout = m_manager->m_minTimerThreshold;
+  m_successThreshold = m_manager->m_minSuccessThreshold;
+}
+
+bool 
+AarfcdWifiRemoteStation::NeedRecoveryFallback (void)
+{
+  if (m_retry >= 1) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+bool 
+AarfcdWifiRemoteStation::NeedNormalFallback (void)
+{
+  int retryMod = (m_retry - 1) % 2;
+  if (retryMod == 1) 
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+
+
+
+void 
+AarfcdWifiRemoteStation::DoReportRtsFailed (void)
+{
+  //printf ("%.9f %p RtsFail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  NS_LOG_INFO ("" << this << " RtsFail rate=" << m_rate);
+  if (m_manager->m_rtsFailsAsDataFails)
+    {
+      m_rtsCounter--;
+      ReportDataFailed ();
+    }
+}
+/**
+ * It is important to realize that "recovery" mode starts after failure of
+ * the first transmission after a rate increase and ends at the first successful
+ * transmission. Specifically, recovery mode transcends retransmissions boundaries.
+ * Fundamentally, ARF handles each data transmission independently, whether it
+ * is the initial transmission of a packet or the retransmission of a packet.
+ * The fundamental reason for this is that there is a backoff between each data
+ * transmission, be it an initial transmission or a retransmission.
+ */
+void 
+AarfcdWifiRemoteStation::DoReportDataFailed (void)
+{
+  NS_LOG_INFO ("" << this << " TxFail rate=" << m_rate);
+  m_timer++;
+  m_failed++;
+  m_retry++;
+  m_success = 0;
+  //printf ("%.9f %p Fail %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  if (!m_rtsOn) 
+    {
+      TurnOnRts ();
+      if (!m_justModifyRate && !m_haveASuccess) 
+        {
+          //printf ("%p Increase RTS Windows\n",this);
+          IncreaseRtsWnd ();
+        }
+      else 
+        {
+          //printf ("%p Reset RTS Window\n",this);
+          ResetRtsWnd ();
+        }
+      m_rtsCounter = m_rtsWnd;
+      if (m_retry >= 2) 
+        {
+          m_timer = 0;
+        }
+      //printf ("%.9f %p AtcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
+    }
+  else if (m_recovery) 
+    {
+      NS_ASSERT (m_retry >= 1);
+      m_justModifyRate = false;
+      m_rtsCounter = m_rtsWnd;
+      if (NeedRecoveryFallback ()) 
+        {
+          if (m_manager->m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts ();
+            }
+          m_justModifyRate = true;
+          ReportRecoveryFailure ();
+          if (m_rate != GetMinRate ()) 
+            {
+              m_rate--;
+            }
+          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
+          //printf ("%.9f %p DecreaseRateRecovery %d\n", Simulator::Now ().GetSeconds (),this, m_rate);
+        }
+      m_timer = 0;
+    } 
+  else 
+    {
+      NS_ASSERT (m_retry >= 1);
+      m_justModifyRate = false;
+      m_rtsCounter = m_rtsWnd;
+      if (NeedNormalFallback ()) 
+        {
+          if (m_manager->m_turnOffRtsAfterRateDecrease) 
+            {
+              TurnOffRts ();
+            }
+          m_justModifyRate = true;
+          ReportFailure ();
+          if (m_rate != GetMinRate ()) 
+            {
+              m_rate--;
+            }
+          NS_LOG_INFO ("" << this << " JD rate=" << m_rate << " Sthr=" << m_successThreshold);
+          //printf ("%.9f %p DecreaseRate %d\n", Simulator::Now ().GetSeconds (),this,m_rate);
+        }
+      if (m_retry >= 2) 
+        {
+          m_timer = 0;
+        }
+    }
+  CheckRts ();
+}
+void 
+AarfcdWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+AarfcdWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_INFO ("" << this << " RtsOk rate=" << m_rate);
+  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+  m_rtsCounter--;
+}
+void 
+AarfcdWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  NS_LOG_INFO ("" << this << " TxOk rate=" << m_rate);
+  m_timer++;
+  m_success++;
+  m_failed = 0;
+  m_recovery = false;
+  m_retry = 0;
+  m_justModifyRate = false;
+  m_haveASuccess = true;
+  //printf ("%.9f %p Ok %d %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,m_timer,m_retry);
+  //printf ("%p OK (m_success=%d, th=%d, m_rate=%d, maxRate=%d)\n",this,m_success,GetSuccessThreshold (), m_rate, GetMaxRate ());
+  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
+  if ((m_success == m_successThreshold ||
+       m_timer >= m_timerTimeout) &&
+      (m_rate < GetMaxRate ())) 
+    {
+      NS_LOG_DEBUG ("self="<<this<<" inc rate");
+      m_rate++;
+      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
+      m_timer = 0;
+      m_success = 0;
+      m_recovery = true;
+      m_justModifyRate = true;
+      if (m_manager->m_turnOnRtsAfterRateIncrease) 
+        {
+          TurnOnRts ();
+          ResetRtsWnd ();
+          m_rtsCounter = m_rtsWnd;
+        }
+      //printf ("%.9f %p IncreaseRate %d %d\n", Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
+    }
+  else if (m_success == m_successThreshold ||
+           m_timer >= m_timerTimeout) 
+    {
+      NS_LOG_INFO ("" << this << " JI rate=" << m_rate << " Sthr=" << m_successThreshold);
+    }
+  CheckRts ();
+}
+void 
+AarfcdWifiRemoteStation::DoReportFinalRtsFailed (void)
+{}
+void 
+AarfcdWifiRemoteStation::DoReportFinalDataFailed (void)
+{}
+
+WifiMode
+AarfcdWifiRemoteStation::DoGetDataMode (uint32_t size)
+{
+  return GetSupportedMode (m_rate);
+}
+WifiMode
+AarfcdWifiRemoteStation::DoGetRtsMode (void)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupportedMode (0);
+}
+
+Ptr<WifiRemoteStationManager>
+AarfcdWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
+void
+AarfcdWifiRemoteStation::CheckRts (void)
+{
+  if (m_rtsCounter == 0 && m_rtsOn) 
+    {
+      //printf ("%p Turn off RTS\n",this);
+      TurnOffRts ();
+    }
+}
+
+void
+AarfcdWifiRemoteStation::TurnOffRts (void)
+{
+  //printf ("%.9f %p DeatcivateRTS %d %d\n",Simulator::Now ().GetSeconds (),this, m_rate, m_rtsCounter);
+  m_rtsOn = false;
+  m_haveASuccess = false;
+}
+
+void
+AarfcdWifiRemoteStation::TurnOnRts (void)
+{
+  m_rtsOn = true;
+}
+
+void
+AarfcdWifiRemoteStation::IncreaseRtsWnd (void)
+{
+  if (m_rtsWnd == m_manager->m_maxRtsWnd)
+    {
+      return;
+    }
+
+  m_rtsWnd *= 2;
+  if (m_rtsWnd > m_manager->m_maxRtsWnd)
+    {
+      m_rtsWnd = m_manager->m_maxRtsWnd;
+    }
+}
+
+void
+AarfcdWifiRemoteStation::ResetRtsWnd (void)
+{
+  m_rtsWnd = m_manager->m_minRtsWnd;
+}
+
+bool
+AarfcdWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
+{
+  //printf ("%.9f %p NeedRts %d %d\n",Simulator::Now ().GetSeconds (),this,m_rate,(m_rtsOn?1:0));
+  NS_LOG_INFO ("" << this << " rate=" << m_rate << " rts=" << (m_rtsOn?"RTS":"BASIC") << " rtsCounter=" << m_rtsCounter);
+  return m_rtsOn;
+}
+
+
+
+
+
+TypeId 
+AarfcdWifiManager::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::AarfcdWifiManager")
+    .SetParent<WifiRemoteStationManager> ()
+    .AddConstructor<AarfcdWifiManager> ()
+    .AddAttribute ("SuccessK", "Multiplication factor for the success threshold in the AARF algorithm.",
+                   DoubleValue (2.0),
+                   MakeDoubleAccessor (&AarfcdWifiManager::m_successK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("TimerK",
+                   "Multiplication factor for the timer threshold in the AARF algorithm.",
+                   DoubleValue (2.0),
+                   MakeDoubleAccessor (&AarfcdWifiManager::m_timerK),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxSuccessThreshold",
+                   "Maximum value of the success threshold in the AARF algorithm.",
+                   UintegerValue (60),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_maxSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinTimerThreshold",
+                   "The minimum value for the 'timer' threshold in the AARF algorithm.",
+                   UintegerValue (15),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minTimerThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinSuccessThreshold",
+                   "The minimum value for the success threshold in the AARF algorithm.",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minSuccessThreshold),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinRtsWnd", 
+                   "Minimum value for Rts window of Aarf-CD",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_minRtsWnd),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxRtsWnd", 
+                   "Maximum value for Rts window of Aarf-CD",
+                   UintegerValue (40),
+                   MakeUintegerAccessor (&AarfcdWifiManager::m_maxRtsWnd),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RtsFailsAsDataFails",
+                   "If true the RTS failures will be treated by Aarf-CD as Data failures",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_rtsFailsAsDataFails),
+                   MakeBooleanChecker ())
+    .AddAttribute ("TurnOffRtsAfterRateDecrease",
+                   "If true the RTS mechanism will be turned off when the rate will be decreased",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_turnOffRtsAfterRateDecrease),
+                   MakeBooleanChecker ())
+    .AddAttribute ("TurnOnRtsAfterRateIncrease",
+                   "If true the RTS mechanism will be turned on when the rate will be increased",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&AarfcdWifiManager::m_turnOnRtsAfterRateIncrease),
+                   MakeBooleanChecker ())
+    ;
+  return tid;
+}
+AarfcdWifiManager::AarfcdWifiManager ()
+  : WifiRemoteStationManager ()
+{}
+AarfcdWifiManager::~AarfcdWifiManager ()
+{}
+WifiRemoteStation *
+AarfcdWifiManager::CreateStation (void)
+{
+  return new AarfcdWifiRemoteStation (this);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/aarfcd-wifi-manager.h	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,112 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+#ifndef AARFCD_WIFI_MANAGER_H
+#define AARFCD_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief an implementation of the AARF-CD algorithm
+ *
+ * This algorithm was first described in "Efficient Collision Detection for Auto Rate Fallback Algorithm".
+ * The implementation available here was done by Federico Maguolo for a very early development
+ * version of ns-3. Federico died before merging this work in ns-3 itself so his code was ported
+ * to ns-3 later without his supervision.
+ */
+class AarfcdWifiManager : public WifiRemoteStationManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  AarfcdWifiManager ();
+  virtual ~AarfcdWifiManager ();
+
+private:
+  friend class AarfcdWifiRemoteStation;
+  virtual WifiRemoteStation *CreateStation (void);
+  uint32_t m_minTimerThreshold;
+  uint32_t m_minSuccessThreshold;
+  double m_successK;
+  uint32_t m_maxSuccessThreshold;
+  double m_timerK;
+  uint32_t m_minRtsWnd;
+  uint32_t m_maxRtsWnd;
+  bool m_rtsFailsAsDataFails;
+  bool m_turnOffRtsAfterRateDecrease;
+  bool m_turnOnRtsAfterRateIncrease;
+};
+
+
+class AarfcdWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  AarfcdWifiRemoteStation (Ptr<AarfcdWifiManager> manager);
+  virtual ~AarfcdWifiRemoteStation ();
+
+
+private:
+  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
+  virtual void DoReportRtsFailed (void);
+  virtual void DoReportDataFailed (void);
+  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (void);
+  virtual void DoReportFinalDataFailed (void);
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
+  virtual WifiMode DoGetDataMode (uint32_t size);
+  virtual WifiMode DoGetRtsMode (void);
+  virtual bool NeedRts (Ptr<const Packet> packet);
+
+  void ReportRecoveryFailure (void);
+  void ReportFailure (void);
+  uint32_t GetMaxRate (void);
+  uint32_t GetMinRate (void);
+  void CheckRts (void);
+  void IncreaseRtsWnd (void);
+  void ResetRtsWnd (void);
+  void TurnOffRts (void);
+  void TurnOnRts (void);
+
+  bool NeedRecoveryFallback (void);
+  bool NeedNormalFallback (void);
+
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  bool m_recovery;
+  bool m_justModifyRate;
+  uint32_t m_retry;
+  
+  uint32_t m_successThreshold;
+  uint32_t m_timerTimeout;
+
+  uint32_t m_rate;
+  bool m_rtsOn;
+  uint32_t m_rtsWnd;
+  uint32_t m_rtsCounter;
+  bool m_haveASuccess;
+  
+  Ptr<AarfcdWifiManager> m_manager;
+};
+
+} // namespace ns3
+
+#endif /* MAARF_MAC_STATIONS_H */
--- a/src/devices/wifi/arf-wifi-manager.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/arf-wifi-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -28,15 +28,11 @@
 
 namespace ns3 {
   
-ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
-                                            int minTimerTimeout,
-                                            int minSuccessThreshold)
-  : m_stations (stations)
+ArfWifiRemoteStation::ArfWifiRemoteStation (Ptr<ArfWifiManager> manager)
+  : m_manager (manager)
 {
-  m_minTimerTimeout = minTimerTimeout;
-  m_minSuccessThreshold = minSuccessThreshold;
-  m_successThreshold = m_minSuccessThreshold;
-  m_timerTimeout = m_minTimerTimeout;
+  m_successThreshold = m_manager->m_successThreshold;
+  m_timerTimeout = m_manager->m_timerThreshold;
   m_rate = GetMinRate ();
 
   m_success = 0;
@@ -189,11 +185,11 @@
 {}
 uint32_t ArfWifiRemoteStation::GetMinTimerTimeout (void)
 {
-  return m_minTimerTimeout;
+  return m_manager->m_timerThreshold;
 }
 uint32_t ArfWifiRemoteStation::GetMinSuccessThreshold (void)
 {
-  return m_minSuccessThreshold;
+  return m_manager->m_successThreshold;
 }
 uint32_t ArfWifiRemoteStation::GetTimerTimeout (void)
 {
@@ -205,18 +201,18 @@
 }
 void ArfWifiRemoteStation::SetTimerTimeout (uint32_t timerTimeout)
 {
-  NS_ASSERT (timerTimeout >= m_minTimerTimeout);
+  NS_ASSERT (timerTimeout >= m_manager->m_timerThreshold);
   m_timerTimeout = timerTimeout;
 }
 void ArfWifiRemoteStation::SetSuccessThreshold (uint32_t successThreshold)
 {
-  NS_ASSERT (successThreshold >= m_minSuccessThreshold);
+  NS_ASSERT (successThreshold >= m_manager->m_successThreshold);
   m_successThreshold = successThreshold;
 }
 Ptr<WifiRemoteStationManager>
 ArfWifiRemoteStation::GetManager (void) const
 {
-  return m_stations;
+  return m_manager;
 }
 
 NS_OBJECT_ENSURE_REGISTERED (ArfWifiManager);
@@ -247,7 +243,7 @@
 WifiRemoteStation *
 ArfWifiManager::CreateStation (void)
 {
-  return new ArfWifiRemoteStation (this, m_timerThreshold, m_successThreshold);
+  return new ArfWifiRemoteStation (this);
 }
 
 } // namespace ns3
--- a/src/devices/wifi/arf-wifi-manager.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/arf-wifi-manager.h	Fri Apr 17 12:33:17 2009 -0700
@@ -46,6 +46,7 @@
   virtual ~ArfWifiManager ();
 
 private:
+  friend class ArfWifiRemoteStation;
   virtual class WifiRemoteStation *CreateStation (void);
   uint32_t m_timerThreshold;
   uint32_t m_successThreshold;
@@ -55,9 +56,7 @@
 class ArfWifiRemoteStation : public WifiRemoteStation
 {
 public:
-  ArfWifiRemoteStation (Ptr<ArfWifiManager> stations,
-                        int minTimerTimeout,
-                        int minSuccessThreshold);
+  ArfWifiRemoteStation (Ptr<ArfWifiManager> manager);
   virtual ~ArfWifiRemoteStation ();
 
 protected:
@@ -85,10 +84,7 @@
 
   uint32_t m_rate;
   
-  uint32_t m_minTimerTimeout;
-  uint32_t m_minSuccessThreshold;
-
-  Ptr<ArfWifiManager> m_stations;
+  Ptr<ArfWifiManager> m_manager;
   
 private:
   // overriden by AarfMacStation.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/cara-wifi-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,193 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004,2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+
+#include "cara-wifi-manager.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+NS_LOG_COMPONENT_DEFINE ("Cara");
+
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(CaraWifiManager);
+
+CaraWifiRemoteStation::CaraWifiRemoteStation (Ptr<CaraWifiManager> manager)
+  : m_manager (manager)
+{
+  m_rate = GetMinRate ();
+
+  m_success = 0;
+  m_failed = 0;
+  m_timer = 0;
+}
+CaraWifiRemoteStation::~CaraWifiRemoteStation ()
+{}
+
+uint32_t
+CaraWifiRemoteStation::GetMaxRate (void)
+{
+  return GetNSupportedModes () - 1;
+}
+uint32_t
+CaraWifiRemoteStation::GetMinRate (void)
+{
+  return 0;
+}
+
+bool 
+CaraWifiRemoteStation::NeedNormalFallback (void)
+{
+  return (m_failed >= m_manager->m_failureThreshold);
+}
+
+void 
+CaraWifiRemoteStation::DoReportRtsFailed (void) 
+{}
+
+void 
+CaraWifiRemoteStation::DoReportDataFailed (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_timer++;
+  m_failed++;
+  m_success = 0;
+  if (NeedNormalFallback ()) 
+    {
+      NS_LOG_DEBUG ("self="<<this<<" dec rate");
+      if (m_rate != GetMinRate ())
+        {
+          m_rate--;
+        }
+      m_failed = 0;
+      m_timer = 0;
+    }
+}
+void 
+CaraWifiRemoteStation::DoReportRxOk (double rxSnr, WifiMode txMode)
+{}
+void 
+CaraWifiRemoteStation::DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr)
+{
+  NS_LOG_DEBUG ("self="<<this<<" rts ok");
+}
+void 
+CaraWifiRemoteStation::DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr)
+{
+  m_timer++;
+  m_success++;
+  m_failed = 0;
+  NS_LOG_DEBUG ("self="<<this<<" data ok success="<<m_success<<", timer="<<m_timer);
+  if ((m_success == m_manager->m_successThreshold ||
+       m_timer >= m_manager->m_timerTimeout))
+    {
+      if (m_rate < GetMaxRate ())
+        {
+          m_rate++;
+        }
+      NS_LOG_DEBUG ("self="<<this<<" inc rate=" << m_rate);
+      m_timer = 0;
+      m_success = 0;
+    }
+}
+void 
+CaraWifiRemoteStation::DoReportFinalRtsFailed (void)
+{}
+void 
+CaraWifiRemoteStation::DoReportFinalDataFailed (void)
+{}
+
+WifiMode
+CaraWifiRemoteStation::DoGetDataMode (uint32_t size)
+{
+  return GetSupportedMode (m_rate);
+}
+WifiMode
+CaraWifiRemoteStation::DoGetRtsMode (void)
+{
+  // XXX: we could/should implement the Arf algorithm for
+  // RTS only by picking a single rate within the BasicRateSet.
+  return GetSupportedMode (0);
+}
+
+Ptr<WifiRemoteStationManager>
+CaraWifiRemoteStation::GetManager (void) const
+{
+  return m_manager;
+}
+
+bool
+CaraWifiRemoteStation::NeedRts (Ptr<const Packet> packet)
+{
+  bool rts = WifiRemoteStation::NeedRts (packet);
+  if (rts || m_failed >= m_manager->m_probeThreshold)
+    {
+      return true;
+    }
+
+  return false;
+}
+
+
+
+TypeId 
+CaraWifiManager::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::CaraWifiManager")
+   .SetParent<WifiRemoteStationManager> ()
+   .AddConstructor<CaraWifiManager> ()
+   .AddAttribute ("ProbeThreshold",
+                  "The number of consecutive transmissions failure to activate the RTS probe.",
+                  UintegerValue (1),
+                  MakeUintegerAccessor (&CaraWifiManager::m_probeThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("FailureThreshold",
+                  "The number of consecutive transmissions failure to decrease the rate.",
+                  UintegerValue (2),
+                  MakeUintegerAccessor (&CaraWifiManager::m_failureThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("SuccessThreshold",
+                  "The minimum number of sucessfull transmissions to try a new rate.",
+                  UintegerValue (10),
+                  MakeUintegerAccessor (&CaraWifiManager::m_successThreshold),
+                  MakeUintegerChecker<uint32_t> ())
+   .AddAttribute ("Timeout",
+                  "The 'timer' in the CARA algorithm",
+                  UintegerValue (15),
+                  MakeUintegerAccessor (&CaraWifiManager::m_timerTimeout),
+                  MakeUintegerChecker<uint32_t> ())
+ ;
+ return tid;
+}
+
+CaraWifiManager::CaraWifiManager ()
+  : WifiRemoteStationManager ()
+{}
+CaraWifiManager::~CaraWifiManager ()
+{}
+
+WifiRemoteStation *
+CaraWifiManager::CreateStation (void)
+{
+  return new CaraWifiRemoteStation (this);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wifi/cara-wifi-manager.h	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,91 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Federico Maguolo <maguolof@dei.unipd.it>
+ */
+#ifndef CARA_WIFI_MANAGER_H
+#define CARA_WIFI_MANAGER_H
+
+#include "wifi-remote-station-manager.h"
+
+namespace ns3 {
+
+/**
+ * \brief implement the CARA rate control algorithm
+ *
+ * Implement the CARA algorithm from:
+ * J. Kim, S. Kim, S. Choi, and D. Qiao. 
+ * "CARA: Collision-Aware Rate Adaptation for IEEE 802.11 WLANs."
+ *
+ * Originally implemented by Federico Maguolo for a very early 
+ * prototype version of ns-3.
+ */
+class CaraWifiManager : public WifiRemoteStationManager 
+{
+public:
+  static TypeId GetTypeId (void);
+  CaraWifiManager ();
+  virtual ~CaraWifiManager ();
+
+private:
+  friend class CaraWifiRemoteStation;
+  virtual class WifiRemoteStation *CreateStation (void);
+  uint32_t m_timerTimeout;
+  uint32_t m_successThreshold;
+  uint32_t m_failureThreshold;
+  uint32_t m_probeThreshold;
+};
+
+
+class CaraWifiRemoteStation : public WifiRemoteStation
+{
+public:
+  CaraWifiRemoteStation (Ptr<CaraWifiManager> manager);
+  virtual ~CaraWifiRemoteStation ();
+
+private:
+  virtual Ptr<WifiRemoteStationManager> GetManager (void) const;
+  virtual void DoReportRtsFailed (void);
+  virtual void DoReportDataFailed (void);
+  virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  virtual void DoReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  virtual void DoReportFinalRtsFailed (void);
+  virtual void DoReportFinalDataFailed (void);
+  virtual void DoReportRxOk (double rxSnr, WifiMode txMode);
+  virtual WifiMode DoGetDataMode (uint32_t size);
+  virtual WifiMode DoGetRtsMode (void);
+
+  virtual bool NeedRts (Ptr<const Packet> packet);
+
+  uint32_t m_timer;
+  uint32_t m_success;
+  uint32_t m_failed;
+  
+  uint32_t m_rate;
+  
+  Ptr<CaraWifiManager> m_manager;
+  
+  uint32_t GetMaxRate (void);
+  uint32_t GetMinRate (void);
+
+  bool NeedNormalFallback (void);
+  
+};
+
+} // namespace ns3
+
+#endif /* CARA_WIFI_MANAGER_H */
--- a/src/devices/wifi/dcf-manager-test.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/dcf-manager-test.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1,4 +1,22 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifdef RUN_SELF_TESTS
 
 #include "ns3/test.h"
--- a/src/devices/wifi/dcf-manager.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/dcf-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1,4 +1,22 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 
 #include "ns3/assert.h"
 #include "ns3/log.h"
--- a/src/devices/wifi/interference-helper.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/interference-helper.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #include "interference-helper.h"
 #include "wifi-phy.h"
 #include "error-rate-model.h"
@@ -137,15 +156,15 @@
 }
 
 void 
-InterferenceHelper::SetNoiseFloorW (double noiseFloor)
+InterferenceHelper::SetNoiseFigure (double value)
 {
-  m_noiseFloorW = noiseFloor;
+  m_noiseFigure = value;
 }
 
 double 
-InterferenceHelper::GetNoiseFloorW (void) const
+InterferenceHelper::GetNoiseFigure (void) const
 {
-  return m_noiseFloorW;
+  return m_noiseFigure;
 }
 
 void 
@@ -260,9 +279,10 @@
 {
   // thermal noise at 290K in J/s = W
   static const double BOLTZMANN = 1.3803e-23;
+  // Nt is the power of thermal noise in W
   double Nt = BOLTZMANN * 290.0 * mode.GetBandwidth ();
-  // receiver noise Floor (W)
-  double noiseFloor = m_noiseFloorW * Nt;
+  // receiver noise Floor (W) which accounts for thermal noise and non-idealities of the receiver
+  double noiseFloor = m_noiseFigure * Nt;
   double noise = noiseFloor + noiseInterference;
   double snr = signal / noise;
   return snr;
--- a/src/devices/wifi/interference-helper.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/interference-helper.h	Fri Apr 17 12:33:17 2009 -0700
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifndef INTERFERENCE_HELPER_H
 #define INTERFERENCE_HELPER_H
 
@@ -50,10 +69,10 @@
   ~InterferenceHelper ();
 
   void Configure80211aParameters (void);
-  void SetNoiseFloorW (double noiseFloor);
+  void SetNoiseFigure (double value);
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
 
-  double GetNoiseFloorW (void) const;
+  double GetNoiseFigure (void) const;
   Ptr<ErrorRateModel> GetErrorRateModel (void) const;
 
 
@@ -99,7 +118,7 @@
   WifiMode m_shortPlcpHeaderMode;
   uint32_t m_plcpHeaderLength;
   Time m_maxPacketDuration;
-  double m_noiseFloorW;
+  double m_noiseFigure; /**< noise figure (linear) */
   Events m_events;
   bool m_80211a;
   Ptr<ErrorRateModel> m_errorRateModel;
--- a/src/devices/wifi/rraa-wifi-manager.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/rraa-wifi-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -29,6 +29,8 @@
 NS_LOG_COMPONENT_DEFINE ("RraaWifiManager");
 
 namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED(RraaWifiManager);
   
 RraaWifiRemoteStation::RraaWifiRemoteStation (Ptr<RraaWifiManager> stations)
   : m_stations (stations)
@@ -188,7 +190,7 @@
 TypeId 
 RraaWifiManager::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("RraaWifiManager")
+  static TypeId tid = TypeId ("ns3::RraaWifiManager")
     .SetParent<WifiRemoteStationManager> ()
     .AddConstructor<RraaWifiManager> ()
     .AddAttribute ("Basic",
--- a/src/devices/wifi/wifi-mode.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-mode.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -87,6 +87,12 @@
 std::string 
 WifiMode::GetUniqueName (void) const
 {
+  // needed for ostream printing of the invalid mode
+  if (m_uid == 0)
+    {
+      return "Invalid-WifiMode";
+    }
+
   struct WifiModeFactory::WifiModeItem *item = WifiModeFactory::GetFactory ()->Get (m_uid);
   return item->uniqueUid;
 }
--- a/src/devices/wifi/wifi-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -137,16 +137,6 @@
 }
 
 void 
-WifiNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-std::string 
-WifiNetDevice::GetName(void) const
-{
-  return m_name;
-}
-void 
 WifiNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/devices/wifi/wifi-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -75,8 +75,6 @@
 
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -123,7 +121,6 @@
   TracedCallback<Ptr<const Packet>, Mac48Address> m_txLogger;
 
   uint32_t m_ifIndex;
-  std::string m_name;
   bool m_linkUp;
   Callback<void> m_linkChange;
   mutable uint16_t m_mtu;
--- a/src/devices/wifi/wifi-phy-test.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-phy-test.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #include "wifi-net-device.h"
 #include "yans-wifi-channel.h"
 #include "yans-wifi-phy.h"
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -97,7 +97,7 @@
 WifiMode 
 NonUnicastWifiRemoteStation::DoGetDataMode (uint32_t size)
 {
-  WifiMode mode = m_stations->GetBasicMode (0);
+  WifiMode mode = m_stations->GetNonUnicastMode ();
   NS_LOG_DEBUG ("non-unicast size="<<size<<", mode="<<mode);
   return mode;
 }
@@ -155,6 +155,10 @@
                    UintegerValue (1500),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
                    MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("NonUnicastMode", "Wifi mode used for non-unicast transmissions.",
+                   WifiModeValue (),
+                   MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode),
+                   MakeWifiModeChecker ())
     ;
   return tid;
 }
@@ -305,6 +309,14 @@
 {
   return m_isLowLatency;
 }
+WifiMode
+WifiRemoteStationManager::GetNonUnicastMode (void) const
+{
+  if (m_nonUnicastMode == WifiMode ())
+    return GetBasicMode(0);
+  else
+    return m_nonUnicastMode;
+}
 
 } // namespace ns3
 
--- a/src/devices/wifi/wifi-remote-station-manager.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Fri Apr 17 12:33:17 2009 -0700
@@ -80,6 +80,8 @@
 
   bool IsLowLatency (void) const;
 
+  WifiMode GetNonUnicastMode (void) const;
+
   WifiRemoteStation *Lookup (Mac48Address address);
   WifiRemoteStation *LookupNonUnicast (void);
 protected:
@@ -97,6 +99,7 @@
   uint32_t m_maxSlrc;
   uint32_t m_rtsCtsThreshold;
   uint32_t m_fragmentationThreshold;
+  WifiMode m_nonUnicastMode;
 };
 
 } // namespace ns3
@@ -259,12 +262,9 @@
   WifiMode GetAckMode (WifiMode dataMode);
 
 private:
-  typedef std::vector<WifiMode> SupportedModes;
   virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
   virtual WifiMode DoGetDataMode (uint32_t size) = 0;
   virtual WifiMode DoGetRtsMode (void) = 0;
-  uint32_t GetNFragments (Ptr<const Packet> packet);
-protected:
   virtual void DoReportRtsFailed (void) = 0;
   virtual void DoReportDataFailed (void) = 0;
   virtual void DoReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr) = 0;
@@ -272,9 +272,12 @@
   virtual void DoReportFinalRtsFailed (void) = 0;
   virtual void DoReportFinalDataFailed (void) = 0;
   virtual void DoReportRxOk (double rxSnr, WifiMode txMode) = 0;
+protected:
   uint32_t GetNSupportedModes (void) const;
   WifiMode GetSupportedMode (uint32_t i) const;
 private:
+  typedef std::vector<WifiMode> SupportedModes;
+  uint32_t GetNFragments (Ptr<const Packet> packet);
   bool IsIn (WifiMode mode) const;
   WifiMode GetControlAnswerMode (WifiMode reqMode);
   enum {
--- a/src/devices/wifi/wifi-test.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wifi-test.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -1,3 +1,22 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as 
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 #ifdef RUN_SELF_TESTS
 
 #include "wifi-net-device.h"
--- a/src/devices/wifi/wscript	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/wscript	Fri Apr 17 12:33:17 2009 -0700
@@ -42,6 +42,8 @@
         'amrr-wifi-manager.cc',
         'onoe-wifi-manager.cc',
         'rraa-wifi-manager.cc',
+        'aarfcd-wifi-manager.cc',
+        'cara-wifi-manager.cc',
         'constant-rate-wifi-manager.cc',
         'wifi-test.cc',
         ]
--- a/src/devices/wifi/yans-wifi-phy.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/yans-wifi-phy.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -93,11 +93,17 @@
                    MakeDoubleAccessor (&YansWifiPhy::SetTxPowerStart, 
                                        &YansWifiPhy::GetTxPowerStart),
                    MakeDoubleChecker<double> ())
-    .AddAttribute ("RxNoise",
-                   "Ratio of energy lost by receiver (dB).",
+    .AddAttribute ("RxNoiseFigure",
+                   "Loss (dB) in the Signal-to-Noise-Ratio due to non-idealities in the receiver."
+                   " According to Wikipedia (http://en.wikipedia.org/wiki/Noise_figure), this is "
+                   "\"the difference in decibels (dB) between"
+                   " the noise output of the actual receiver to the noise output of an "
+                   " ideal receiver with the same overall gain and bandwidth when the receivers "
+                   " are connected to sources at the standard noise temperature T0 (usually 290 K)\"."
+                   " For",
                    DoubleValue (7),
-                   MakeDoubleAccessor (&YansWifiPhy::SetRxNoise,
-                                       &YansWifiPhy::GetRxNoise),
+                   MakeDoubleAccessor (&YansWifiPhy::SetRxNoiseFigure,
+                                       &YansWifiPhy::GetRxNoiseFigure),
                    MakeDoubleChecker<double> ())
     .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes"
                    " and some PHY-specific constants.",
@@ -155,10 +161,10 @@
 
 
 void 
-YansWifiPhy::SetRxNoise (double db)
+YansWifiPhy::SetRxNoiseFigure (double noiseFigureDb)
 {
-  NS_LOG_FUNCTION (this << db);
-  m_interference.SetNoiseFloorW (DbToRatio (db));
+  NS_LOG_FUNCTION (this << noiseFigureDb);
+  m_interference.SetNoiseFigure (DbToRatio (noiseFigureDb));
 }
 void 
 YansWifiPhy::SetTxPowerStart (double start)
@@ -219,9 +225,9 @@
 }
 
 double 
-YansWifiPhy::GetRxNoise (void) const
+YansWifiPhy::GetRxNoiseFigure (void) const
 {
-  return RatioToDb (m_interference.GetNoiseFloorW ());
+  return RatioToDb (m_interference.GetNoiseFigure ());
 }
 double 
 YansWifiPhy::GetTxPowerStart (void) const
--- a/src/devices/wifi/yans-wifi-phy.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/devices/wifi/yans-wifi-phy.h	Fri Apr 17 12:33:17 2009 -0700
@@ -75,7 +75,7 @@
                            WifiPreamble preamble);
 
   void SetStandard (enum WifiPhyStandard standard);
-  void SetRxNoise (double ratio);
+  void SetRxNoiseFigure (double noiseFigureDb);
   void SetTxPowerStart (double start);
   void SetTxPowerEnd (double end);
   void SetNTxPower (uint32_t n);
@@ -86,7 +86,7 @@
   void SetErrorRateModel (Ptr<ErrorRateModel> rate);
   void SetDevice (Ptr<Object> device);
   void SetMobility (Ptr<Object> mobility);
-  double GetRxNoise (void) const;
+  double GetRxNoiseFigure (void) const;
   double GetTxGain (void) const;
   double GetRxGain (void) const;
   double GetEdThreshold (void) const;
--- a/src/helper/olsr-helper.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/helper/olsr-helper.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -18,7 +18,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "olsr-helper.h"
-#include "ns3/olsr-agent.h"
+#include "ns3/olsr-routing-protocol.h"
 #include "ns3/node-list.h"
 #include "ns3/names.h"
 
@@ -26,7 +26,7 @@
 
 OlsrHelper::OlsrHelper ()
 {
-  m_agentFactory.SetTypeId ("ns3::olsr::AgentImpl");
+  m_agentFactory.SetTypeId ("ns3::olsr::RoutingProtocol");
 }
 
 void 
@@ -63,15 +63,17 @@
 void 
 OlsrHelper::Install (Ptr<Node> node)
 {
-  if (node->GetObject<olsr::Agent> () != 0)
+  if (node->GetObject<olsr::RoutingProtocol> () != 0)
     {
       NS_FATAL_ERROR ("OlsrHelper::Install(): Aggregating "
-         "an Olsr Agent to a node with an existing Olsr Agent");
+         "an Olsr Agent to a node with an existing Olsr RoutingProtocol");
       return;
     }
-  Ptr<olsr::Agent> agent = m_agentFactory.Create<olsr::Agent> ();
+  Ptr<olsr::RoutingProtocol> agent = m_agentFactory.Create<olsr::RoutingProtocol> ();
+  node->AggregateObject (agent);
+  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+  ipv4->AddRoutingProtocol (agent, 10);
   agent->SetNode (node);
-  node->AggregateObject (agent);
   agent->Start ();
 }
 void 
--- a/src/internet-stack/ipv4-l3-protocol.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -150,7 +150,13 @@
 Ipv4L3Protocol::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
-  for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+ 
+  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)
     {
       *i = 0;
     }
--- a/src/mobility/hierarchical-mobility-model.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/mobility/hierarchical-mobility-model.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -52,15 +52,46 @@
 void 
 HierarchicalMobilityModel::SetChild (Ptr<MobilityModel> model)
 {
+  Ptr<MobilityModel> oldChild = m_child;
+  Vector pos;
+  if (m_child)
+    {
+      pos = GetPosition ();
+      m_child->TraceDisconnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+    }
   m_child = model;
   m_child->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+
+  // if we had a child before, then we had a valid position before;
+  // try to preserve the old absolute position.
+  if (oldChild)
+    {
+      SetPosition (pos);
+    }
 }
 
 void 
 HierarchicalMobilityModel::SetParent (Ptr<MobilityModel> model)
 {
+  Vector pos;
+  if (m_child)
+    {
+      pos = GetPosition ();
+    }
+  if (m_parent)
+    {
+      m_parent->TraceDisconnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+    }
   m_parent = model;
-  m_parent->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+  if (m_parent)
+    {
+      m_parent->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+    }
+  // try to preserve the old position across parent changes
+  if (m_child)
+    {
+      SetPosition (pos);
+    }
 }
 
 
@@ -79,6 +110,10 @@
 Vector
 HierarchicalMobilityModel::DoGetPosition (void) const
 {
+  if (!m_parent)
+    {
+      return m_child->GetPosition ();
+    }
   Vector parentPosition = m_parent->GetPosition ();
   Vector childPosition = m_child->GetPosition ();
   return Vector (parentPosition.x + childPosition.x,
@@ -88,27 +123,41 @@
 void 
 HierarchicalMobilityModel::DoSetPosition (const Vector &position)
 {
-  if (m_parent == 0 || m_child == 0)
+  if (m_child == 0)
     {
       return;
     }
   // This implementation of DoSetPosition is really an arbitraty choice.
   // anything else would have been ok.
-  Vector parentPosition = m_parent->GetPosition ();
-  Vector childPosition (position.x - parentPosition.x,
-			  position.y - parentPosition.y,
-			  position.z - parentPosition.z);
-  m_child->SetPosition (childPosition);
+  if (m_parent)
+    {
+      Vector parentPosition = m_parent->GetPosition ();
+      Vector childPosition (position.x - parentPosition.x,
+                            position.y - parentPosition.y,
+                            position.z - parentPosition.z);
+      m_child->SetPosition (childPosition);
+    }
+  else
+    {
+      m_child->SetPosition (position);
+    }
 }
 Vector
 HierarchicalMobilityModel::DoGetVelocity (void) const
 {
-  Vector parentSpeed = m_parent->GetVelocity ();
-  Vector childSpeed = m_child->GetVelocity ();
-  Vector speed (parentSpeed.x + childSpeed.x,
-               parentSpeed.y + childSpeed.y,
-               parentSpeed.z + childSpeed.z);
-  return speed;
+  if (m_parent)
+    {
+      Vector parentSpeed = m_parent->GetVelocity ();
+      Vector childSpeed = m_child->GetVelocity ();
+      Vector speed (parentSpeed.x + childSpeed.x,
+                    parentSpeed.y + childSpeed.y,
+                    parentSpeed.z + childSpeed.z);
+      return speed;
+    }
+  else
+    {
+      return m_child->GetVelocity ();
+    }
 }
 
 void 
--- a/src/mobility/hierarchical-mobility-model.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/mobility/hierarchical-mobility-model.h	Fri Apr 17 12:33:17 2009 -0700
@@ -27,8 +27,31 @@
 /**
  * \brief a hierachical mobility model.
  * 
- * This model allows you to specify the position of a
- * child object relative to a parent object.
+ * This model allows you to specify the position of a child object
+ * relative to a parent object.
+ * 
+ * Basically this is a mobility model that combines two other mobility
+ * models: a "parent" model and a "child" model.  The position of the
+ * hierarchical model is always the vector sum of the parent + child
+ * positions, so that if the parent model "moves", then this model
+ * will report an equal relative movement.  Useful, for instance, if
+ * you want to simulate a node inside another node that moves, such as
+ * a vehicle.
+ *
+ * Setting the position on this model is always done using world
+ * absolute coordinates, and it changes only the child mobility model
+ * position, never the parent.  The child mobility model always uses a
+ * coordinate sytem relative to the parent model position.
+ *
+ * @note: as a special case, the parent model may be NULL, which is
+ * semantically equivalent to having a ConstantPositionMobilityModel
+ * as parent positioned at origin (0,0,0).  In other words, setting
+ * the parent model to NULL makes the child model and the hierarchical
+ * model start using world absolute coordinates.
+ *
+ * @warning: changing the parent/child mobility models in the middle
+ * of a simulation will probably not play very well with the
+ * ConfigStore APIs, so do this only if you know what you are doing.
  */
 class HierarchicalMobilityModel : public MobilityModel
 {
@@ -52,14 +75,26 @@
    * position by the child mobility model.
    */
   Ptr<MobilityModel> GetParent (void) const;
+  /**
+   * Sets the child mobility model to a new one.  If before there
+   * already existed a child model, then the child mobility model
+   * current position is also modified to ensure that the composite
+   * position is preserved.
+   */
+  void SetChild (Ptr<MobilityModel> model);
+  /**
+   * Sets the parent mobility model to a new one.  If before there
+   * already existed a child model, then the child mobility model
+   * current position is also modified to ensure that the composite
+   * position is preserved.
+   */
+  void SetParent (Ptr<MobilityModel> model);
   
 private:
   virtual Vector DoGetPosition (void) const;
   virtual void DoSetPosition (const Vector &position);
   virtual Vector DoGetVelocity (void) const;
 
-  void SetChild (Ptr<MobilityModel> model);
-  void SetParent (Ptr<MobilityModel> model);
   void ParentChanged (Ptr<const MobilityModel> model);
   void ChildChanged (Ptr<const MobilityModel> model);
 
--- a/src/mobility/random-waypoint-mobility-model.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/mobility/random-waypoint-mobility-model.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -45,7 +45,7 @@
                    RandomVariableValue (ConstantVariable (2.0)),
                    MakeRandomVariableAccessor (&RandomWaypointMobilityModel::m_pause),
                    MakeRandomVariableChecker ())
-    .AddAttribute ("Position",
+    .AddAttribute ("PositionAllocator",
                    "The position model used to pick a destination point.",
                    PointerValue (),
                    MakePointerAccessor (&RandomWaypointMobilityModel::m_position),
--- a/src/node/channel.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/channel.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -35,34 +35,14 @@
 }
 
 Channel::Channel ()
-  : m_name("Channel")
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
-Channel::Channel (std::string name)
-  : m_name(name)
-{
-  NS_LOG_FUNCTION (this << name);
-}
 
 Channel::~Channel ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
-  void
-Channel::SetName(std::string name)
-{
-  NS_LOG_FUNCTION (this << name);
-  m_name = name;
-}
-
-  std::string
-Channel::GetName(void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_name;
-}
-
 } // namespace ns3
--- a/src/node/channel.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/channel.h	Fri Apr 17 12:33:17 2009 -0700
@@ -43,12 +43,8 @@
   static TypeId GetTypeId (void);
 
   Channel ();
-  Channel (std::string name);
   virtual ~Channel ();
 
-  void SetName(std::string);
-  std::string GetName(void);
-
   /**
    * \returns the number of NetDevices connected to this Channel.
    *
@@ -63,10 +59,8 @@
    */
   virtual Ptr<NetDevice> GetDevice (uint32_t i) const = 0;
 
-private:
-  std::string   m_name;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* NS3_CHANNEL_H */
--- a/src/node/net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -68,14 +68,6 @@
   virtual ~NetDevice();
 
   /**
-   * \param name name of the device (e.g. "eth0")
-   */
-  virtual void SetName(const std::string name) = 0;
-  /**
-   * \return name name of the device (e.g. "eth0")
-   */
-  virtual std::string GetName(void) const = 0;
-  /**
    * \param index ifIndex of the device 
    */
   virtual void SetIfIndex(const uint32_t index) = 0;
--- a/src/node/node.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/node.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -225,7 +225,7 @@
 Node::PromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                 const Address &from, const Address &to, NetDevice::PacketType packetType)
 {
-  NS_LOG_FUNCTION(device->GetName ());
+  NS_LOG_FUNCTION(this);
   return ReceiveFromDevice (device, packet, protocol, from, to, packetType, true);
 }
 
@@ -233,7 +233,7 @@
 Node::NonPromiscReceiveFromDevice (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol,
                                    const Address &from)
 {
-  NS_LOG_FUNCTION(device->GetName ());
+  NS_LOG_FUNCTION(this);
   return ReceiveFromDevice (device, packet, protocol, from, from, NetDevice::PacketType (0), false);
 }
 
@@ -242,8 +242,7 @@
                          const Address &from, const Address &to, NetDevice::PacketType packetType, bool promiscuous)
 {
   NS_LOG_DEBUG("Node " << GetId () << " ReceiveFromDevice:  dev "
-               << device->GetIfIndex () << " ("
-               << device->GetName () << " type " << device->GetInstanceTypeId ().GetName ()
+               << device->GetIfIndex () << " (type=" << device->GetInstanceTypeId ().GetName ()
                << ") Packet UID " << packet->GetUid ());
   bool found = false;
 
--- a/src/node/simple-net-device.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/simple-net-device.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -38,7 +38,6 @@
   : m_channel (0),
     m_node (0),
     m_mtu (0xffff),
-    m_name (""),
     m_ifIndex (0)
 {}
 
@@ -84,16 +83,6 @@
 }
 
 void 
-SimpleNetDevice::SetName(const std::string name)
-{
-  m_name = name;
-}
-std::string 
-SimpleNetDevice::GetName(void) const
-{
-  return m_name;
-}
-void 
 SimpleNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
--- a/src/node/simple-net-device.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/simple-net-device.h	Fri Apr 17 12:33:17 2009 -0700
@@ -46,8 +46,6 @@
   void SetAddress (Mac48Address address);
 
   // inherited from NetDevice base class.
-  virtual void SetName(const std::string name);
-  virtual std::string GetName(void) const;
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
   virtual Ptr<Channel> GetChannel (void) const;
@@ -82,7 +80,6 @@
   NetDevice::PromiscReceiveCallback m_promiscCallback;
   Ptr<Node> m_node;
   uint16_t m_mtu;
-  std::string m_name;
   uint32_t m_ifIndex;
   Mac48Address m_address;
 };
--- a/src/node/socket.cc	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/socket.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -252,6 +252,19 @@
     }
 }
 
+void 
+Socket::DoDispose (void)
+{
+  
+  m_connectionSucceeded = MakeNullCallback<void,Ptr<Socket> > ();
+  m_connectionFailed = MakeNullCallback<void,Ptr<Socket> > ();
+  m_connectionRequest = MakeNullCallback<bool,Ptr<Socket>, const Address &> ();
+  m_newConnectionCreated = MakeNullCallback<void,Ptr<Socket>, const Address &> ();
+  m_dataSent = MakeNullCallback<void,Ptr<Socket>, uint32_t> ();
+  m_sendCb = MakeNullCallback<void,Ptr<Socket>, uint32_t> ();
+  m_receivedData = MakeNullCallback<void,Ptr<Socket> > ();
+}
+
 /***************************************************************
  *           Socket Tags
  ***************************************************************/
--- a/src/node/socket.h	Sun Apr 12 22:41:33 2009 -0700
+++ b/src/node/socket.h	Fri Apr 17 12:33:17 2009 -0700
@@ -499,6 +499,7 @@
   void NotifyDataSent (uint32_t size);
   void NotifySend (uint32_t spaceAvailable);
   void NotifyDataRecv (void);
+  virtual void DoDispose (void);
 private:
   Callback<void, Ptr<Socket> >   m_connectionSucceeded;
   Callback<void, Ptr<Socket> >   m_connectionFailed;
--- a/src/routing/olsr/olsr-agent-impl.cc	Sun Apr 12 22:41:33 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2500 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2004 Francisco J. Ros 
- * Copyright (c) 2007 INESC Porto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: Francisco J. Ros  <fjrm@dif.um.es>
- *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
- */
-
-
-///
-/// \file	OLSR.cc
-/// \brief	Implementation of OLSR agent and related classes.
-///
-/// This is the main file of this software because %OLSR's behaviour is
-/// implemented here.
-///
-
-#define NS_LOG_APPEND_CONTEXT                                   \
-  if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
-
-
-#include "olsr-agent-impl.h"
-#include "ns3/socket-factory.h"
-#include "ns3/udp-socket-factory.h"
-#include "ns3/simulator.h"
-#include "ns3/log.h"
-#include "ns3/random-variable.h"
-#include "ns3/inet-socket-address.h"
-#include "ns3/boolean.h"
-#include "ns3/uinteger.h"
-#include "ns3/enum.h"
-#include "ns3/trace-source-accessor.h"
-
-/********** Useful macros **********/
-
-///
-/// \brief Gets the delay between a given time and the current time.
-///
-/// If given time is previous to the current one, then this macro returns
-/// a number close to 0. This is used for scheduling events at a certain moment.
-///
-#define DELAY(time) (((time) < (Simulator::Now ())) ? Seconds (0.000001) : \
-                     (time - Simulator::Now () + Seconds (0.000001)))
-
-
-
-///
-/// \brief Period at which a node must cite every link and every neighbor.
-///
-/// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
-///
-#define OLSR_REFRESH_INTERVAL	Seconds (2)
-
-
-/********** Holding times **********/
-
-/// Neighbor holding time.
-#define OLSR_NEIGHB_HOLD_TIME	(Scalar (3) * OLSR_REFRESH_INTERVAL)
-/// Top holding time.
-#define OLSR_TOP_HOLD_TIME	(Scalar (3) * m_tcInterval)
-/// Dup holding time.
-#define OLSR_DUP_HOLD_TIME	Seconds (30)
-/// MID holding time.
-#define OLSR_MID_HOLD_TIME	(Scalar (3) * m_midInterval)
-
-
-/********** Link types **********/
-
-/// Unspecified link type.
-#define OLSR_UNSPEC_LINK	0
-/// Asymmetric link type.
-#define OLSR_ASYM_LINK		1
-/// Symmetric link type.
-#define OLSR_SYM_LINK		2
-/// Lost link type.
-#define OLSR_LOST_LINK		3
-
-/********** Neighbor types **********/
-
-/// Not neighbor type.
-#define OLSR_NOT_NEIGH		0
-/// Symmetric neighbor type.
-#define OLSR_SYM_NEIGH		1
-/// Asymmetric neighbor type.
-#define OLSR_MPR_NEIGH		2
-
-
-/********** Willingness **********/
-
-/// Willingness for forwarding packets from other nodes: never.
-#define OLSR_WILL_NEVER		0
-/// Willingness for forwarding packets from other nodes: low.
-#define OLSR_WILL_LOW		1
-/// Willingness for forwarding packets from other nodes: medium.
-#define OLSR_WILL_DEFAULT	3
-/// Willingness for forwarding packets from other nodes: high.
-#define OLSR_WILL_HIGH		6
-/// Willingness for forwarding packets from other nodes: always.
-#define OLSR_WILL_ALWAYS	7
-
-
-/********** Miscellaneous constants **********/
-
-/// Maximum allowed jitter.
-#define OLSR_MAXJITTER		(m_helloInterval.GetSeconds () / 4)
-/// Maximum allowed sequence number.
-#define OLSR_MAX_SEQ_NUM	65535
-/// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
-#define JITTER (Seconds (UniformVariable().GetValue (0, OLSR_MAXJITTER)))
-
-
-#define OLSR_PORT_NUMBER 698
-/// Maximum number of messages per packet.
-#define OLSR_MAX_MSGS		64
-
-/// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
-#define OLSR_MAX_HELLOS		12
-
-/// Maximum number of addresses advertised on a message.
-#define OLSR_MAX_ADDRS		64
-
-
-namespace ns3 {
-namespace olsr {
-
-NS_LOG_COMPONENT_DEFINE ("OlsrAgent");
-
-
-/********** OLSR class **********/
-
-NS_OBJECT_ENSURE_REGISTERED (AgentImpl);
-
-TypeId 
-AgentImpl::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::olsr::AgentImpl")
-    .SetParent<Agent> ()
-    .AddConstructor<AgentImpl> ()
-    .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
-                   TimeValue (Seconds (2)),
-                   MakeTimeAccessor (&AgentImpl::m_helloInterval),
-                   MakeTimeChecker ())
-    .AddAttribute ("TcInterval", "TC messages emission interval.",
-                   TimeValue (Seconds (5)),
-                   MakeTimeAccessor (&AgentImpl::m_tcInterval),
-                   MakeTimeChecker ())
-    .AddAttribute ("MidInterval", "MID messages emission interval.  Normally it is equal to TcInterval.",
-                   TimeValue (Seconds (5)),
-                   MakeTimeAccessor (&AgentImpl::m_midInterval),
-                   MakeTimeChecker ())
-    .AddAttribute ("Willingness", "Willingness of a node to carry and forward traffic for other nodes.",
-                   EnumValue (OLSR_WILL_DEFAULT),
-                   MakeEnumAccessor (&AgentImpl::m_willingness),
-                   MakeEnumChecker (OLSR_WILL_NEVER, "never",
-                                    OLSR_WILL_LOW, "low",
-                                    OLSR_WILL_DEFAULT, "default",
-                                    OLSR_WILL_HIGH, "high",
-                                    OLSR_WILL_ALWAYS, "always"))
-    .AddTraceSource ("Rx", "Receive OLSR packet.",
-                     MakeTraceSourceAccessor (&AgentImpl::m_rxPacketTrace))
-    .AddTraceSource ("Tx", "Send OLSR packet.",
-                     MakeTraceSourceAccessor (&AgentImpl::m_txPacketTrace))
-    .AddTraceSource ("RoutingTableChanged", "The OLSR routing table has changed.",
-		     MakeTraceSourceAccessor (&AgentImpl::m_routingTableChanged))
-    ;
-  return tid;
-}
-
-
-AgentImpl::AgentImpl ()
-  :
-  m_helloTimer (Timer::CANCEL_ON_DESTROY),
-  m_tcTimer (Timer::CANCEL_ON_DESTROY),
-  m_midTimer (Timer::CANCEL_ON_DESTROY)
-{}
-
-AgentImpl::~AgentImpl ()
-{}
-
-void
-AgentImpl::SetNode (Ptr<Node> node)
-{
-  NS_LOG_DEBUG ("Created olsr::AgentImpl");
-  m_helloTimer.SetFunction (&AgentImpl::HelloTimerExpire, this);
-  m_tcTimer.SetFunction (&AgentImpl::TcTimerExpire, this);
-  m_midTimer.SetFunction (&AgentImpl::MidTimerExpire, this);
-  m_queuedMessagesTimer.SetFunction (&AgentImpl::SendQueuedMessages, this);
-
-  m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
-  m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
-  m_ansn = OLSR_MAX_SEQ_NUM;
-
-  m_linkTupleTimerFirstTime = true;
-
-  m_ipv4 = node->GetObject<Ipv4> ();
-  NS_ASSERT (m_ipv4);
-}
-
-void AgentImpl::DoDispose ()
-{
-  m_ipv4 = 0;
-
-  for (std::map< Ptr<Socket>, Ipv4Address >::iterator iter = m_socketAddresses.begin ();
-       iter != m_socketAddresses.end (); iter++)
-    {
-      iter->first->Dispose ();
-    }
-  m_socketAddresses.clear ();
-
-  if (m_routingTable)
-    {
-      m_routingTable->Dispose ();
-      m_routingTable = 0;
-    }
-
-  Object::DoDispose ();
-}
-
-void AgentImpl::Start ()
-{
-  if (m_mainAddress == Ipv4Address ())
-    {
-      Ipv4Address loopback ("127.0.0.1");
-      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
-        {
-          // Use primary address, if multiple
-          Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
-          if (addr != loopback)
-            {
-              m_mainAddress = addr;
-              break;
-            }
-        }
-
-      NS_ASSERT (m_mainAddress != Ipv4Address ());
-    }
-
-  NS_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress);
-
-  m_routingTable = CreateObject<RoutingTable> ();
-  m_routingTable->SetIpv4 (m_ipv4);
-  m_routingTable->SetMainAddress (m_mainAddress);
-  // Add OLSR as routing protocol, with slightly higher priority than
-  // static routing.
-  m_ipv4->AddRoutingProtocol (m_routingTable, 10);
-  
-  Ipv4Address loopback ("127.0.0.1");
-  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
-    {
-      Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
-      if (addr == loopback)
-        continue;
-
-      if (addr != m_mainAddress)
-        {
-          // Create never expiring interface association tuple entries for our
-          // own network interfaces, so that GetMainAddress () works to
-          // translate the node's own interface addresses into the main address.
-          IfaceAssocTuple tuple;
-          tuple.ifaceAddr = addr;
-          tuple.mainAddr = m_mainAddress;
-          AddIfaceAssocTuple (tuple);
-          NS_ASSERT (GetMainAddress (addr) == m_mainAddress);
-        }
-
-      // Create a socket to listen only on this interface
-      Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), 
-        UdpSocketFactory::GetTypeId()); 
-      socket->SetRecvCallback (MakeCallback (&AgentImpl::RecvOlsr,  this));
-      if (socket->Bind (InetSocketAddress (addr, OLSR_PORT_NUMBER)))
-        {
-          NS_FATAL_ERROR ("Failed to bind() OLSR receive socket");
-        }
-      socket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER));
-      m_socketAddresses[socket] = addr;
-    }
-
-  HelloTimerExpire ();
-  TcTimerExpire ();
-  MidTimerExpire ();
-
-  NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started");
-}
-
-void AgentImpl::SetMainInterface (uint32_t interface)
-{
-  m_mainAddress = m_ipv4->GetAddress (interface, 0).GetLocal ();
-}
-
-
-//
-// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
-void
-AgentImpl::RecvOlsr (Ptr<Socket> socket)
-{
-  Ptr<Packet> receivedPacket;
-  Address sourceAddress;
-  receivedPacket = socket->RecvFrom (sourceAddress);
-
-  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
-  Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
-  Ipv4Address receiverIfaceAddr = m_socketAddresses[socket];
-  NS_ASSERT (receiverIfaceAddr != Ipv4Address ());
-  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet from "
-                << senderIfaceAddr << " to " << receiverIfaceAddr);
-  
-  // All routing messages are sent from and to port RT_PORT,
-  // so we check it.
-  NS_ASSERT (inetSourceAddr.GetPort () == OLSR_PORT_NUMBER);
-  
-  Ptr<Packet> packet = receivedPacket;
-
-  olsr::PacketHeader olsrPacketHeader;
-  packet->RemoveHeader (olsrPacketHeader);
-  NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSerializedSize ());
-  uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSerializedSize ();
-
-  MessageList messages;
-  
-  while (sizeLeft)
-    {
-      MessageHeader messageHeader;
-      if (packet->RemoveHeader (messageHeader) == 0)
-        NS_ASSERT (false);
-      
-      sizeLeft -= messageHeader.GetSerializedSize ();
-
-      NS_LOG_DEBUG ("Olsr Msg received with type "
-                << std::dec << int (messageHeader.GetMessageType ())
-                << " TTL=" << int (messageHeader.GetTimeToLive ())
-                << " origAddr=" << messageHeader.GetOriginatorAddress ());
-      messages.push_back (messageHeader);
-    }
-
-  m_rxPacketTrace (olsrPacketHeader, messages);
-
-  for (MessageList::const_iterator messageIter = messages.begin ();
-       messageIter != messages.end (); messageIter++)
-    {
-      const MessageHeader &messageHeader = *messageIter;
-      // If ttl is less than or equal to zero, or
-      // the receiver is the same as the originator,
-      // the message must be silently dropped
-      if (messageHeader.GetTimeToLive () == 0
-          || messageHeader.GetOriginatorAddress () == m_mainAddress)
-        {
-          packet->RemoveAtStart (messageHeader.GetSerializedSize ()
-                                 - messageHeader.GetSerializedSize ());
-          continue;
-        }
-
-      // If the message has been processed it must not be processed again
-      bool do_forwarding = true;
-      DuplicateTuple *duplicated = m_state.FindDuplicateTuple
-        (messageHeader.GetOriginatorAddress (),
-         messageHeader.GetMessageSequenceNumber ());
-
-      // Get main address of the peer, which may be different from the packet source address
-//       const IfaceAssocTuple *ifaceAssoc = m_state.FindIfaceAssocTuple (inetSourceAddr.GetIpv4 ());
-//       Ipv4Address peerMainAddress;
-//       if (ifaceAssoc != NULL)
-//         {
-//           peerMainAddress = ifaceAssoc->mainAddr;
-//         }
-//       else
-//         {
-//           peerMainAddress = inetSourceAddr.GetIpv4 () ;
-//         }
-      
-      if (duplicated == NULL)
-        {
-          switch (messageHeader.GetMessageType ())
-            {
-            case olsr::MessageHeader::HELLO_MESSAGE:
-              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                            << "s OLSR node " << m_mainAddress
-                            << " received HELLO message of size " << messageHeader.GetSerializedSize ());
-              ProcessHello (messageHeader, receiverIfaceAddr, senderIfaceAddr);
-              break;
-
-            case olsr::MessageHeader::TC_MESSAGE:
-              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                            << "s OLSR node " << m_mainAddress
-                            << " received TC message of size " << messageHeader.GetSerializedSize ());
-              ProcessTc (messageHeader, senderIfaceAddr);
-              break;
-
-            case olsr::MessageHeader::MID_MESSAGE:
-              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                            << "s OLSR node " << m_mainAddress
-                            <<  " received MID message of size " << messageHeader.GetSerializedSize ());
-              ProcessMid (messageHeader, senderIfaceAddr);
-              break;
-
-            default:
-              NS_LOG_DEBUG ("OLSR message type " <<
-                        int (messageHeader.GetMessageType ()) <<
-                        " not implemented");
-            }
-        }
-      else
-        {
-          NS_LOG_DEBUG ("OLSR message is duplicated, not reading it.");
-      
-          // If the message has been considered for forwarding, it should
-          // not be retransmitted again
-          for (std::vector<Ipv4Address>::const_iterator it = duplicated->ifaceList.begin ();
-               it != duplicated->ifaceList.end(); it++)
-            {
-              if (*it == receiverIfaceAddr)
-                {
-                  do_forwarding = false;
-                  break;
-                }
-            }
-        }
-      
-      if (do_forwarding)
-        {
-          // HELLO messages are never forwarded.
-          // TC and MID messages are forwarded using the default algorithm.
-          // Remaining messages are also forwarded using the default algorithm.
-          if (messageHeader.GetMessageType ()  != olsr::MessageHeader::HELLO_MESSAGE)
-            {
-              ForwardDefault (messageHeader, duplicated,
-                              receiverIfaceAddr, inetSourceAddr.GetIpv4 ());
-            }
-        }
-	
-    }
-
-  // After processing all OLSR messages, we must recompute the routing table
-  RoutingTableComputation ();
-}
-
-///
-/// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
-///
-/// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
-/// \return the degree of the node.
-///
-int
-AgentImpl::Degree (NeighborTuple const &tuple)
-{
-  int degree = 0;
-  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
-       it != m_state.GetTwoHopNeighbors ().end (); it++)
-    {
-      TwoHopNeighborTuple const &nb2hop_tuple = *it;
-      if (nb2hop_tuple.neighborMainAddr == tuple.neighborMainAddr)
-        {
-          const NeighborTuple *nb_tuple =
-            m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr);
-          if (nb_tuple == NULL)
-            degree++;
-        }
-    }
-  return degree;
-}
-
-///
-/// \brief Computates MPR set of a node following RFC 3626 hints.
-///
-void
-AgentImpl::MprComputation()
-{
-  NS_LOG_FUNCTION (this);
-  
-  // MPR computation should be done for each interface. See section 8.3.1
-  // (RFC 3626) for details.
-  MprSet mprSet;
-	
-  
-  // N is the subset of neighbors of the node, which are
-  // neighbor "of the interface I"
-  NeighborSet N;
-  for (NeighborSet::const_iterator neighbor = m_state.GetNeighbors ().begin();
-       neighbor != m_state.GetNeighbors ().end (); neighbor++)
-    {
-      if (neighbor->status == NeighborTuple::STATUS_SYM) // I think that we need this check
-        {
-          N.push_back (*neighbor);
-        }
-    }
-	
-  // N2 is the set of 2-hop neighbors reachable from "the interface
-  // I", excluding:
-  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
-  // (ii)  the node performing the computation
-  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
-  //       link to this node on some interface.
-  TwoHopNeighborSet N2;
-  for (TwoHopNeighborSet::const_iterator twoHopNeigh = m_state.GetTwoHopNeighbors ().begin ();
-       twoHopNeigh != m_state.GetTwoHopNeighbors ().end (); twoHopNeigh++)
-    {
-      // excluding:
-      // (ii)  the node performing the computation
-      if (twoHopNeigh->twoHopNeighborAddr == m_mainAddress)
-        {
-          continue;
-        }
-
-      //  excluding:
-      // (i)   the nodes only reachable by members of N with willingness WILL_NEVER      
-      bool ok = false;
-      for (NeighborSet::const_iterator neigh = N.begin ();
-           neigh != N.end (); neigh++)
-        {
-          if (neigh->neighborMainAddr == twoHopNeigh->neighborMainAddr)
-            {
-              if (neigh->willingness == OLSR_WILL_NEVER)
-                {
-                  ok = false;
-                  break;
-                }
-              else
-                {
-                  ok = true;
-                  break;
-                }
-            }
-        }
-      if (!ok)
-        {
-          continue;
-        }
-      
-      // excluding:
-      // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
-      //       link to this node on some interface.
-      for (NeighborSet::const_iterator neigh = N.begin ();
-           neigh != N.end (); neigh++)
-        {
-          if (neigh->neighborMainAddr == twoHopNeigh->twoHopNeighborAddr)
-            {
-              ok = false;
-              break;
-            }
-        }
-
-      if (ok)
-        {
-          N2.push_back (*twoHopNeigh);
-        }
-    }
-
-  NS_LOG_DEBUG ("Size of N2: " << N2.size ());  
-
-  // 1. Start with an MPR set made of all members of N with
-  // N_willingness equal to WILL_ALWAYS
-  for (NeighborSet::const_iterator neighbor = N.begin (); neighbor != N.end (); neighbor++)
-    {
-      if (neighbor->willingness == OLSR_WILL_ALWAYS)
-        {
-          mprSet.insert (neighbor->neighborMainAddr);
-          // (not in RFC but I think is needed: remove the 2-hop
-          // neighbors reachable by the MPR from N2)
-          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
-               twoHopNeigh != N2.end (); )
-            {
-              if (twoHopNeigh->neighborMainAddr == neighbor->neighborMainAddr)
-                {
-                  twoHopNeigh = N2.erase (twoHopNeigh);
-                }
-              else
-                {
-                  twoHopNeigh++;
-                }
-            }
-        }
-    }
-  
-  // 2. Calculate D(y), where y is a member of N, for all nodes in N.
-  // (we do this later)
-	
-  // 3. Add to the MPR set those nodes in N, which are the *only*
-  // nodes to provide reachability to a node in N2.
-  std::set<Ipv4Address> coveredTwoHopNeighbors;
-  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
-    {
-      NeighborSet::const_iterator onlyNeighbor = N.end ();
-      
-      for (NeighborSet::const_iterator neighbor = N.begin ();
-           neighbor != N.end (); neighbor++)
-        {
-          if (neighbor->neighborMainAddr == twoHopNeigh->neighborMainAddr)
-            {
-              if (onlyNeighbor == N.end ())
-                {
-                  onlyNeighbor = neighbor;
-                }
-              else
-                {
-                  onlyNeighbor = N.end ();
-                  break;
-                }
-            }
-        }
-      if (onlyNeighbor != N.end ())
-        {
-          mprSet.insert (onlyNeighbor->neighborMainAddr);
-          coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
-        }
-    }
-  // Remove the nodes from N2 which are now covered by a node in the MPR set.
-  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
-       twoHopNeigh != N2.end (); )
-    {
-      if (coveredTwoHopNeighbors.find (twoHopNeigh->twoHopNeighborAddr) != coveredTwoHopNeighbors.end ())
-        {
-          twoHopNeigh = N2.erase (twoHopNeigh);
-        }
-      else
-        {
-          twoHopNeigh++;
-        }
-    }
-	
-  // 4. While there exist nodes in N2 which are not covered by at
-  // least one node in the MPR set:
-  while (N2.begin () != N2.end ())
-    {
-      // 4.1. For each node in N, calculate the reachability, i.e., the
-      // number of nodes in N2 which are not yet covered by at
-      // least one node in the MPR set, and which are reachable
-      // through this 1-hop neighbor
-      std::map<int, std::vector<const NeighborTuple *> > reachability;
-      std::set<int> rs;
-      for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
-        {
-          NeighborTuple const &nb_tuple = *it;
-          int r = 0;
-          for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
-            {
-              TwoHopNeighborTuple const &nb2hop_tuple = *it2;
-              if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
-                r++;
-            }
-          rs.insert (r);
-          reachability[r].push_back (&nb_tuple);
-        }
-      
-      // 4.2. Select as a MPR the node with highest N_willingness among
-      // the nodes in N with non-zero reachability. In case of
-      // multiple choice select the node which provides
-      // reachability to the maximum number of nodes in N2. In
-      // case of multiple nodes providing the same amount of
-      // reachability, select the node as MPR whose D(y) is
-      // greater. Remove the nodes from N2 which are now covered
-      // by a node in the MPR set.
-      NeighborTuple const *max = NULL;
-      int max_r = 0;
-      for (std::set<int>::iterator it = rs.begin (); it != rs.end (); it++)
-        {
-          int r = *it;
-          if (r == 0)
-            {
-              continue;
-            }
-          for (std::vector<const NeighborTuple *>::iterator it2 = reachability[r].begin ();
-               it2 != reachability[r].end (); it2++)
-            {
-              const NeighborTuple *nb_tuple = *it2;
-              if (max == NULL || nb_tuple->willingness > max->willingness)
-                {
-                  max = nb_tuple;
-                  max_r = r;
-                }
-              else if (nb_tuple->willingness == max->willingness)
-                {
-                  if (r > max_r)
-                    {
-                      max = nb_tuple;
-                      max_r = r;
-                    }
-                  else if (r == max_r)
-                    {
-                      if (Degree (*nb_tuple) > Degree (*max))
-                        {
-                          max = nb_tuple;
-                          max_r = r;
-                        }
-                    }
-                }
-            }
-        }
-
-      if (max != NULL)
-        {
-          mprSet.insert (max->neighborMainAddr);
-          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
-               twoHopNeigh != N2.end (); )
-            {
-              if (twoHopNeigh->neighborMainAddr == max->neighborMainAddr)
-                {
-                  twoHopNeigh = N2.erase (twoHopNeigh);
-                }
-              else
-                {
-                  twoHopNeigh++;
-                }
-            }
-        }
-    }
-
-#ifdef NS3_LOG_ENABLE
-  {
-    std::ostringstream os;
-    os << "[";
-    for (MprSet::const_iterator iter = mprSet.begin ();
-         iter != mprSet.end (); iter++)
-      {
-        MprSet::const_iterator next = iter;
-        next++;
-        os << *iter;
-        if (next != mprSet.end ())
-          os << ", ";
-      }
-    os << "]";
-    NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ());
-  }
-#endif
-
-  m_state.SetMprSet (mprSet);
-}
-
-///
-/// \brief Gets the main address associated with a given interface address.
-///
-/// \param iface_addr the interface address.
-/// \return the corresponding main address.
-///
-Ipv4Address
-AgentImpl::GetMainAddress (Ipv4Address iface_addr) const
-{
-  const IfaceAssocTuple *tuple =
-    m_state.FindIfaceAssocTuple (iface_addr);
-  
-  if (tuple != NULL)
-    return tuple->mainAddr;
-  else
-    return iface_addr;
-}
-
-///
-/// \brief Creates the routing table of the node following RFC 3626 hints.
-///
-void
-AgentImpl::RoutingTableComputation ()
-{
-  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " s: Node " << m_mainAddress
-                << ": RoutingTableComputation begin...");
-
-  // 1. All the entries from the routing table are removed.
-  m_routingTable->Clear ();
-	
-  // 2. The new routing entries are added starting with the
-  // symmetric neighbors (h=1) as the destination nodes.
-  const NeighborSet &neighborSet = m_state.GetNeighbors ();
-  for (NeighborSet::const_iterator it = neighborSet.begin ();
-       it != neighborSet.end(); it++)
-    {
-      NeighborTuple const &nb_tuple = *it;
-      NS_LOG_DEBUG ("Looking at neighbor tuple: " << nb_tuple);
-      if (nb_tuple.status == NeighborTuple::STATUS_SYM)
-        {
-          bool nb_main_addr = false;
-          const LinkTuple *lt = NULL;
-          const LinkSet &linkSet = m_state.GetLinks ();
-          for (LinkSet::const_iterator it2 = linkSet.begin();
-               it2 != linkSet.end(); it2++)
-            {
-              LinkTuple const &link_tuple = *it2;
-              NS_LOG_DEBUG ("Looking at link tuple: " << link_tuple
-                            << (link_tuple.time >= Simulator::Now ()? "" : " (expired)"));
-              if ((GetMainAddress (link_tuple.neighborIfaceAddr) == nb_tuple.neighborMainAddr)
-                  && link_tuple.time >= Simulator::Now ())
-                {
-                  NS_LOG_LOGIC ("Link tuple matches neighbor " << nb_tuple.neighborMainAddr
-                                << " => adding routing table entry to neighbor");
-                  lt = &link_tuple;
-                  m_routingTable->AddEntry (link_tuple.neighborIfaceAddr,
-                                            link_tuple.neighborIfaceAddr,
-                                            link_tuple.localIfaceAddr,
-                                            1);
-                  if (link_tuple.neighborIfaceAddr == nb_tuple.neighborMainAddr)
-                    {
-                      nb_main_addr = true;
-                    }
-                }
-              else
-                {
-                  NS_LOG_LOGIC ("Link tuple: linkMainAddress= " << GetMainAddress (link_tuple.neighborIfaceAddr)
-                                << "; neighborMainAddr =  " << nb_tuple.neighborMainAddr
-                                << "; expired=" << int (link_tuple.time < Simulator::Now ())
-                                << " => IGNORE");
-                }
-            }
-
-          // If, in the above, no R_dest_addr is equal to the main
-          // address of the neighbor, then another new routing entry
-          // with MUST be added, with:
-          //      R_dest_addr  = main address of the neighbor;
-          //      R_next_addr  = L_neighbor_iface_addr of one of the
-          //                     associated link tuple with L_time >= current time;
-          //      R_dist       = 1;
-          //      R_iface_addr = L_local_iface_addr of the
-          //                     associated link tuple.
-          if (!nb_main_addr && lt != NULL)
-            {
-              NS_LOG_LOGIC ("no R_dest_addr is equal to the main address of the neighbor "
-                            "=> adding additional routing entry");
-              m_routingTable->AddEntry(nb_tuple.neighborMainAddr,
-                                       lt->neighborIfaceAddr,
-                                       lt->localIfaceAddr,
-                                       1);
-            }
-        }
-    }
-  
-  //  3. for each node in N2, i.e., a 2-hop neighbor which is not a
-  //  neighbor node or the node itself, and such that there exist at
-  //  least one entry in the 2-hop neighbor set where
-  //  N_neighbor_main_addr correspond to a neighbor node with
-  //  willingness different of WILL_NEVER,
-  const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
-  for (TwoHopNeighborSet::const_iterator it = twoHopNeighbors.begin ();
-       it != twoHopNeighbors.end (); it++)
-    {
-      TwoHopNeighborTuple const &nb2hop_tuple = *it;
-
-      NS_LOG_LOGIC ("Looking at two-hop neighbor tuple: " << nb2hop_tuple);
-
-      // a 2-hop neighbor which is not a neighbor node or the node itself
-      if (m_state.FindNeighborTuple (nb2hop_tuple.twoHopNeighborAddr))
-        {
-          NS_LOG_LOGIC ("Two-hop neighbor tuple is also neighbor; skipped.");
-          continue;
-        }
-
-      if (nb2hop_tuple.twoHopNeighborAddr == m_mainAddress)
-        {
-          NS_LOG_LOGIC ("Two-hop neighbor is self; skipped.");
-          continue;
-        }
-
-      // ...and such that there exist at least one entry in the 2-hop
-      // neighbor set where N_neighbor_main_addr correspond to a
-      // neighbor node with willingness different of WILL_NEVER...
-      bool nb2hopOk = false;
-      for (NeighborSet::const_iterator neighbor = neighborSet.begin ();
-           neighbor != neighborSet.end(); neighbor++)
-        {
-          if (neighbor->neighborMainAddr == nb2hop_tuple.neighborMainAddr
-              && neighbor->willingness != OLSR_WILL_NEVER)
-            {
-              nb2hopOk = true;
-              break;
-            }
-        }
-      if (!nb2hopOk)
-        {
-          NS_LOG_LOGIC ("Two-hop neighbor tuple skipped: 2-hop neighbor "
-                        << nb2hop_tuple.twoHopNeighborAddr
-                        << " is attached to neighbor " << nb2hop_tuple.neighborMainAddr
-                        << ", which was not found in the Neighbor Set.");
-          continue;
-        }
-      
-      // one selects one 2-hop tuple and creates one entry in the routing table with:
-      //                R_dest_addr  =  the main address of the 2-hop neighbor;
-      //                R_next_addr  = the R_next_addr of the entry in the
-      //                               routing table with:
-      //                                   R_dest_addr == N_neighbor_main_addr
-      //                                                  of the 2-hop tuple;
-      //                R_dist       = 2;
-      //                R_iface_addr = the R_iface_addr of the entry in the
-      //                               routing table with:
-      //                                   R_dest_addr == N_neighbor_main_addr
-      //                                                  of the 2-hop tuple;
-      RoutingTableEntry entry;
-      bool foundEntry = m_routingTable->Lookup (nb2hop_tuple.neighborMainAddr, entry);
-      if (foundEntry)
-        {
-          NS_LOG_LOGIC ("Adding routing entry for two-hop neighbor.");
-          m_routingTable->AddEntry (nb2hop_tuple.twoHopNeighborAddr,
-                                    entry.nextAddr,
-                                    entry.interface,
-                                    2);
-        }
-      else
-        {
-          NS_LOG_LOGIC ("NOT adding routing entry for two-hop neighbor ("
-                        << nb2hop_tuple.twoHopNeighborAddr
-                        << " not found in the routing table)");
-        }
-    }
-  
-  for (uint32_t h = 2; ; h++)
-    {
-      bool added = false;
-		
-      // 3.1. For each topology entry in the topology table, if its
-      // T_dest_addr does not correspond to R_dest_addr of any
-      // route entry in the routing table AND its T_last_addr
-      // corresponds to R_dest_addr of a route entry whose R_dist
-      // is equal to h, then a new route entry MUST be recorded in
-      // the routing table (if it does not already exist)
-      const TopologySet &topology = m_state.GetTopologySet ();
-      for (TopologySet::const_iterator it = topology.begin ();
-           it != topology.end (); it++)
-        {
-          const TopologyTuple &topology_tuple = *it;
-          NS_LOG_LOGIC ("Looking at topology tuple: " << topology_tuple);
-
-          RoutingTableEntry destAddrEntry, lastAddrEntry;
-          bool have_destAddrEntry = m_routingTable->Lookup (topology_tuple.destAddr, destAddrEntry);
-          bool have_lastAddrEntry = m_routingTable->Lookup (topology_tuple.lastAddr, lastAddrEntry);
-          if (!have_destAddrEntry && have_lastAddrEntry && lastAddrEntry.distance == h)
-            {
-              NS_LOG_LOGIC ("Adding routing table entry based on the topology tuple.");
-              // then a new route entry MUST be recorded in
-              //                the routing table (if it does not already exist) where:
-              //                     R_dest_addr  = T_dest_addr;
-              //                     R_next_addr  = R_next_addr of the recorded
-              //                                    route entry where:
-              //                                    R_dest_addr == T_last_addr
-              //                     R_dist       = h+1; and
-              //                     R_iface_addr = R_iface_addr of the recorded
-              //                                    route entry where:
-              //                                       R_dest_addr == T_last_addr.
-              m_routingTable->AddEntry (topology_tuple.destAddr,
-                                        lastAddrEntry.nextAddr,
-                                        lastAddrEntry.interface,
-                                        h + 1);
-              added = true;
-            }
-          else
-            {
-              NS_LOG_LOGIC ("NOT adding routing table entry based on the topology tuple: "
-                            "have_destAddrEntry=" << have_destAddrEntry
-                            << " have_lastAddrEntry=" << have_lastAddrEntry
-                            << " lastAddrEntry.distance=" << (int) lastAddrEntry.distance
-                            << " (h=" << h << ")");
-            }
-        }
-      
-      if (!added)
-        break;
-    }
-
-  // 4. For each entry in the multiple interface association base
-  // where there exists a routing entry such that:
-  //	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
-  // AND there is no routing entry such that:
-  //	R_dest_addr  == I_iface_addr
-  const IfaceAssocSet &ifaceAssocSet = m_state.GetIfaceAssocSet ();
-  for (IfaceAssocSet::const_iterator it = ifaceAssocSet.begin ();
-       it != ifaceAssocSet.end (); it++)
-    {
-      IfaceAssocTuple const &tuple = *it;
-      RoutingTableEntry entry1, entry2;
-      bool have_entry1 = m_routingTable->Lookup (tuple.mainAddr, entry1);
-      bool have_entry2 = m_routingTable->Lookup (tuple.ifaceAddr, entry2);
-      if (have_entry1 && !have_entry2)
-        {
-          // then a route entry is created in the routing table with:
-          //       R_dest_addr  =  I_iface_addr (of the multiple interface
-          //                                     association entry)
-          //       R_next_addr  =  R_next_addr  (of the recorded route entry)
-          //       R_dist       =  R_dist       (of the recorded route entry)
-          //       R_iface_addr =  R_iface_addr (of the recorded route entry).
-          m_routingTable->AddEntry (tuple.ifaceAddr,
-                                    entry1.nextAddr,
-                                    entry1.interface,
-                                    entry1.distance);
-        }
-    }
-
-  NS_LOG_DEBUG ("Node " << m_mainAddress << ": RoutingTableComputation end.");
-  m_routingTableChanged (m_routingTable->GetSize ());
-}
-
-
-///
-/// \brief Processes a HELLO message following RFC 3626 specification.
-///
-/// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
-/// Selector Set are performed.
-///
-/// \param msg the %OLSR message which contains the HELLO message.
-/// \param receiver_iface the address of the interface where the message was received from.
-/// \param sender_iface the address of the interface where the message was sent from.
-///
-void
-AgentImpl::ProcessHello (const olsr::MessageHeader &msg,
-                         const Ipv4Address &receiverIface,
-                         const Ipv4Address &senderIface)
-{
-  const olsr::MessageHeader::Hello &hello = msg.GetHello ();
-
-  LinkSensing (msg, hello, receiverIface, senderIface);
-
-#ifdef NS3_LOG_ENABLE
-  {
-    const LinkSet &links = m_state.GetLinks ();
-    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                  << "s ** BEGIN dump Link Set for OLSR Node " << m_mainAddress);
-    for (LinkSet::const_iterator link = links.begin (); link != links.end (); link++)
-      {
-        NS_LOG_DEBUG(*link);
-      }
-    NS_LOG_DEBUG ("** END dump Link Set for OLSR Node " << m_mainAddress);
-
-    const NeighborSet &neighbors = m_state.GetNeighbors ();
-    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                  << "s ** BEGIN dump Neighbor Set for OLSR Node " << m_mainAddress);
-    for (NeighborSet::const_iterator neighbor = neighbors.begin (); neighbor != neighbors.end (); neighbor++)
-      {
-        NS_LOG_DEBUG(*neighbor);
-      }
-    NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress);
-  }
-#endif
-
-  PopulateNeighborSet (msg, hello);
-  PopulateTwoHopNeighborSet (msg, hello);
-
-#ifdef NS3_LOG_ENABLE
-  {
-    const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
-    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                  << "s ** BEGIN dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
-    for (TwoHopNeighborSet::const_iterator tuple = twoHopNeighbors.begin ();
-         tuple != twoHopNeighbors.end (); tuple++)
-      {
-        NS_LOG_DEBUG(*tuple);
-      }
-    NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
-  }
-#endif
-
-  MprComputation ();
-  PopulateMprSelectorSet (msg, hello);
-}
-
-///
-/// \brief Processes a TC message following RFC 3626 specification.
-///
-/// The Topology Set is updated (if needed) with the information of
-/// the received TC message.
-///
-/// \param msg the %OLSR message which contains the TC message.
-/// \param sender_iface the address of the interface where the message was sent from.
-///
-void
-AgentImpl::ProcessTc (const olsr::MessageHeader &msg,
-                      const Ipv4Address &senderIface)
-{
-  const olsr::MessageHeader::Tc &tc = msg.GetTc ();
-  Time now = Simulator::Now ();
-	
-  // 1. If the sender interface of this message is not in the symmetric
-  // 1-hop neighborhood of this node, the message MUST be discarded.
-  const LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now);
-  if (link_tuple == NULL)
-    return;
-	
-  // 2. If there exist some tuple in the topology set where:
-  // 	T_last_addr == originator address AND
-  // 	T_seq       >  ANSN,
-  // then further processing of this TC message MUST NOT be
-  // performed.
-  const TopologyTuple *topologyTuple =
-    m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.ansn);
-  if (topologyTuple != NULL)
-    return;
-	
-  // 3. All tuples in the topology set where:
-  //	T_last_addr == originator address AND
-  //	T_seq       <  ANSN
-  // MUST be removed from the topology set.
-  m_state.EraseOlderTopologyTuples (msg.GetOriginatorAddress (), tc.ansn);
-
-  // 4. For each of the advertised neighbor main address received in
-  // the TC message:
-  for (std::vector<Ipv4Address>::const_iterator i = tc.neighborAddresses.begin ();
-       i != tc.neighborAddresses.end (); i++)
-    {
-      const Ipv4Address &addr = *i;
-      // 4.1. If there exist some tuple in the topology set where:
-      // 	T_dest_addr == advertised neighbor main address, AND
-      // 	T_last_addr == originator address,
-      // then the holding time of that tuple MUST be set to:
-      // 	T_time      =  current time + validity time.
-      TopologyTuple *topologyTuple =
-        m_state.FindTopologyTuple (addr, msg.GetOriginatorAddress ());
-
-      if (topologyTuple != NULL)
-        {
-          topologyTuple->expirationTime = now + msg.GetVTime ();
-        }
-      else
-        {
-          // 4.2. Otherwise, a new tuple MUST be recorded in the topology
-          // set where:
-          //	T_dest_addr = advertised neighbor main address,
-          //	T_last_addr = originator address,
-          //	T_seq       = ANSN,
-          //	T_time      = current time + validity time.
-          TopologyTuple topologyTuple;;
-          topologyTuple.destAddr = addr;
-          topologyTuple.lastAddr = msg.GetOriginatorAddress ();
-          topologyTuple.sequenceNumber = tc.ansn;
-          topologyTuple.expirationTime = now + msg.GetVTime ();
-          AddTopologyTuple (topologyTuple);
-
-          // Schedules topology tuple deletion
-          m_events.Track (Simulator::Schedule (DELAY (topologyTuple.expirationTime),
-                                               &AgentImpl::TopologyTupleTimerExpire,
-                                               this,
-                                               topologyTuple.destAddr,
-                                               topologyTuple.lastAddr));
-        }
-    }
-
-#ifdef NS3_LOG_ENABLE
-  {
-    const TopologySet &topology = m_state.GetTopologySet ();
-    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                  << "s ** BEGIN dump TopologySet for OLSR Node " << m_mainAddress);
-    for (TopologySet::const_iterator tuple = topology.begin ();
-         tuple != topology.end (); tuple++)
-      {
-        NS_LOG_DEBUG (*tuple);
-      }
-    NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress);
-  }
-#endif
-}
-
-///
-/// \brief Processes a MID message following RFC 3626 specification.
-///
-/// The Interface Association Set is updated (if needed) with the information
-/// of the received MID message.
-///
-/// \param msg the %OLSR message which contains the MID message.
-/// \param sender_iface the address of the interface where the message was sent from.
-///
-void
-AgentImpl::ProcessMid (const olsr::MessageHeader &msg,
-                       const Ipv4Address &senderIface)
-{
-  const olsr::MessageHeader::Mid &mid = msg.GetMid ();
-  Time now = Simulator::Now ();
-  
-  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface);
-  // 1. If the sender interface of this message is not in the symmetric
-  // 1-hop neighborhood of this node, the message MUST be discarded.
-  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
-  if (linkTuple == NULL)
-    {
-      NS_LOG_LOGIC ("Node " << m_mainAddress <<
-                    ": the sender interface of this message is not in the "
-                    "symmetric 1-hop neighborhood of this node,"
-                    " the message MUST be discarded.");
-      return;
-    }
-	
-  // 2. For each interface address listed in the MID message
-  for (std::vector<Ipv4Address>::const_iterator i = mid.interfaceAddresses.begin ();
-       i != mid.interfaceAddresses.end (); i++)
-    {
-      bool updated = false;
-      IfaceAssocSet &ifaceAssoc = m_state.GetIfaceAssocSetMutable ();
-      for (IfaceAssocSet::iterator tuple = ifaceAssoc.begin();
-           tuple != ifaceAssoc.end(); tuple++)
-        {
-          if (tuple->ifaceAddr == *i
-              && tuple->mainAddr == msg.GetOriginatorAddress ())
-            {
-              NS_LOG_LOGIC ("IfaceAssoc updated: " << *tuple);
-              tuple->time = now + msg.GetVTime ();
-              updated = true;
-            }
-        }
-      if (!updated)
-        {
-          IfaceAssocTuple tuple;
-          tuple.ifaceAddr = *i;
-          tuple.mainAddr = msg.GetOriginatorAddress ();
-          tuple.time = now + msg.GetVTime ();
-          AddIfaceAssocTuple (tuple);
-          NS_LOG_LOGIC ("New IfaceAssoc added: " << tuple);
-          // Schedules iface association tuple deletion
-          Simulator::Schedule (DELAY (tuple.time),
-                               &AgentImpl::IfaceAssocTupleTimerExpire, this, tuple.ifaceAddr);
-        }
-    }
-
-  // 3. (not part of the RFC) iterate over all NeighborTuple's and
-  // TwoHopNeighborTuples, update the neighbor addresses taking into account
-  // the new MID information.
-  NeighborSet &neighbors = m_state.GetNeighbors ();
-  for (NeighborSet::iterator neighbor = neighbors.begin (); neighbor != neighbors.end(); neighbor++)
-    {
-      neighbor->neighborMainAddr = GetMainAddress (neighbor->neighborMainAddr);
-    }
-
-  TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
-  for (TwoHopNeighborSet::iterator twoHopNeighbor = twoHopNeighbors.begin ();
-       twoHopNeighbor != twoHopNeighbors.end(); twoHopNeighbor++)
-    {
-      twoHopNeighbor->neighborMainAddr = GetMainAddress (twoHopNeighbor->neighborMainAddr);
-      twoHopNeighbor->twoHopNeighborAddr = GetMainAddress (twoHopNeighbor->twoHopNeighborAddr);
-    }
-  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface << " -> END.");
-}
-
-
-///
-/// \brief OLSR's default forwarding algorithm.
-///
-/// See RFC 3626 for details.
-///
-/// \param p the %OLSR packet which has been received.
-/// \param msg the %OLSR message which must be forwarded.
-/// \param dup_tuple NULL if the message has never been considered for forwarding,
-/// or a duplicate tuple in other case.
-/// \param local_iface the address of the interface where the message was received from.
-///
-void
-AgentImpl::ForwardDefault (olsr::MessageHeader olsrMessage,
-                               DuplicateTuple *duplicated,
-                               const Ipv4Address &localIface,
-                               const Ipv4Address &senderAddress)
-{
-  Time now = Simulator::Now ();
-  
-  // If the sender interface address is not in the symmetric
-  // 1-hop neighborhood the message must not be forwarded
-  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderAddress, now);
-  if (linkTuple == NULL)
-    return;
-
-  // If the message has already been considered for forwarding,
-  // it must not be retransmitted again
-  if (duplicated != NULL && duplicated->retransmitted)
-    {
-      NS_LOG_LOGIC (Simulator::Now () << "Node " << m_mainAddress << " does not forward a message received"
-                    " from " << olsrMessage.GetOriginatorAddress () << " because it is duplicated");
-      return;
-    }
-	
-  // If the sender interface address is an interface address
-  // of a MPR selector of this node and ttl is greater than 1,
-  // the message must be retransmitted
-  bool retransmitted = false;
-  if (olsrMessage.GetTimeToLive () > 1)
-    {
-      const MprSelectorTuple *mprselTuple =
-        m_state.FindMprSelectorTuple (GetMainAddress (senderAddress));
-      if (mprselTuple != NULL)
-        {
-          olsrMessage.SetTimeToLive (olsrMessage.GetTimeToLive () - 1);
-          olsrMessage.SetHopCount (olsrMessage.GetHopCount () + 1);
-          // We have to introduce a random delay to avoid
-          // synchronization with neighbors.
-          QueueMessage (olsrMessage, JITTER);
-          retransmitted = true;
-        }
-    }
-	
-  // Update duplicate tuple...
-  if (duplicated != NULL)
-    {
-      duplicated->expirationTime = now + OLSR_DUP_HOLD_TIME;
-      duplicated->retransmitted = retransmitted;
-      duplicated->ifaceList.push_back (localIface);
-    }
-  // ...or create a new one
-  else
-    {
-      DuplicateTuple newDup;
-      newDup.address = olsrMessage.GetOriginatorAddress ();
-      newDup.sequenceNumber = olsrMessage.GetMessageSequenceNumber ();
-      newDup.expirationTime = now + OLSR_DUP_HOLD_TIME;
-      newDup.retransmitted = retransmitted;
-      newDup.ifaceList.push_back (localIface);
-      AddDuplicateTuple (newDup);
-      // Schedule dup tuple deletion
-      Simulator::Schedule (OLSR_DUP_HOLD_TIME,
-                           &AgentImpl::DupTupleTimerExpire, this,
-                           newDup.address, newDup.sequenceNumber);
-    }
-}
-
-///
-/// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
-///
-/// This buffering system is used in order to piggyback several %OLSR messages in
-/// a same %OLSR packet.
-///
-/// \param msg the %OLSR message which must be sent.
-/// \param delay maximum delay the %OLSR message is going to be buffered.
-///
-void
-AgentImpl::QueueMessage (const olsr::MessageHeader &message, Time delay)
-{
-  m_queuedMessages.push_back (message);
-  if (not m_queuedMessagesTimer.IsRunning ())
-    {
-      m_queuedMessagesTimer.SetDelay (delay);
-      m_queuedMessagesTimer.Schedule ();
-    }
-}
-
-void
-AgentImpl::SendPacket (Ptr<Packet> packet, 
-                       const MessageList &containedMessages)
-{
-  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
-
-  // Add a header
-  olsr::PacketHeader header;
-  header.SetPacketLength (header.GetSerializedSize () + packet->GetSize ());
-  header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
-  packet->AddHeader (header);
-
-  // Trace it
-  m_txPacketTrace (header, containedMessages);
-
-  // Send it
-  m_socketAddresses.begin ()->first->Send (packet);
-}
-
-///
-/// \brief Creates as many %OLSR packets as needed in order to send all buffered
-/// %OLSR messages.
-///
-/// Maximum number of messages which can be contained in an %OLSR packet is
-/// dictated by OLSR_MAX_MSGS constant.
-///
-void
-AgentImpl::SendQueuedMessages ()
-{
-  Ptr<Packet> packet = Create<Packet> ();
-  int numMessages = 0;
-
-  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
-
-  MessageList msglist;
-
-  for (std::vector<olsr::MessageHeader>::const_iterator message = m_queuedMessages.begin ();
-       message != m_queuedMessages.end ();
-       message++)
-    {
-      Ptr<Packet> p = Create<Packet> ();
-      p->AddHeader (*message);
-      packet->AddAtEnd (p);
-      msglist.push_back (*message);
-      if (++numMessages == OLSR_MAX_MSGS)
-        {
-          SendPacket (packet, msglist);
-          msglist.clear ();
-          // Reset variables for next packet
-          numMessages = 0;
-          packet = Create<Packet> ();
-        }
-    }
-
-  if (packet->GetSize ())
-    {
-      SendPacket (packet, msglist);
-    }
-
-  m_queuedMessages.clear ();
-}
-
-///
-/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
-///
-void
-AgentImpl::SendHello ()
-{
-  NS_LOG_FUNCTION (this);
-  
-  olsr::MessageHeader msg;
-  Time now = Simulator::Now ();
-
-  msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
-  msg.SetOriginatorAddress (m_mainAddress);
-  msg.SetTimeToLive (1);
-  msg.SetHopCount (0);
-  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
-  olsr::MessageHeader::Hello &hello = msg.GetHello ();
-
-  hello.SetHTime (Scalar (3) * m_helloInterval);
-  hello.willingness = m_willingness;
-
-  std::vector<olsr::MessageHeader::Hello::LinkMessage>
-    &linkMessages = hello.linkMessages;
-	
-  const LinkSet &links = m_state.GetLinks ();
-  for (LinkSet::const_iterator link_tuple = links.begin ();
-       link_tuple != links.end (); link_tuple++)
-    {
-      if (!(GetMainAddress (link_tuple->localIfaceAddr) == m_mainAddress
-            && link_tuple->time >= now))
-        {
-          continue;
-        }
-
-      uint8_t link_type, nb_type = 0xff;
-			
-      // Establishes link type
-      if (link_tuple->symTime >= now)
-        {
-          link_type = OLSR_SYM_LINK;
-        }
-      else if (link_tuple->asymTime >= now)
-        {
-          link_type = OLSR_ASYM_LINK;
-        }
-      else
-        {
-          link_type = OLSR_LOST_LINK;
-        }
-      // Establishes neighbor type.
-      if (m_state.FindMprAddress (GetMainAddress (link_tuple->neighborIfaceAddr)))
-        {
-          nb_type = OLSR_MPR_NEIGH;
-          NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
-                        << " to be MPR_NEIGH.");
-        }
-      else
-        {
-          bool ok = false;
-          for (NeighborSet::const_iterator nb_tuple = m_state.GetNeighbors ().begin ();
-               nb_tuple != m_state.GetNeighbors ().end ();
-               nb_tuple++)
-            {
-              if (nb_tuple->neighborMainAddr == GetMainAddress (link_tuple->neighborIfaceAddr))
-                {
-                  if (nb_tuple->status == NeighborTuple::STATUS_SYM)
-                    {
-                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
-                                    << " to be SYM_NEIGH.");
-                      nb_type = OLSR_SYM_NEIGH;
-                    }
-                  else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
-                    {
-                      nb_type = OLSR_NOT_NEIGH;
-                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
-                                    << " to be NOT_NEIGH.");
-                    }
-                  else
-                    {
-                      NS_FATAL_ERROR ("There is a neighbor tuple with an unknown status!\n");
-                    }
-                  ok = true;
-                  break;
-                }
-            }
-          if (!ok)
-            {
-              NS_LOG_WARN ("I don't know the neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr) << "!!!");
-              continue;
-            }
-        }
-
-      olsr::MessageHeader::Hello::LinkMessage linkMessage;
-      linkMessage.linkCode = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
-      linkMessage.neighborInterfaceAddresses.push_back
-        (link_tuple->neighborIfaceAddr);
-
-      std::vector<Ipv4Address> interfaces =
-        m_state.FindNeighborInterfaces (link_tuple->neighborIfaceAddr);
-
-      linkMessage.neighborInterfaceAddresses.insert
-        (linkMessage.neighborInterfaceAddresses.end (),
-         interfaces.begin (), interfaces.end ());
-
-      linkMessages.push_back (linkMessage);
-    }
-  NS_LOG_DEBUG ("OLSR HELLO message size: " << int (msg.GetSerializedSize ())
-                << " (with " << int (linkMessages.size ()) << " link messages)");
-  QueueMessage (msg, JITTER);
-}
-
-///
-/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
-///
-void
-AgentImpl::SendTc ()
-{
-  NS_LOG_FUNCTION (this);
-  
-  olsr::MessageHeader msg;
-
-  msg.SetVTime (OLSR_TOP_HOLD_TIME);
-  msg.SetOriginatorAddress (m_mainAddress);
-  msg.SetTimeToLive (255);
-  msg.SetHopCount (0);
-  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
-  
-  olsr::MessageHeader::Tc &tc = msg.GetTc ();
-  tc.ansn = m_ansn;
-  for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
-       mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
-    {
-      tc.neighborAddresses.push_back (mprsel_tuple->mainAddr);
-    }
-  QueueMessage (msg, JITTER);
-}
-
-///
-/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
-///
-void
-AgentImpl::SendMid ()
-{
-  olsr::MessageHeader msg;
-  olsr::MessageHeader::Mid &mid = msg.GetMid ();
-
-  // A node which has only a single interface address participating in
-  // the MANET (i.e., running OLSR), MUST NOT generate any MID
-  // message.
-
-  // A node with several interfaces, where only one is participating
-  // in the MANET and running OLSR (e.g., a node is connected to a
-  // wired network as well as to a MANET) MUST NOT generate any MID
-  // messages.
-
-  // A node with several interfaces, where more than one is
-  // participating in the MANET and running OLSR MUST generate MID
-  // messages as specified.
-
-  // [ Note: assuming here that all interfaces participate in the
-  // MANET; later we may want to make this configurable. ]
-
-  Ipv4Address loopback ("127.0.0.1");
-  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
-    {
-      Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
-      if (addr != m_mainAddress && addr != loopback)
-        mid.interfaceAddresses.push_back (addr);
-    }
-  if (mid.interfaceAddresses.size () == 0)
-    return;
-  
-  msg.SetVTime (OLSR_MID_HOLD_TIME);
-  msg.SetOriginatorAddress (m_mainAddress);
-  msg.SetTimeToLive (255);
-  msg.SetHopCount (0);
-  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
-
-  QueueMessage (msg, JITTER);
-}
-
-///
-/// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
-///		specification). Neighbor Set is also updated if needed.
-void
-AgentImpl::LinkSensing (const olsr::MessageHeader &msg,
-                        const olsr::MessageHeader::Hello &hello,
-                        const Ipv4Address &receiverIface,
-                        const Ipv4Address &senderIface)
-{
-  Time now = Simulator::Now ();
-  bool updated = false;
-  bool created = false;
-  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
-                << ": LinkSensing(receiverIface=" << receiverIface
-                << ", senderIface=" << senderIface << ") BEGIN");
-	
-  NS_ASSERT (msg.GetVTime () > Seconds (0));
-  LinkTuple *link_tuple = m_state.FindLinkTuple (senderIface);
-  if (link_tuple == NULL)
-    {
-      LinkTuple newLinkTuple;
-      // We have to create a new tuple
-      newLinkTuple.neighborIfaceAddr = senderIface;
-      newLinkTuple.localIfaceAddr = receiverIface;
-      newLinkTuple.symTime = now - Seconds (1);
-      newLinkTuple.time = now + msg.GetVTime ();
-      link_tuple = &m_state.InsertLinkTuple (newLinkTuple);
-      created = true;
-      NS_LOG_LOGIC ("Existing link tuple did not exist => creating new one");
-    }
-  else
-    {
-      NS_LOG_LOGIC ("Existing link tuple already exists => will update it");
-      updated = true;
-    }
-	
-  link_tuple->asymTime = now + msg.GetVTime ();
-  for (std::vector<olsr::MessageHeader::Hello::LinkMessage>::const_iterator linkMessage =
-         hello.linkMessages.begin ();
-       linkMessage != hello.linkMessages.end ();
-       linkMessage++)
-    {
-      int lt = linkMessage->linkCode & 0x03; // Link Type
-      int nt = (linkMessage->linkCode >> 2) & 0x03; // Neighbor Type
-
-#ifdef NS3_LOG_ENABLE
-      const char *linkTypeName;
-      switch (lt)
-        {
-        case OLSR_UNSPEC_LINK: linkTypeName = "UNSPEC_LINK"; break;
-        case OLSR_ASYM_LINK: linkTypeName = "ASYM_LINK"; break;
-        case OLSR_SYM_LINK: linkTypeName = "SYM_LINK"; break;
-        case OLSR_LOST_LINK: linkTypeName = "LOST_LINK"; break;
-        default: linkTypeName = "(invalid value!)";
-        }
-
-      const char *neighborTypeName;
-      switch (nt)
-        {
-        case OLSR_NOT_NEIGH: neighborTypeName = "NOT_NEIGH"; break;
-        case OLSR_SYM_NEIGH: neighborTypeName = "SYM_NEIGH"; break;
-        case OLSR_MPR_NEIGH: neighborTypeName = "MPR_NEIGH"; break;
-        default: neighborTypeName = "(invalid value!)";
-        }
-
-      NS_LOG_DEBUG ("Looking at HELLO link messages with Link Type "
-                    << lt << " (" << linkTypeName
-                    << ") and Neighbor Type " << nt
-                    << " (" << neighborTypeName << ")");
-#endif
-
-      // We must not process invalid advertised links
-      if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
-          (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
-           && nt != OLSR_NOT_NEIGH))
-        {
-          NS_LOG_LOGIC ("HELLO link code is invalid => IGNORING");
-          continue;
-        }
-      
-      for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
-             linkMessage->neighborInterfaceAddresses.begin ();
-           neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
-           neighIfaceAddr++)
-        {
-          NS_LOG_DEBUG ("   -> Neighbor: " << *neighIfaceAddr);
-          if (*neighIfaceAddr == receiverIface)
-            {
-              if (lt == OLSR_LOST_LINK)
-                {
-                  NS_LOG_LOGIC ("link is LOST => expiring it");
-                  link_tuple->symTime = now - Seconds (1);
-                  updated = true;
-                }
-              else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
-                {
-                  NS_LOG_DEBUG (*link_tuple << ": link is SYM or ASYM => should become SYM now"
-                                " (symTime being increased to " << now + msg.GetVTime ());
-                  link_tuple->symTime = now + msg.GetVTime ();
-                  link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
-                  updated = true;
-                }
-              else
-                {
-                  NS_FATAL_ERROR ("bad link type");
-                }
-              break;
-            }
-          else
-            {
-              NS_LOG_DEBUG ("     \\-> *neighIfaceAddr (" << *neighIfaceAddr
-                            << " != receiverIface (" << receiverIface << ") => IGNORING!");
-            }
-        }
-      NS_LOG_DEBUG ("Link tuple updated: " << int (updated));
-    }
-  link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
-
-  if (updated)
-    {
-      LinkTupleUpdated (*link_tuple, hello.willingness);
-    }
-
-  // Schedules link tuple deletion
-  if (created && link_tuple != NULL)
-    {
-      LinkTupleAdded (*link_tuple, hello.willingness);
-      m_events.Track (Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
-                                           &AgentImpl::LinkTupleTimerExpire, this,
-                                           link_tuple->neighborIfaceAddr));
-    }
-  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
-                << ": LinkSensing END");
-}
-
-///
-/// \brief	Updates the Neighbor Set according to the information contained in a new received
-///		HELLO message (following RFC 3626).
-void
-AgentImpl::PopulateNeighborSet (const olsr::MessageHeader &msg,
-                                const olsr::MessageHeader::Hello &hello)
-{
-  NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
-  if (nb_tuple != NULL)
-    {
-      nb_tuple->willingness = hello.willingness;
-    }
-}
-
-
-///
-/// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
-///		received HELLO message (following RFC 3626).
-void
-AgentImpl::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
-                                      const olsr::MessageHeader::Hello &hello)
-{
-  Time now = Simulator::Now ();
-
-  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet BEGIN");
-	
-  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
-       link_tuple != m_state.GetLinks ().end (); link_tuple++)
-    {
-      NS_LOG_LOGIC ("Looking at link tuple: " << *link_tuple);
-      if (GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ())
-        {
-          NS_LOG_LOGIC ("Link tuple ignored: "
-                        "GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ()");
-          NS_LOG_LOGIC ("(GetMainAddress(" << link_tuple->neighborIfaceAddr << "): "
-                        << GetMainAddress (link_tuple->neighborIfaceAddr)
-                        << "; msg.GetOriginatorAddress (): " << msg.GetOriginatorAddress ());
-          continue;
-        }
-
-      if (link_tuple->symTime < now)
-        {
-          NS_LOG_LOGIC ("Link tuple ignored: expired.");
-          continue;
-        }
-
-      typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
-      for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
-           linkMessage != hello.linkMessages.end (); linkMessage++)
-        {
-          int neighborType = (linkMessage->linkCode >> 2) & 0x3;
-#ifdef NS3_LOG_ENABLE
-          const char *neighborTypeNames[3] = { "NOT_NEIGH", "SYM_NEIGH", "MPR_NEIGH" };
-          const char *neighborTypeName = ((neighborType < 3)?
-                                          neighborTypeNames[neighborType]
-                                          : "(invalid value)");
-          NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType="
-                        << neighborType << " (" << neighborTypeName << ")");
-#endif
-
-          for (std::vector<Ipv4Address>::const_iterator nb2hop_addr_iter =
-                 linkMessage->neighborInterfaceAddresses.begin ();
-               nb2hop_addr_iter != linkMessage->neighborInterfaceAddresses.end ();
-               nb2hop_addr_iter++)
-            {
-              Ipv4Address nb2hop_addr = GetMainAddress (*nb2hop_addr_iter);
-              NS_LOG_DEBUG ("Looking at 2-hop neighbor address from HELLO message: "
-                            << *nb2hop_addr_iter
-                            << " (main address is " << nb2hop_addr << ")");
-              if (neighborType == OLSR_SYM_NEIGH || neighborType == OLSR_MPR_NEIGH)
-                {
-                  // If the main address of the 2-hop neighbor address == main address
-                  // of the receiving node, silently discard the 2-hop
-                  // neighbor address.
-                  if (nb2hop_addr == m_routingAgentAddr)
-                    {
-                      NS_LOG_LOGIC ("Ignoring 2-hop neighbor (it is the node itself)");
-                      continue;
-                    }
-
-                  // Otherwise, a 2-hop tuple is created
-                  TwoHopNeighborTuple *nb2hop_tuple =
-                    m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (), nb2hop_addr);
-                  NS_LOG_LOGIC ("Adding the 2-hop neighbor"
-                                << (nb2hop_tuple? " (refreshing existing entry)" : ""));
-                  if (nb2hop_tuple == NULL)
-                    {
-                      TwoHopNeighborTuple new_nb2hop_tuple;
-                      new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
-                      new_nb2hop_tuple.twoHopNeighborAddr = nb2hop_addr;
-                      new_nb2hop_tuple.expirationTime = now + msg.GetVTime ();
-                      AddTwoHopNeighborTuple (new_nb2hop_tuple);
-                      // Schedules nb2hop tuple deletion
-                      m_events.Track (Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
-                                                           &AgentImpl::Nb2hopTupleTimerExpire, this,
-                                                           new_nb2hop_tuple.neighborMainAddr,
-                                                           new_nb2hop_tuple.twoHopNeighborAddr));
-                    }
-                  else
-                    {
-                      nb2hop_tuple->expirationTime = now + msg.GetVTime ();
-                    }
-                }
-              else if (neighborType == OLSR_NOT_NEIGH)
-                {
-                  // For each 2-hop node listed in the HELLO message
-                  // with Neighbor Type equal to NOT_NEIGH all 2-hop
-                  // tuples where: N_neighbor_main_addr == Originator
-                  // Address AND N_2hop_addr == main address of the
-                  // 2-hop neighbor are deleted.
-                  NS_LOG_LOGIC ("2-hop neighbor is NOT_NEIGH => deleting matching 2-hop neighbor state");
-                  m_state.EraseTwoHopNeighborTuples (msg.GetOriginatorAddress (), nb2hop_addr);
-                }
-              else
-                {
-                  NS_LOG_LOGIC ("*** WARNING *** Ignoring link message (inside HELLO) with bad"
-                                " neighbor type value: " << neighborType);
-                }
-            }
-        }
-    }
-
-  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet END");
-}
-
-
-
-///
-/// \brief	Updates the MPR Selector Set according to the information contained in a new
-///		received HELLO message (following RFC 3626).
-void
-AgentImpl::PopulateMprSelectorSet (const olsr::MessageHeader &msg,
-                                       const olsr::MessageHeader::Hello &hello)
-{
-  NS_LOG_FUNCTION (this);
-  
-  Time now = Simulator::Now ();
-	
-  typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
-  for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
-       linkMessage != hello.linkMessages.end ();
-       linkMessage++)
-    {
-      int nt = linkMessage->linkCode >> 2;
-      if (nt == OLSR_MPR_NEIGH)
-        {
-          NS_LOG_DEBUG ("Processing a link message with neighbor type MPR_NEIGH");
-          
-          for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
-                 linkMessage->neighborInterfaceAddresses.begin ();
-               nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
-               nb_iface_addr++)
-            {
-              if (GetMainAddress (*nb_iface_addr) == m_mainAddress)
-                {
-                  NS_LOG_DEBUG ("Adding entry to mpr selector set for neighbor " << *nb_iface_addr);
-                  
-                  // We must create a new entry into the mpr selector set
-                  MprSelectorTuple *existing_mprsel_tuple =
-                    m_state.FindMprSelectorTuple (msg.GetOriginatorAddress ());
-                  if (existing_mprsel_tuple == NULL)
-                    {
-                      MprSelectorTuple mprsel_tuple;
-
-                      mprsel_tuple.mainAddr = msg.GetOriginatorAddress ();
-                      mprsel_tuple.expirationTime = now + msg.GetVTime ();
-                      AddMprSelectorTuple (mprsel_tuple);
-
-                      // Schedules mpr selector tuple deletion
-                      m_events.Track (Simulator::Schedule
-                                      (DELAY (mprsel_tuple.expirationTime),
-                                       &AgentImpl::MprSelTupleTimerExpire, this,
-                                       mprsel_tuple.mainAddr));
-                    }
-                  else
-                    {
-                      existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
-                    }
-                }
-            }
-        }
-    }
-  NS_LOG_DEBUG ("Computed MPR selector set for node " << m_mainAddress << ": " << m_state.PrintMprSelectorSet ());
-}
-
-
-#if 0
-///
-/// \brief	Drops a given packet because it couldn't be delivered to the corresponding
-///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
-///		actions are then taken.
-///
-/// \param p the packet which couldn't be delivered by the MAC layer.
-///
-void
-OLSR::mac_failed(Ptr<Packet> p) {
-	double now		= Simulator::Now ();
-	struct hdr_ip* ih	= HDR_IP(p);
-	struct hdr_cmn* ch	= HDR_CMN(p);
-	
-	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
-		now,
-		OLSR::node_id(ra_addr()),
-		OLSR::node_id(ch->next_hop()));
-	
-	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
-		drop(p, DROP_RTR_MAC_CALLBACK);
-		return;
-	}
-	
-	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
-	if (link_tuple != NULL) {
-		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
-		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
-		nb_loss(link_tuple);
-	}
-	drop(p, DROP_RTR_MAC_CALLBACK);
-}
-#endif
-
-
-
-
-///
-/// \brief Performs all actions needed when a neighbor loss occurs.
-///
-/// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
-///
-/// \param tuple link tuple with the information of the link to the neighbor which has been lost.
-///
-void
-AgentImpl::NeighborLoss (const LinkTuple &tuple)
-{
-  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                << "s: OLSR Node " << m_mainAddress
-                << " LinkTuple " << tuple.neighborIfaceAddr << " -> neighbor loss.");
-  LinkTupleUpdated (tuple, OLSR_WILL_DEFAULT);
-  m_state.EraseTwoHopNeighborTuples (GetMainAddress (tuple.neighborIfaceAddr));
-  m_state.EraseMprSelectorTuples (GetMainAddress (tuple.neighborIfaceAddr));
-  
-  MprComputation ();
-  RoutingTableComputation ();
-}
-
-///
-/// \brief Adds a duplicate tuple to the Duplicate Set.
-///
-/// \param tuple the duplicate tuple to be added.
-///
-void
-AgentImpl::AddDuplicateTuple (const DuplicateTuple &tuple)
-{
-	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
-		Simulator::Now (),
-		OLSR::node_id(ra_addr()),
-		OLSR::node_id(tuple->addr()),
-		tuple->seq_num());*/
-  m_state.InsertDuplicateTuple (tuple);
-}
-
-///
-/// \brief Removes a duplicate tuple from the Duplicate Set.
-///
-/// \param tuple the duplicate tuple to be removed.
-///
-void
-AgentImpl::RemoveDuplicateTuple (const DuplicateTuple &tuple)
-{
-  /*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
-    Simulator::Now (),
-    OLSR::node_id(ra_addr()),
-    OLSR::node_id(tuple->addr()),
-    tuple->seq_num());*/
-  m_state.EraseDuplicateTuple (tuple);
-}
-
-void
-AgentImpl::LinkTupleAdded (const LinkTuple &tuple, uint8_t willingness)
-{
-  // Creates associated neighbor tuple
-  NeighborTuple nb_tuple;
-  nb_tuple.neighborMainAddr = GetMainAddress (tuple.neighborIfaceAddr);
-  nb_tuple.willingness = willingness;
-
-  if (tuple.symTime >= Simulator::Now ())
-    {
-      nb_tuple.status = NeighborTuple::STATUS_SYM;
-    }
-  else
-    {
-      nb_tuple.status = NeighborTuple::STATUS_NOT_SYM;
-    }
-
-  AddNeighborTuple (nb_tuple);
-}
-
-///
-/// \brief Removes a link tuple from the Link Set.
-///
-/// \param tuple the link tuple to be removed.
-///
-void
-AgentImpl::RemoveLinkTuple (const LinkTuple &tuple)
-{
-  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                << "s: OLSR Node " << m_mainAddress
-                << " LinkTuple " << tuple << " REMOVED.");
-
-  m_state.EraseLinkTuple (tuple);
-  m_state.EraseNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
-
-}
-
-///
-/// \brief	This function is invoked when a link tuple is updated. Its aim is to
-///		also update the corresponding neighbor tuple if it is needed.
-///
-/// \param tuple the link tuple which has been updated.
-///
-void
-AgentImpl::LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness)
-{
-  // Each time a link tuple changes, the associated neighbor tuple must be recomputed
-
-  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
-                << "s: OLSR Node " << m_mainAddress
-                << " LinkTuple " << tuple << " UPDATED.");
-
-  NeighborTuple *nb_tuple =
-    m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
-  
-  if (nb_tuple == NULL)
-    {
-      LinkTupleAdded (tuple, willingness);
-      nb_tuple = m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
-    }
-
-  if (nb_tuple != NULL)
-    {
-#ifdef NS3_LOG_ENABLE
-      int statusBefore = nb_tuple->status;
-#endif
-      if (tuple.symTime >= Simulator::Now ())
-        {
-          nb_tuple->status = NeighborTuple::STATUS_SYM;
-          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_SYM; changed:"
-                        << int (statusBefore != nb_tuple->status));
-        }
-      else
-        {
-          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
-          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_NOT_SYM; changed:"
-                        << int (statusBefore != nb_tuple->status));
-        }
-    }
-  else
-    {
-      NS_LOG_WARN ("ERROR! Wanted to update a NeighborTuple but none was found!");
-    }
-}
-
-///
-/// \brief Adds a neighbor tuple to the Neighbor Set.
-///
-/// \param tuple the neighbor tuple to be added.
-///
-void
-AgentImpl::AddNeighborTuple (const NeighborTuple &tuple)
-{
-//   debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->neighborMainAddr),
-//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
-  
-  m_state.InsertNeighborTuple (tuple);
-  IncrementAnsn ();
-}
-
-///
-/// \brief Removes a neighbor tuple from the Neighbor Set.
-///
-/// \param tuple the neighbor tuple to be removed.
-///
-void
-AgentImpl::RemoveNeighborTuple (const NeighborTuple &tuple)
-{
-//   debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->neighborMainAddr),
-//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
-	
-  m_state.EraseNeighborTuple (tuple);
-  IncrementAnsn ();
-}
-
-///
-/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
-///
-/// \param tuple the 2-hop neighbor tuple to be added.
-///
-void
-AgentImpl::AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
-{
-//   debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->neighborMainAddr),
-//         OLSR::node_id(tuple->twoHopNeighborAddr));
-  
-  m_state.InsertTwoHopNeighborTuple (tuple);
-}
-
-///
-/// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
-///
-/// \param tuple the 2-hop neighbor tuple to be removed.
-///
-void
-AgentImpl::RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
-{
-//   debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->neighborMainAddr),
-//         OLSR::node_id(tuple->twoHopNeighborAddr));
-
-  m_state.EraseTwoHopNeighborTuple (tuple);
-}
-
-void
-AgentImpl::IncrementAnsn ()
-{
-  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
-}
-
-///
-/// \brief Adds an MPR selector tuple to the MPR Selector Set.
-///
-/// Advertised Neighbor Sequence Number (ANSN) is also updated.
-///
-/// \param tuple the MPR selector tuple to be added.
-///
-void
-AgentImpl::AddMprSelectorTuple (const MprSelectorTuple  &tuple)
-{
-//   debug("%f: Node %d adds MPR selector tuple: nb_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->main_addr()));
-  
-  m_state.InsertMprSelectorTuple (tuple);
-  IncrementAnsn ();
-}
-
-///
-/// \brief Removes an MPR selector tuple from the MPR Selector Set.
-///
-/// Advertised Neighbor Sequence Number (ANSN) is also updated.
-///
-/// \param tuple the MPR selector tuple to be removed.
-///
-void
-AgentImpl::RemoveMprSelectorTuple (const MprSelectorTuple &tuple)
-{
-//   debug("%f: Node %d removes MPR selector tuple: nb_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->main_addr()));
-  
-  m_state.EraseMprSelectorTuple (tuple);
-  IncrementAnsn ();
-}
-
-///
-/// \brief Adds a topology tuple to the Topology Set.
-///
-/// \param tuple the topology tuple to be added.
-///
-void
-AgentImpl::AddTopologyTuple (const TopologyTuple &tuple)
-{
-//   debug("%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->dest_addr()),
-//         OLSR::node_id(tuple->last_addr()),
-//         tuple->seq());
-
-  m_state.InsertTopologyTuple(tuple);
-}
-
-///
-/// \brief Removes a topology tuple from the Topology Set.
-///
-/// \param tuple the topology tuple to be removed.
-///
-void
-AgentImpl::RemoveTopologyTuple (const TopologyTuple &tuple)
-{
-//   debug("%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->dest_addr()),
-//         OLSR::node_id(tuple->last_addr()),
-//         tuple->seq());
-
-  m_state.EraseTopologyTuple (tuple);
-}
-
-///
-/// \brief Adds an interface association tuple to the Interface Association Set.
-///
-/// \param tuple the interface association tuple to be added.
-///
-void
-AgentImpl::AddIfaceAssocTuple (const IfaceAssocTuple &tuple)
-{
-//   debug("%f: Node %d adds iface association tuple: main_addr = %d iface_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->main_addr()),
-//         OLSR::node_id(tuple->iface_addr()));
-
-  m_state.InsertIfaceAssocTuple (tuple);
-}
-
-///
-/// \brief Removes an interface association tuple from the Interface Association Set.
-///
-/// \param tuple the interface association tuple to be removed.
-///
-void
-AgentImpl::RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple)
-{
-//   debug("%f: Node %d removes iface association tuple: main_addr = %d iface_addr = %d\n",
-//         Simulator::Now (),
-//         OLSR::node_id(ra_addr()),
-//         OLSR::node_id(tuple->main_addr()),
-//         OLSR::node_id(tuple->iface_addr()));
-
-  m_state.EraseIfaceAssocTuple (tuple);
-}
-
-
-uint16_t AgentImpl::GetPacketSequenceNumber ()
-{
-  m_packetSequenceNumber = (m_packetSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
-  return m_packetSequenceNumber;
-}
-
-/// Increments message sequence number and returns the new value.
-uint16_t AgentImpl::GetMessageSequenceNumber ()
-{
-  m_messageSequenceNumber = (m_messageSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
-  return m_messageSequenceNumber;
-}
-
-
-///
-/// \brief Sends a HELLO message and reschedules the HELLO timer.
-/// \param e The event which has expired.
-///
-void
-AgentImpl::HelloTimerExpire ()
-{
-  SendHello ();
-  m_helloTimer.Schedule (m_helloInterval);
-}
-
-///
-/// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
-/// \param e The event which has expired.
-///
-void
-AgentImpl::TcTimerExpire ()
-{
-  if (m_state.GetMprSelectors ().size () > 0)
-    {
-      SendTc ();
-    }
-  else
-    {
-      NS_LOG_DEBUG ("Not sending any TC, no one selected me as MPR.");
-    }
-  m_tcTimer.Schedule (m_tcInterval);
-}
-
-///
-/// \brief Sends a MID message (if the node has more than one interface) and resets the MID timer.
-/// \warning Currently it does nothing because there is no support for multiple interfaces.
-/// \param e The event which has expired.
-///
-void
-AgentImpl::MidTimerExpire ()
-{
-  SendMid ();
-  m_midTimer.Schedule (m_midInterval);
-}
-
-///
-/// \brief Removes tuple if expired. Else timer is rescheduled to expire at tuple.expirationTime.
-///
-/// The task of actually removing the tuple is left to the OLSR agent.
-///
-/// \param tuple The tuple which has expired.
-///
-void
-AgentImpl::DupTupleTimerExpire (Ipv4Address address, uint16_t sequenceNumber)
-{
-  DuplicateTuple *tuple =
-    m_state.FindDuplicateTuple (address, sequenceNumber);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->expirationTime < Simulator::Now ())
-    {
-      RemoveDuplicateTuple (*tuple);
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
-                                           &AgentImpl::DupTupleTimerExpire, this,
-                                           address, sequenceNumber));
-    }
-}
-
-///
-/// \brief Removes tuple_ if expired. Else if symmetric time
-/// has expired then it is assumed a neighbor loss and agent_->nb_loss()
-/// is called. In this case the timer is rescheduled to expire at
-/// tuple_->time(). Otherwise the timer is rescheduled to expire at
-/// the minimum between tuple_->time() and tuple_->sym_time().
-///
-/// The task of actually removing the tuple is left to the OLSR agent.
-///
-/// \param e The event which has expired.
-///
-void
-AgentImpl::LinkTupleTimerExpire (Ipv4Address neighborIfaceAddr)
-{
-  Time now = Simulator::Now ();
-
-  // the tuple parameter may be a stale copy; get a newer version from m_state
-  LinkTuple *tuple = m_state.FindLinkTuple (neighborIfaceAddr);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->time < now)
-    {
-      RemoveLinkTuple (*tuple);
-    }
-  else if (tuple->symTime < now)
-    {
-      if (m_linkTupleTimerFirstTime)
-        m_linkTupleTimerFirstTime = false;
-      else
-        NeighborLoss (*tuple);
-
-      m_events.Track (Simulator::Schedule (DELAY (tuple->time),
-                                           &AgentImpl::LinkTupleTimerExpire, this,
-                                           neighborIfaceAddr));
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (std::min (tuple->time, tuple->symTime)),
-                                           &AgentImpl::LinkTupleTimerExpire, this,
-                                           neighborIfaceAddr));
-    }
-}
-
-///
-/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
-///
-/// The task of actually removing the tuple is left to the OLSR agent.
-///
-/// \param e The event which has expired.
-///
-void
-AgentImpl::Nb2hopTupleTimerExpire (Ipv4Address neighborMainAddr, Ipv4Address twoHopNeighborAddr)
-{
-  TwoHopNeighborTuple *tuple;
-  tuple = m_state.FindTwoHopNeighborTuple (neighborMainAddr, twoHopNeighborAddr);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->expirationTime < Simulator::Now ())
-    {
-      RemoveTwoHopNeighborTuple (*tuple);
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
-                                           &AgentImpl::Nb2hopTupleTimerExpire,
-                                           this, neighborMainAddr, twoHopNeighborAddr));
-    }
-}
-
-///
-/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
-///
-/// The task of actually removing the tuple is left to the OLSR agent.
-///
-/// \param e The event which has expired.
-///
-void
-AgentImpl::MprSelTupleTimerExpire (Ipv4Address mainAddr)
-{
-  MprSelectorTuple *tuple = m_state.FindMprSelectorTuple (mainAddr);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->expirationTime < Simulator::Now ())
-    {
-      RemoveMprSelectorTuple (*tuple);
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
-                                           &AgentImpl::MprSelTupleTimerExpire,
-                                           this, mainAddr));
-    }
-}
-
-///
-/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
-///
-/// The task of actually removing the tuple is left to the OLSR agent.
-///
-/// \param e The event which has expired.
-///
-void
-AgentImpl::TopologyTupleTimerExpire (Ipv4Address destAddr, Ipv4Address lastAddr)
-{
-  TopologyTuple *tuple = m_state.FindTopologyTuple (destAddr, lastAddr);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->expirationTime < Simulator::Now ())
-    {
-      RemoveTopologyTuple (*tuple);
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (tuple->expirationTime),
-                                           &AgentImpl::TopologyTupleTimerExpire,
-                                           this, tuple->destAddr, tuple->lastAddr));
-    }
-}
-
-///
-/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
-/// \warning Actually this is never invoked because there is no support for multiple interfaces.
-/// \param e The event which has expired.
-///
-void
-AgentImpl::IfaceAssocTupleTimerExpire (Ipv4Address ifaceAddr)
-{
-  IfaceAssocTuple *tuple = m_state.FindIfaceAssocTuple (ifaceAddr);
-  if (tuple == NULL)
-    {
-      return;
-    }
-  if (tuple->time < Simulator::Now ())
-    {
-      RemoveIfaceAssocTuple (*tuple);
-    }
-  else
-    {
-      m_events.Track (Simulator::Schedule (DELAY (tuple->time),
-                                           &AgentImpl::IfaceAssocTupleTimerExpire,
-                                           this, ifaceAddr));
-    }
-}
-
-Ptr<const olsr::RoutingTable>
-AgentImpl::GetRoutingTable () const
-{
-  return m_routingTable;
-}
-
-}} // namespace olsr, ns3
-
-
--- a/src/routing/olsr/olsr-agent-impl.h	Sun Apr 12 22:41:33 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2004 Francisco J. Ros 
- * Copyright (c) 2007 INESC Porto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Authors: Francisco J. Ros  <fjrm@dif.um.es>
- *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
- */
-
-
-#ifndef __OLSR_AGENT_IMPL_H__
-#define __OLSR_AGENT_IMPL_H__
-
-#include <vector>
-
-#include "olsr-agent.h"
-#include "olsr-header.h"
-#include "olsr-state.h"
-
-#include "olsr-routing-table.h"
-#include "repositories.h"
-
-#include "ns3/object.h"
-#include "ns3/packet.h"
-#include "ns3/node.h"
-#include "ns3/socket.h"
-#include "ns3/event-garbage-collector.h"
-#include "ns3/timer.h"
-#include "ns3/traced-callback.h"
-
-
-namespace ns3 {
-namespace olsr {
-
-
-class AgentImpl : public Agent
-{
-public:
-  static TypeId GetTypeId (void);
-
-  AgentImpl ();
-  virtual ~AgentImpl ();
-
-  virtual void SetNode (Ptr<Node> node);
-
-  virtual void Start ();
-  virtual void SetMainInterface (uint32_t interface);
-  virtual Ptr<const olsr::RoutingTable> GetRoutingTable () const;
-
-private:
-  EventGarbageCollector m_events;
-
-  /// Address of the routing agent.
-  Ipv4Address m_routingAgentAddr;
-	
-  /// Packets sequence number counter.
-  uint16_t m_packetSequenceNumber;
-  /// Messages sequence number counter.
-  uint16_t m_messageSequenceNumber;
-  /// Advertised Neighbor Set sequence number.
-  uint16_t m_ansn;
-  
-  /// HELLO messages' emission interval.
-  Time m_helloInterval;
-  /// TC messages' emission interval.
-  Time m_tcInterval;
-  /// MID messages' emission interval.
-  Time m_midInterval;
-  /// Willingness for forwarding packets on behalf of other nodes.
-  uint8_t m_willingness;
-	
-  /// Routing table.
-  Ptr<RoutingTable> m_routingTable;
-  /// Internal state with all needed data structs.
-  OlsrState m_state;
-
-  Ptr<Ipv4> m_ipv4;
-	
-protected:
-  void DoDispose ();
-
-  void SendPacket (Ptr<Packet> packet, const MessageList &containedMessages);
-	
-  /// Increments packet sequence number and returns the new value.
-  inline uint16_t GetPacketSequenceNumber ();
-  /// Increments message sequence number and returns the new value.
-  inline uint16_t GetMessageSequenceNumber ();
-	
-  void RecvOlsr (Ptr<Socket> socket);
-
-  void MprComputation ();
-  void RoutingTableComputation ();
-  Ipv4Address GetMainAddress (Ipv4Address iface_addr) const;
-
-  // Timer handlers
-  Timer m_helloTimer;
-  void HelloTimerExpire ();
-  
-  Timer m_tcTimer;
-  void TcTimerExpire ();
-
-  Timer m_midTimer;
-  void MidTimerExpire ();
-
-  void DupTupleTimerExpire (Ipv4Address address, uint16_t sequenceNumber);
-  bool m_linkTupleTimerFirstTime;
-  void LinkTupleTimerExpire (Ipv4Address neighborIfaceAddr);
-  void Nb2hopTupleTimerExpire (Ipv4Address neighborMainAddr, Ipv4Address twoHopNeighborAddr);
-  void MprSelTupleTimerExpire (Ipv4Address mainAddr);
-  void TopologyTupleTimerExpire (Ipv4Address destAddr, Ipv4Address lastAddr);
-  void IfaceAssocTupleTimerExpire (Ipv4Address ifaceAddr);
-
-  void IncrementAnsn ();
-
-  /// A list of pending messages which are buffered awaiting for being sent.
-  olsr::MessageList m_queuedMessages;
-  Timer m_queuedMessagesTimer; // timer for throttling outgoing messages
-
-  void ForwardDefault (olsr::MessageHeader olsrMessage,
-                       DuplicateTuple *duplicated,
-                       const Ipv4Address &localIface,
-                       const Ipv4Address &senderAddress);
-  void QueueMessage (const olsr::MessageHeader &message, Time delay);
-  void SendQueuedMessages ();
-  void SendHello ();
-  void SendTc ();
-  void SendMid ();
-
-  void NeighborLoss (const LinkTuple &tuple);
-  void AddDuplicateTuple (const DuplicateTuple &tuple);
-  void RemoveDuplicateTuple (const DuplicateTuple &tuple);
-  void LinkTupleAdded (const LinkTuple &tuple, uint8_t willingness);
-  void RemoveLinkTuple (const LinkTuple &tuple);
-  void LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness);
-  void AddNeighborTuple (const NeighborTuple &tuple);
-  void RemoveNeighborTuple (const NeighborTuple &tuple);
-  void AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
-  void RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
-  void AddMprSelectorTuple (const MprSelectorTuple  &tuple);
-  void RemoveMprSelectorTuple (const MprSelectorTuple &tuple);
-  void AddTopologyTuple (const TopologyTuple &tuple);
-  void RemoveTopologyTuple (const TopologyTuple &tuple);
-  void AddIfaceAssocTuple (const IfaceAssocTuple &tuple);
-  void RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple);
-
-  void ProcessHello (const olsr::MessageHeader &msg,
-                     const Ipv4Address &receiverIface,
-                     const Ipv4Address &senderIface);
-  void ProcessTc (const olsr::MessageHeader &msg,
-                  const Ipv4Address &senderIface);
-  void ProcessMid (const olsr::MessageHeader &msg,
-                   const Ipv4Address &senderIface);
-
-  void LinkSensing (const olsr::MessageHeader &msg,
-                    const olsr::MessageHeader::Hello &hello,
-                    const Ipv4Address &receiverIface,
-                    const Ipv4Address &sender_iface);
-  void PopulateNeighborSet (const olsr::MessageHeader &msg,
-                            const olsr::MessageHeader::Hello &hello);
-  void PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
-                                  const olsr::MessageHeader::Hello &hello);
-  void PopulateMprSelectorSet (const olsr::MessageHeader &msg,
-                               const olsr::MessageHeader::Hello &hello);
-
-  int Degree (NeighborTuple const &tuple);
-
-  Ipv4Address m_mainAddress;
-
-  // One socket per interface, each bound to that interface's address
-  // (reason: for OLSR Link Sensing we need to know on which interface
-  // HELLO messages arrive)
-  std::map< Ptr<Socket>, Ipv4Address > m_socketAddresses;
-
-  TracedCallback <const PacketHeader &,
-                  const MessageList &> m_rxPacketTrace;
-  TracedCallback <const PacketHeader &,
-                  const MessageList &> m_txPacketTrace;
-  TracedCallback <uint32_t> m_routingTableChanged;
-
-};
-
-}} // namespace ns3
-
-#endif
--- a/src/routing/olsr/olsr-agent.cc	Sun Apr 12 22:41:33 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INESC Porto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
- */
-
-#include "olsr-agent.h"
-
-namespace ns3 {
-namespace olsr {
-
-NS_OBJECT_ENSURE_REGISTERED (Agent);
-
-TypeId 
-Agent::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::olsr::Agent")
-    .SetParent<Object> ();
-  return tid;
-}
-
-}}
--- a/src/routing/olsr/olsr-agent.h	Sun Apr 12 22:41:33 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INESC Porto
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
- */
-
-#ifndef OLSR_AGENT_H
-#define OLSR_AGENT_H
-
-#include "ns3/node.h"
-#include "ns3/olsr-routing-table.h"
-
-namespace ns3 {
-namespace olsr {
-
-/**
- * \brief Class implementing the OLSR state machine
- *
- * This class represents an instance of the OLSR protocol.  It
- * attaches itself to a Node, and its lifecycle is bound to that node.
- * Normally the functions in the ns3::olsr namespace are more simple
- * to use to start OLSR on nodes, but access to the underlying OLSR
- * agent can be useful in order to customize the OLSR parameters.
- * Example:
- *
- * \code
- * Ptr<olsr::Agent> olsr = Agend::CreateDefault ();
- * agent->SetMainInterface (2);
- * agent->Start ();
- * \endcode
- */
-class Agent : public Object
-{
-public:
-  static TypeId GetTypeId (void);
-
-  virtual void SetNode (Ptr<Node> node) = 0;
-
-  /**
-   * \brief Sets the main interface to be used by OLSR
-   *
-   * Normally OLSR supports multiple interfaces, but the protocol
-   * requires the definition of a "main interface".  This interface's
-   * IPv4 address provides the identity of the node, and all outgoing
-   * OLSR routing messages must have the main interface address,
-   * regardless of the actual interface used to transmit the packet.
-   * This method allows one to explicitly select an interface as the
-   * main interface.  It must be called before the agent starts, but
-   * calling it is optional; if not called, the agent tries to guess
-   * and uses a suitable interface.
-   */
-  virtual void SetMainInterface (uint32_t interface) = 0;
-
-  /**
-   * \brief Starts the OLSR protocol operation
-   *
-   * Calling this method essentially bootstraps the OLSR protocol, and
-   * causes the agent to start broadcasting OLSR messages to
-   * neighbors, as well start listening to messages from neighbors.
-   */
-  virtual void Start () = 0;
-
-  virtual Ptr<const olsr::RoutingTable> GetRoutingTable () const = 0;
-};
-
-}} // namespace olsr, ns3
-
-#endif /* OLSR_AGENT_H */
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-repositories.h	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,246 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+///
+/// \file	OLSR_olsr-repositories.h
+/// \brief	Here are defined all data structures needed by an OLSR node.
+///
+
+#ifndef __OLSR_REPOSITORIES_H__
+#define __OLSR_REPOSITORIES_H__
+
+#include <set>
+#include <vector>
+
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+namespace ns3 { namespace olsr {
+
+
+
+/// An Interface Association Tuple.
+struct IfaceAssocTuple
+{
+  /// Interface address of a node.
+  Ipv4Address ifaceAddr;
+  /// Main address of the node.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const IfaceAssocTuple &a, const IfaceAssocTuple &b)
+{
+  return (a.ifaceAddr == b.ifaceAddr
+          && a.mainAddr == b.mainAddr);
+}
+
+static inline std::ostream&
+operator << (std::ostream &os, const IfaceAssocTuple &tuple)
+{
+  os << "IfaceAssocTuple(ifaceAddr=" << tuple.ifaceAddr
+     << ", mainAddr=" << tuple.mainAddr
+     << ", time=" << tuple.time << ")";
+  return os;
+}
+
+/// A Link Tuple.
+struct LinkTuple
+{
+  /// Interface address of the local node.
+  Ipv4Address localIfaceAddr;
+  /// Interface address of the neighbor node.
+  Ipv4Address neighborIfaceAddr;
+  /// The link is considered bidirectional until this time.
+  Time symTime;
+  /// The link is considered unidirectional until this time.
+  Time asymTime;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const LinkTuple &a, const LinkTuple &b)
+{
+  return (a.localIfaceAddr == b.localIfaceAddr
+          && a.neighborIfaceAddr == b.neighborIfaceAddr);
+}
+
+static inline std::ostream&
+operator << (std::ostream &os, const LinkTuple &tuple)
+{
+  os << "LinkTuple(localIfaceAddr=" << tuple.localIfaceAddr
+     << ", neighborIfaceAddr=" << tuple.neighborIfaceAddr
+     << ", symTime=" << tuple.symTime
+     << ", asymTime=" << tuple.asymTime
+     << ", expTime=" << tuple.time;
+  return os;
+}
+
+/// A Neighbor Tuple.
+struct NeighborTuple
+{
+  /// Main address of a neighbor node.
+  Ipv4Address neighborMainAddr;
+  /// Neighbor Type and Link Type at the four less significative digits.
+  enum Status {
+    STATUS_NOT_SYM = 0, // "not symmetric"
+    STATUS_SYM = 1, // "symmetric"
+  } status;
+  /// A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
+  uint8_t willingness;
+};
+
+static inline bool
+operator == (const NeighborTuple &a, const NeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.status == b.status
+          && a.willingness == b.willingness);
+}
+
+static inline std::ostream&
+operator << (std::ostream &os, const NeighborTuple &tuple)
+{
+  os << "NeighborTuple(neighborMainAddr=" << tuple.neighborMainAddr
+     << ", status=" << (tuple.status == NeighborTuple::STATUS_SYM? "SYM" : "NOT_SYM")
+     << ", willingness=" << (int) tuple.willingness << ")";
+  return os;
+}
+
+/// A 2-hop Tuple.
+struct TwoHopNeighborTuple
+{
+  /// Main address of a neighbor.
+  Ipv4Address neighborMainAddr;
+  /// Main address of a 2-hop neighbor with a symmetric link to nb_main_addr.
+  Ipv4Address twoHopNeighborAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;        // previously called 'time_'
+};
+
+static inline std::ostream&
+operator << (std::ostream &os, const TwoHopNeighborTuple &tuple)
+{
+  os << "TwoHopNeighborTuple(neighborMainAddr=" << tuple.neighborMainAddr
+     << ", twoHopNeighborAddr=" << tuple.twoHopNeighborAddr
+     << ", expirationTime=" << tuple.expirationTime
+     << ")";
+  return os;
+}
+
+static inline bool
+operator == (const TwoHopNeighborTuple &a, const TwoHopNeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.twoHopNeighborAddr == b.twoHopNeighborAddr);
+}
+
+/// An MPR-Selector Tuple.
+struct MprSelectorTuple
+{
+  /// Main address of a node which have selected this node as a MPR.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;       // previously called 'time_'
+};
+
+static inline bool
+operator == (const MprSelectorTuple &a, const MprSelectorTuple &b)
+{
+  return (a.mainAddr == b.mainAddr);
+}
+
+
+/// The type "list of interface addresses"
+//typedef std::vector<nsaddr_t> addr_list_t;
+
+/// A Duplicate Tuple
+struct DuplicateTuple
+{
+  /// Originator address of the message.
+  Ipv4Address address;
+  /// Message sequence number.
+  uint16_t sequenceNumber;
+  /// Indicates whether the message has been retransmitted or not.
+  bool retransmitted;
+  /// List of interfaces which the message has been received on.
+  std::vector<Ipv4Address> ifaceList;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const DuplicateTuple &a, const DuplicateTuple &b)
+{
+  return (a.address == b.address
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+/// A Topology Tuple
+struct TopologyTuple
+{
+  /// Main address of the destination.
+  Ipv4Address destAddr;
+  /// Main address of a node which is a neighbor of the destination.
+  Ipv4Address lastAddr;
+  /// Sequence number.
+  uint16_t sequenceNumber;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const TopologyTuple &a, const TopologyTuple &b)
+{
+  return (a.destAddr == b.destAddr
+          && a.lastAddr == b.lastAddr
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+static inline std::ostream&
+operator << (std::ostream &os, const TopologyTuple &tuple)
+{
+  os << "TopologyTuple(destAddr=" << tuple.destAddr
+     << ", lastAddr=" << tuple.lastAddr
+     << ", sequenceNumber=" << (int) tuple.sequenceNumber
+     << ", expirationTime=" << tuple.expirationTime
+     << ")";
+  return os;
+}
+
+
+typedef std::set<Ipv4Address> 			MprSet;	///< MPR Set type.
+typedef std::vector<MprSelectorTuple>		MprSelectorSet;	///< MPR Selector Set type.
+typedef std::vector<LinkTuple>			LinkSet;	///< Link Set type.
+typedef std::vector<NeighborTuple>		NeighborSet;	///< Neighbor Set type.
+typedef std::vector<TwoHopNeighborTuple>	TwoHopNeighborSet; ///< 2-hop Neighbor Set type.
+typedef std::vector<TopologyTuple>		TopologySet;	///< Topology Set type.
+typedef std::vector<DuplicateTuple>		DuplicateSet;	///< Duplicate Set type.
+typedef std::vector<IfaceAssocTuple>		IfaceAssocSet; ///< Interface Association Set type.
+
+
+}}; // namespace ns3, olsr
+
+#endif  /* __OLSR_REPOSITORIES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-routing-protocol.cc	Fri Apr 17 12:33:17 2009 -0700
@@ -0,0 +1,2682 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+
+///
+/// \file	OLSR.cc
+/// \brief	Implementation of OLSR agent and related classes.
+///
+/// This is the main file of this software because %OLSR's behaviour is
+/// implemented here.
+///
+
+#define NS_LOG_APPEND_CONTEXT                                   \
+  if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
+
+
+#include "olsr-routing-protocol.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/enum.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/ipv4-header.h"
+
+/********** Useful macros **********/
+
+///
+/// \brief Gets the delay between a given time and the current time.
+///
+/// If given time is previous to the current one, then this macro returns
+/// a number close to 0. This is used for scheduling events at a certain moment.
+///
+#define DELAY(time) (((time) < (Simulator::Now ())) ? Seconds (0.000001) : \
+                     (time - Simulator::Now () + Seconds (0.000001)))
+
+
+
+///
+/// \brief Period at which a node must cite every link and every neighbor.
+///
+/// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
+///
+#define OLSR_REFRESH_INTERVAL	Seconds (2)
+
+
+/********** Holding times **********/
+
+/// Neighbor holding time.
+#define OLSR_NEIGHB_HOLD_TIME	(Scalar (3) * OLSR_REFRESH_INTERVAL)
+/// Top holding time.
+#define OLSR_TOP_HOLD_TIME	(Scalar (3) * m_tcInterval)
+/// Dup holding time.
+#define OLSR_DUP_HOLD_TIME	Seconds (30)
+/// MID holding time.
+#define OLSR_MID_HOLD_TIME	(Scalar (3) * m_midInterval)
+
+
+/********** Link types **********/
+
+/// Unspecified link type.
+#define OLSR_UNSPEC_LINK	0
+/// Asymmetric link type.
+#define OLSR_ASYM_LINK		1
+/// Symmetric link type.
+#define OLSR_SYM_LINK		2
+/// Lost link type.
+#define OLSR_LOST_LINK		3
+
+/********** Neighbor types **********/
+
+/// Not neighbor type.
+#define OLSR_NOT_NEIGH		0
+/// Symmetric neighbor type.
+#define OLSR_SYM_NEIGH		1
+/// Asymmetric neighbor type.
+#define OLSR_MPR_NEIGH		2
+
+
+/********** Willingness **********/
+
+/// Willingness for forwarding packets from other nodes: never.
+#define OLSR_WILL_NEVER		0
+/// Willingness for forwarding packets from other nodes: low.
+#define OLSR_WILL_LOW		1
+/// Willingness for forwarding packets from other nodes: medium.
+#define OLSR_WILL_DEFAULT	3
+/// Willingness for forwarding packets from other nodes: high.
+#define OLSR_WILL_HIGH		6
+/// Willingness for forwarding packets from other nodes: always.
+#define OLSR_WILL_ALWAYS	7
+
+
+/********** Miscellaneous constants **********/
+
+/// Maximum allowed jitter.
+#define OLSR_MAXJITTER		(m_helloInterval.GetSeconds () / 4)
+/// Maximum allowed sequence number.
+#define OLSR_MAX_SEQ_NUM	65535
+/// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
+#define JITTER (Seconds (UniformVariable().GetValue (0, OLSR_MAXJITTER)))
+
+
+#define OLSR_PORT_NUMBER 698
+/// Maximum number of messages per packet.
+#define OLSR_MAX_MSGS		64
+
+/// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
+#define OLSR_MAX_HELLOS		12
+
+/// Maximum number of addresses advertised on a message.
+#define OLSR_MAX_ADDRS		64
+
+
+namespace ns3 {
+namespace olsr {
+
+NS_LOG_COMPONENT_DEFINE ("OlsrAgent");
+
+
+/********** OLSR class **********/
+
+NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
+
+TypeId 
+RoutingProtocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::olsr::RoutingProtocol")
+    .SetParent<Ipv4RoutingProtocol> ()
+    .AddConstructor<RoutingProtocol> ()
+    .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
+                   TimeValue (Seconds (2)),
+                   MakeTimeAccessor (&RoutingProtocol::m_helloInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("TcInterval", "TC messages emission interval.",
+                   TimeValue (Seconds (5)),
+                   MakeTimeAccessor (&RoutingProtocol::m_tcInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("MidInterval", "MID messages emission interval.  Normally it is equal to TcInterval.",
+                   TimeValue (Seconds (5)),
+                   MakeTimeAccessor (&RoutingProtocol::m_midInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("Willingness", "Willingness of a node to carry and forward traffic for other nodes.",
+                   EnumValue (OLSR_WILL_DEFAULT),
+                   MakeEnumAccessor (&RoutingProtocol::m_willingness),
+                   MakeEnumChecker (OLSR_WILL_NEVER, "never",
+                                    OLSR_WILL_LOW, "low",
+                                    OLSR_WILL_DEFAULT, "default",
+                                    OLSR_WILL_HIGH, "high",
+                                    OLSR_WILL_ALWAYS, "always"))
+    .AddTraceSource ("Rx", "Receive OLSR packet.",
+                     MakeTraceSourceAccessor (&RoutingProtocol::m_rxPacketTrace))
+    .AddTraceSource ("Tx", "Send OLSR packet.",
+                     MakeTraceSourceAccessor (&RoutingProtocol::m_txPacketTrace))
+    .AddTraceSource ("RoutingTableChanged", "The OLSR routing table has changed.",
+		     MakeTraceSourceAccessor (&RoutingProtocol::m_routingTableChanged))
+    ;
+  return tid;
+}
+
+
+RoutingProtocol::RoutingProtocol ()
+  :
+  m_helloTimer (Timer::CANCEL_ON_DESTROY),
+  m_tcTimer (Timer::CANCEL_ON_DESTROY),
+  m_midTimer (Timer::CANCEL_ON_DESTROY)
+{}
+
+RoutingProtocol::~RoutingProtocol ()
+{}
+
+void
+RoutingProtocol::SetNode (Ptr<Node> node)
+{
+  NS_LOG_DEBUG ("Created olsr::RoutingProtocol");
+  m_helloTimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this);
+  m_tcTimer.SetFunction (&RoutingProtocol::TcTimerExpire, this);
+  m_midTimer.SetFunction (&RoutingProtocol::MidTimerExpire, this);
+  m_queuedMessagesTimer.SetFunction (&RoutingProtocol::SendQueuedMessages, this);
+
+  m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_ansn = OLSR_MAX_SEQ_NUM;
+
+  m_linkTupleTimerFirstTime = true;
+
+  m_ipv4 = node->GetObject<Ipv4> ();
+  NS_ASSERT (m_ipv4);
+}
+
+void RoutingProtocol::DoDispose ()
+{
+  m_ipv4 = 0;
+
+  for (std::map< Ptr<Socket>, Ipv4Address >::iterator iter = m_socketAddresses.begin ();
+       iter != m_socketAddresses.end (); iter++)
+    {
+      iter->first->Close ();
+    }
+  m_socketAddresses.clear ();
+
+  Ipv4RoutingProtocol::DoDispose ();
+}
+
+void RoutingProtocol::Start ()
+{
+  if (m_mainAddress == Ipv4Address ())
+    {
+      Ipv4Address loopback ("127.0.0.1");
+      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+        {
+          // Use primary address, if multiple
+          Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
+          if (addr != loopback)
+            {
+              m_mainAddress = addr;
+              break;
+            }
+        }
+
+      NS_ASSERT (m_mainAddress != Ipv4Address ());
+    }
+
+  NS_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress);
+
+  Ipv4Address loopback ("127.0.0.1");
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
+      if (addr == loopback)
+        continue;
+
+      if (addr != m_mainAddress)
+        {
+          // Create never expiring interface association tuple entries for our
+          // own network interfaces, so that GetMainAddress () works to
+          // translate the node's own interface addresses into the main address.
+          IfaceAssocTuple tuple;
+          tuple.ifaceAddr = addr;
+          tuple.mainAddr = m_mainAddress;
+          AddIfaceAssocTuple (tuple);
+          NS_ASSERT (GetMainAddress (addr) == m_mainAddress);
+        }
+
+      // Create a socket to listen only on this interface
+      Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (), 
+        UdpSocketFactory::GetTypeId()); 
+      socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvOlsr,  this));
+      if (socket->Bind (InetSocketAddress (addr, OLSR_PORT_NUMBER)))
+        {
+          NS_FATAL_ERROR ("Failed to bind() OLSR receive socket");
+        }
+      socket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER));
+      m_socketAddresses[socket] = addr;
+    }
+
+  HelloTimerExpire ();
+  TcTimerExpire ();
+  MidTimerExpire ();
+
+  NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started");
+}
+
+void RoutingProtocol::SetMainInterface (uint32_t interface)
+{
+  m_mainAddress = m_ipv4->GetAddress (interface, 0).GetLocal ();
+}
+
+
+//
+// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
+void
+RoutingProtocol::RecvOlsr (Ptr<Socket> socket)
+{
+  Ptr<Packet> receivedPacket;
+  Address sourceAddress;
+  receivedPacket = socket->RecvFrom (sourceAddress);
+
+  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
+  Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
+  Ipv4Address receiverIfaceAddr = m_socketAddresses[socket];
+  NS_ASSERT (receiverIfaceAddr != Ipv4Address ());
+  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet from "
+                << senderIfaceAddr << " to " << receiverIfaceAddr);
+  
+  // All routing messages are sent from and to port RT_PORT,
+  // so we check it.
+  NS_ASSERT (inetSourceAddr.GetPort () == OLSR_PORT_NUMBER);
+  
+  Ptr<Packet> packet = receivedPacket;
+
+  olsr::PacketHeader olsrPacketHeader;
+  packet->RemoveHeader (olsrPacketHeader);
+  NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSerializedSize ());
+  uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSerializedSize ();
+
+  MessageList messages;
+  
+  while (sizeLeft)
+    {
+      MessageHeader messageHeader;
+      if (packet->RemoveHeader (messageHeader) == 0)
+        NS_ASSERT (false);
+      
+      sizeLeft -= messageHeader.GetSerializedSize ();
+
+      NS_LOG_DEBUG ("Olsr Msg received with type "
+                << std::dec << int (messageHeader.GetMessageType ())
+                << " TTL=" << int (messageHeader.GetTimeToLive ())
+                << " origAddr=" << messageHeader.GetOriginatorAddress ());
+      messages.push_back (messageHeader);
+    }
+
+  m_rxPacketTrace (olsrPacketHeader, messages);
+
+  for (MessageList::const_iterator messageIter = messages.begin ();
+       messageIter != messages.end (); messageIter++)
+    {
+      const MessageHeader &messageHeader = *messageIter;
+      // If ttl is less than or equal to zero, or
+      // the receiver is the same as the originator,
+      // the message must be silently dropped
+      if (messageHeader.GetTimeToLive () == 0
+          || messageHeader.GetOriginatorAddress () == m_mainAddress)
+        {
+          packet->RemoveAtStart (messageHeader.GetSerializedSize ()
+                                 - messageHeader.GetSerializedSize ());
+          continue;
+        }
+
+      // If the message has been processed it must not be processed again
+      bool do_forwarding = true;
+      DuplicateTuple *duplicated = m_state.FindDuplicateTuple
+        (messageHeader.GetOriginatorAddress (),
+         messageHeader.GetMessageSequenceNumber ());
+
+      // Get main address of the peer, which may be different from the packet source address
+//       const IfaceAssocTuple *ifaceAssoc = m_state.FindIfaceAssocTuple (inetSourceAddr.GetIpv4 ());
+//       Ipv4Address peerMainAddress;
+//       if (ifaceAssoc != NULL)
+//         {
+//           peerMainAddress = ifaceAssoc->mainAddr;
+//         }
+//       else
+//         {
+//           peerMainAddress = inetSourceAddr.GetIpv4 () ;
+//         }
+      
+      if (duplicated == NULL)
+        {
+          switch (messageHeader.GetMessageType ())
+            {
+            case olsr::MessageHeader::HELLO_MESSAGE:
+              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                            << "s OLSR node " << m_mainAddress
+                            << " received HELLO message of size " << messageHeader.GetSerializedSize ());
+              ProcessHello (messageHeader, receiverIfaceAddr, senderIfaceAddr);
+              break;
+
+            case olsr::MessageHeader::TC_MESSAGE:
+              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                            << "s OLSR node " << m_mainAddress
+                            << " received TC message of size " << messageHeader.GetSerializedSize ());
+              ProcessTc (messageHeader, senderIfaceAddr);
+              break;
+
+            case olsr::MessageHeader::MID_MESSAGE:
+              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                            << "s OLSR node " << m_mainAddress
+                            <<  " received MID message of size " << messageHeader.GetSerializedSize ());
+              ProcessMid (messageHeader, senderIfaceAddr);
+              break;
+
+            default:
+              NS_LOG_DEBUG ("OLSR message type " <<
+                        int (messageHeader.GetMessageType ()) <<
+                        " not implemented");
+            }
+        }
+      else
+        {
+          NS_LOG_DEBUG ("OLSR message is duplicated, not reading it.");
+      
+          // If the message has been considered for forwarding, it should
+          // not be retransmitted again
+          for (std::vector<Ipv4Address>::const_iterator it = duplicated->ifaceList.begin ();
+               it != duplicated->ifaceList.end(); it++)
+            {
+              if (*it == receiverIfaceAddr)
+                {
+                  do_forwarding = false;
+                  break;
+                }
+            }
+        }
+      
+      if (do_forwarding)
+        {
+          // HELLO messages are never forwarded.
+          // TC and MID messages are forwarded using the default algorithm.
+          // Remaining messages are also forwarded using the default algorithm.
+          if (messageHeader.GetMessageType ()  != olsr::MessageHeader::HELLO_MESSAGE)
+            {
+              ForwardDefault (messageHeader, duplicated,
+                              receiverIfaceAddr, inetSourceAddr.GetIpv4 ());
+            }
+        }
+	
+    }
+
+  // After processing all OLSR messages, we must recompute the routing table
+  RoutingTableComputation ();
+}
+
+///
+/// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
+///
+/// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
+/// \return the degree of the node.
+///
+int
+RoutingProtocol::Degree (NeighborTuple const &tuple)
+{
+  int degree = 0;
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+      if (nb2hop_tuple.neighborMainAddr == tuple.neighborMainAddr)
+        {
+          const NeighborTuple *nb_tuple =
+            m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr);
+          if (nb_tuple == NULL)
+            degree++;
+        }
+    }
+  return degree;
+}
+
+///
+/// \brief Computates MPR set of a node following RFC 3626 hints.
+///
+void
+RoutingProtocol::MprComputation()
+{
+  NS_LOG_FUNCTION (this);
+  
+  // MPR computation should be done for each interface. See section 8.3.1
+  // (RFC 3626) for details.
+  MprSet mprSet;
+	
+  
+  // N is the subset of neighbors of the node, which are
+  // neighbor "of the interface I"
+  NeighborSet N;
+  for (NeighborSet::const_iterator neighbor = m_state.GetNeighbors ().begin();
+       neighbor != m_state.GetNeighbors ().end (); neighbor++)
+    {
+      if (neighbor->status == NeighborTuple::STATUS_SYM) // I think that we need this check
+        {
+          N.push_back (*neighbor);
+        }
+    }
+	
+  // N2 is the set of 2-hop neighbors reachable from "the interface
+  // I", excluding:
+  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+  // (ii)  the node performing the computation
+  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+  //       link to this node on some interface.
+  TwoHopNeighborSet N2;
+  for (TwoHopNeighborSet::const_iterator twoHopNeigh = m_state.GetTwoHopNeighbors ().begin ();
+       twoHopNeigh != m_state.GetTwoHopNeighbors ().end (); twoHopNeigh++)
+    {
+      // excluding:
+      // (ii)  the node performing the computation
+      if (twoHopNeigh->twoHopNeighborAddr == m_mainAddress)
+        {
+          continue;
+        }
+
+      //  excluding:
+      // (i)   the nodes only reachable by members of N with willingness WILL_NEVER      
+      bool ok = false;
+      for (NeighborSet::const_iterator neigh = N.begin ();
+           neigh != N.end (); neigh++)
+        {
+          if (neigh->neighborMainAddr == twoHopNeigh->neighborMainAddr)
+            {
+              if (neigh->willingness == OLSR_WILL_NEVER)
+                {
+                  ok = false;
+                  break;
+                }
+              else
+                {
+                  ok = true;
+                  break;
+                }
+            }
+        }
+      if (!ok)
+        {
+          continue;
+        }
+      
+      // excluding:
+      // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+      //       link to this node on some interface.
+      for (NeighborSet::const_iterator neigh = N.begin ();
+           neigh != N.end (); neigh++)
+        {
+          if (neigh->neighborMainAddr == twoHopNeigh->twoHopNeighborAddr)
+            {
+              ok = false;
+              break;
+            }
+        }
+
+      if (ok)
+        {
+          N2.push_back (*twoHopNeigh);
+        }
+    }
+
+  NS_LOG_DEBUG ("Size of N2: " << N2.size ());  
+
+  // 1. Start with an MPR set made of all members of N with
+  // N_willingness equal to WILL_ALWAYS
+  for (NeighborSet::const_iterator neighbor = N.begin (); neighbor != N.end (); neighbor++)
+    {
+      if (neighbor->willingness == OLSR_WILL_ALWAYS)
+        {
+          mprSet.insert (neighbor->neighborMainAddr);
+          // (not in RFC but I think is needed: remove the 2-hop
+          // neighbors reachable by the MPR from N2)
+          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+               twoHopNeigh != N2.end (); )
+            {
+              if (twoHopNeigh->neighborMainAddr == neighbor->neighborMainAddr)
+                {
+                  twoHopNeigh = N2.erase (twoHopNeigh);
+                }
+              else
+                {
+                  twoHopNeigh++;
+                }
+            }
+        }
+    }
+  
+  // 2. Calculate D(y), where y is a member of N, for all nodes in N.
+  // (we do this later)
+	
+  // 3. Add to the MPR set those nodes in N, which are the *only*
+  // nodes to provide reachability to a node in N2.
+  std::set<Ipv4Address> coveredTwoHopNeighbors;
+  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin (); twoHopNeigh != N2.end (); twoHopNeigh++)
+    {
+      NeighborSet::const_iterator onlyNeighbor = N.end ();
+      
+      for (NeighborSet::const_iterator neighbor = N.begin ();
+           neighbor != N.end (); neighbor++)
+        {
+          if (neighbor->neighborMainAddr == twoHopNeigh->neighborMainAddr)
+            {
+              if (onlyNeighbor == N.end ())
+                {
+                  onlyNeighbor = neighbor;
+                }
+              else
+                {
+                  onlyNeighbor = N.end ();
+                  break;
+                }
+            }
+        }
+      if (onlyNeighbor != N.end ())
+        {
+          mprSet.insert (onlyNeighbor->neighborMainAddr);
+          coveredTwoHopNeighbors.insert (twoHopNeigh->twoHopNeighborAddr);
+        }
+    }
+  // Remove the nodes from N2 which are now covered by a node in the MPR set.
+  for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+       twoHopNeigh != N2.end (); )
+    {
+      if (coveredTwoHopNeighbors.find (twoHopNeigh->twoHopNeighborAddr) != coveredTwoHopNeighbors.end ())
+        {
+          twoHopNeigh = N2.erase (twoHopNeigh);
+        }
+      else
+        {
+          twoHopNeigh++;
+        }
+    }
+	
+  // 4. While there exist nodes in N2 which are not covered by at
+  // least one node in the MPR set:
+  while (N2.begin () != N2.end ())
+    {
+      // 4.1. For each node in N, calculate the reachability, i.e., the
+      // number of nodes in N2 which are not yet covered by at
+      // least one node in the MPR set, and which are reachable
+      // through this 1-hop neighbor
+      std::map<int, std::vector<const NeighborTuple *> > reachability;
+      std::set<int> rs;
+      for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
+        {
+          NeighborTuple const &nb_tuple = *it;
+          int r = 0;
+          for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it2;
+              if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
+                r++;
+            }
+          rs.insert (r);
+          reachability[r].push_back (&nb_tuple);
+        }
+      
+      // 4.2. Select as a MPR the node with highest N_willingness among
+      // the nodes in N with non-zero reachability. In case of
+      // multiple choice select the node which provides
+      // reachability to the maximum number of nodes in N2. In
+      // case of multiple nodes providing the same amount of
+      // reachability, select the node as MPR whose D(y) is
+      // greater. Remove the nodes from N2 which are now covered
+      // by a node in the MPR set.
+      NeighborTuple const *max = NULL;
+      int max_r = 0;
+      for (std::set<int>::iterator it = rs.begin (); it != rs.end (); it++)
+        {
+          int r = *it;
+          if (r == 0)
+            {
+              continue;
+            }
+          for (std::vector<const NeighborTuple *>::iterator it2 = reachability[r].begin ();
+               it2 != reachability[r].end (); it2++)
+            {
+              const NeighborTuple *nb_tuple = *it2;
+              if (max == NULL || nb_tuple->willingness > max->willingness)
+                {
+                  max = nb_tuple;
+                  max_r = r;
+                }
+              else if (nb_tuple->willingness == max->willingness)
+                {
+                  if (r > max_r)
+                    {
+                      max = nb_tuple;
+                      max_r = r;
+                    }
+                  else if (r == max_r)
+                    {
+                      if (Degree (*nb_tuple) > Degree (*max))
+                        {
+                          max = nb_tuple;
+                          max_r = r;
+                        }
+                    }
+                }
+            }
+        }
+
+      if (max != NULL)
+        {
+          mprSet.insert (max->neighborMainAddr);
+          for (TwoHopNeighborSet::iterator twoHopNeigh = N2.begin ();
+               twoHopNeigh != N2.end (); )
+            {
+              if (twoHopNeigh->neighborMainAddr == max->neighborMainAddr)
+                {
+                  twoHopNeigh = N2.erase (twoHopNeigh);
+                }
+              else
+                {
+                  twoHopNeigh++;
+                }
+            }
+        }
+    }
+
+#ifdef NS3_LOG_ENABLE
+  {
+    std::ostringstream os;
+    os << "[";
+    for (MprSet::const_iterator iter = mprSet.begin ();
+         iter != mprSet.end (); iter++)
+      {
+        MprSet::const_iterator next = iter;
+        next++;
+        os << *iter;
+        if (next != mprSet.end ())
+          os << ", ";
+      }
+    os << "]";
+    NS_LOG_DEBUG ("Computed MPR set for node " << m_mainAddress << ": " << os.str ());
+  }
+#endif
+
+  m_state.SetMprSet (mprSet);
+}
+
+///
+/// \brief Gets the main address associated with a given interface address.
+///
+/// \param iface_addr the interface address.
+/// \return the corresponding main address.
+///
+Ipv4Address
+RoutingProtocol::GetMainAddress (Ipv4Address iface_addr) const
+{
+  const IfaceAssocTuple *tuple =
+    m_state.FindIfaceAssocTuple (iface_addr);
+  
+  if (tuple != NULL)
+    return tuple->mainAddr;
+  else
+    return iface_addr;
+}
+
+///
+/// \brief Creates the routing table of the node following RFC 3626 hints.
+///
+void
+RoutingProtocol::RoutingTableComputation ()
+{
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds () << " s: Node " << m_mainAddress
+                << ": RoutingTableComputation begin...");
+
+  // 1. All the entries from the routing table are removed.
+  Clear ();
+	
+  // 2. The new routing entries are added starting with the
+  // symmetric neighbors (h=1) as the destination nodes.
+  const NeighborSet &neighborSet = m_state.GetNeighbors ();
+  for (NeighborSet::const_iterator it = neighborSet.begin ();
+       it != neighborSet.end(); it++)
+    {
+      NeighborTuple const &nb_tuple = *it;
+      NS_LOG_DEBUG ("Looking at neighbor tuple: " << nb_tuple);
+      if (nb_tuple.status == NeighborTuple::STATUS_SYM)
+        {
+          bool nb_main_addr = false;
+          const LinkTuple *lt = NULL;
+          const LinkSet &linkSet = m_state.GetLinks ();
+          for (LinkSet::const_iterator it2 = linkSet.begin();
+               it2 != linkSet.end(); it2++)
+            {
+              LinkTuple const &link_tuple = *it2;
+              NS_LOG_DEBUG ("Looking at link tuple: " << link_tuple
+                            << (link_tuple.time >= Simulator::Now ()? "" : " (expired)"));
+              if ((GetMainAddress (link_tuple.neighborIfaceAddr) == nb_tuple.neighborMainAddr)
+                  && link_tuple.time >= Simulator::Now ())
+                {
+                  NS_LOG_LOGIC ("Link tuple matches neighbor " << nb_tuple.neighborMainAddr
+                                << " => adding routing table entry to neighbor");
+                  lt = &link_tuple;
+                  AddEntry (link_tuple.neighborIfaceAddr,
+                            link_tuple.neighborIfaceAddr,
+                            link_tuple.localIfaceAddr,
+                            1);
+                  if (link_tuple.neighborIfaceAddr == nb_tuple.neighborMainAddr)
+                    {
+                      nb_main_addr = true;
+                    }
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("Link tuple: linkMainAddress= " << GetMainAddress (link_tuple.neighborIfaceAddr)
+                                << "; neighborMainAddr =  " << nb_tuple.neighborMainAddr
+                                << "; expired=" << int (link_tuple.time < Simulator::Now ())
+                                << " => IGNORE");
+                }
+            }
+
+          // If, in the above, no R_dest_addr is equal to the main
+          // address of the neighbor, then another new routing entry
+          // with MUST be added, with:
+          //      R_dest_addr  = main address of the neighbor;
+          //      R_next_addr  = L_neighbor_iface_addr of one of the
+          //                     associated link tuple with L_time >= current time;
+          //      R_dist       = 1;
+          //      R_iface_addr = L_local_iface_addr of the
+          //                     associated link tuple.
+          if (!nb_main_addr && lt != NULL)
+            {
+              NS_LOG_LOGIC ("no R_dest_addr is equal to the main address of the neighbor "
+                            "=> adding additional routing entry");
+              AddEntry(nb_tuple.neighborMainAddr,
+                       lt->neighborIfaceAddr,
+                       lt->localIfaceAddr,
+                       1);
+            }
+        }
+    }
+  
+  //  3. for each node in N2, i.e., a 2-hop neighbor which is not a
+  //  neighbor node or the node itself, and such that there exist at
+  //  least one entry in the 2-hop neighbor set where
+  //  N_neighbor_main_addr correspond to a neighbor node with
+  //  willingness different of WILL_NEVER,
+  const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+  for (TwoHopNeighborSet::const_iterator it = twoHopNeighbors.begin ();
+       it != twoHopNeighbors.end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+
+      NS_LOG_LOGIC ("Looking at two-hop neighbor tuple: " << nb2hop_tuple);
+
+      // a 2-hop neighbor which is not a neighbor node or the node itself
+      if (m_state.FindNeighborTuple (nb2hop_tuple.twoHopNeighborAddr))
+        {
+          NS_LOG_LOGIC ("Two-hop neighbor tuple is also neighbor; skipped.");
+          continue;
+        }
+
+      if (nb2hop_tuple.twoHopNeighborAddr == m_mainAddress)
+        {
+          NS_LOG_LOGIC ("Two-hop neighbor is self; skipped.");
+          continue;
+        }
+
+      // ...and such that there exist at least one entry in the 2-hop
+      // neighbor set where N_neighbor_main_addr correspond to a
+      // neighbor node with willingness different of WILL_NEVER...
+      bool nb2hopOk = false;
+      for (NeighborSet::const_iterator neighbor = neighborSet.begin ();
+           neighbor != neighborSet.end(); neighbor++)
+        {
+          if (neighbor->neighborMainAddr == nb2hop_tuple.neighborMainAddr
+              && neighbor->willingness != OLSR_WILL_NEVER)
+            {
+              nb2hopOk = true;
+              break;
+            }
+        }
+      if (!nb2hopOk)
+        {
+          NS_LOG_LOGIC ("Two-hop neighbor tuple skipped: 2-hop neighbor "
+                        << nb2hop_tuple.twoHopNeighborAddr
+                        << " is attached to neighbor " << nb2hop_tuple.neighborMainAddr
+                        << ", which was not found in the Neighbor Set.");
+          continue;
+        }
+      
+      // one selects one 2-hop tuple and creates one entry in the routing table with:
+      //                R_dest_addr  =  the main address of the 2-hop neighbor;
+      //                R_next_addr  = the R_next_addr of the entry in the
+      //                               routing table with:
+      //                                   R_dest_addr == N_neighbor_main_addr
+      //                                                  of the 2-hop tuple;
+      //                R_dist       = 2;
+      //                R_iface_addr = the R_iface_addr of the entry in the
+      //                               routing table with:
+      //                                   R_dest_addr == N_neighbor_main_addr
+      //                                                  of the 2-hop tuple;
+      RoutingTableEntry entry;
+      bool foundEntry = Lookup (nb2hop_tuple.neighborMainAddr, entry);
+      if (foundEntry)
+        {
+          NS_LOG_LOGIC ("Adding routing entry for two-hop neighbor.");
+          AddEntry (nb2hop_tuple.twoHopNeighborAddr,
+                                    entry.nextAddr,
+                                    entry.interface,
+                                    2);
+        }
+      else
+        {
+          NS_LOG_LOGIC ("NOT adding routing entry for two-hop neighbor ("
+                        << nb2hop_tuple.twoHopNeighborAddr
+                        << " not found in the routing table)");
+        }
+    }
+  
+  for (uint32_t h = 2; ; h++)
+    {
+      bool added = false;
+		
+      // 3.1. For each topology entry in the topology table, if its
+      // T_dest_addr does not correspond to R_dest_addr of any
+      // route entry in the routing table AND its T_last_addr
+      // corresponds to R_dest_addr of a route entry whose R_dist
+      // is equal to h, then a new route entry MUST be recorded in
+      // the routing table (if it does not already exist)
+      const TopologySet &topology = m_state.GetTopologySet ();
+      for (TopologySet::const_iterator it = topology.begin ();
+           it != topology.end (); it++)
+        {
+          const TopologyTuple &topology_tuple = *it;
+          NS_LOG_LOGIC ("Looking at topology tuple: " << topology_tuple);
+
+          RoutingTableEntry destAddrEntry, lastAddrEntry;
+          bool have_destAddrEntry = Lookup (topology_tuple.destAddr, destAddrEntry);
+          bool have_lastAddrEntry = Lookup (topology_tuple.lastAddr, lastAddrEntry);
+          if (!have_destAddrEntry && have_lastAddrEntry && lastAddrEntry.distance == h)
+            {
+              NS_LOG_LOGIC ("Adding routing table entry based on the topology tuple.");
+              // then a new route entry MUST be recorded in
+              //                the routing table (if it does not already exist) where:
+              //                     R_dest_addr  = T_dest_addr;
+              //                     R_next_addr  = R_next_addr of the recorded
+              //                                    route entry where:
+              //                                    R_dest_addr == T_last_addr
+              //                     R_dist       = h+1; and
+              //                     R_iface_addr = R_iface_addr of the recorded
+              //                                    route entry where:
+              //                                       R_dest_addr == T_last_addr.
+              AddEntry (topology_tuple.destAddr,
+                        lastAddrEntry.nextAddr,
+                        lastAddrEntry.interface,
+                        h + 1);
+              added = true;
+            }
+          else
+            {
+              NS_LOG_LOGIC ("NOT adding routing table entry based on the topology tuple: "
+                            "have_destAddrEntry=" << have_destAddrEntry
+                            << " have_lastAddrEntry=" << have_lastAddrEntry
+                            << " lastAddrEntry.distance=" << (int) lastAddrEntry.distance
+                            << " (h=" << h << ")");
+            }
+        }
+      
+      if (!added)
+        break;
+    }
+
+  // 4. For each entry in the multiple interface association base
+  // where there exists a routing entry such that:
+  //	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
+  // AND there is no routing entry such that:
+  //	R_dest_addr  == I_iface_addr
+  const IfaceAssocSet &ifaceAssocSet = m_state.GetIfaceAssocSet ();
+  for (IfaceAssocSet::const_iterator it = ifaceAssocSet.begin ();
+       it != ifaceAssocSet.end (); it++)
+    {
+      IfaceAssocTuple const &tuple = *it;
+      RoutingTableEntry entry1, entry2;
+      bool have_entry1 = Lookup (tuple.mainAddr, entry1);
+      bool have_entry2 = Lookup (tuple.ifaceAddr, entry2);
+      if (have_entry1 && !have_entry2)
+        {
+          // then a route entry is created in the routing table with:
+          //       R_dest_addr  =  I_iface_addr (of the multiple interface
+          //                                     association entry)
+          //       R_next_addr  =  R_next_addr  (of the recorded route entry)
+          //       R_dist       =  R_dist       (of the recorded route entry)
+          //       R_iface_addr =  R_iface_addr (of the recorded route entry).
+          AddEntry (tuple.ifaceAddr,
+                    entry1.nextAddr,
+                    entry1.interface,
+                    entry1.distance);
+        }
+    }
+
+  NS_LOG_DEBUG ("Node " << m_mainAddress << ": RoutingTableComputation end.");
+  m_routingTableChanged (GetSize ());
+}
+
+
+///
+/// \brief Processes a HELLO message following RFC 3626 specification.
+///
+/// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
+/// Selector Set are performed.
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+/// \param receiver_iface the address of the interface where the message was received from.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+RoutingProtocol::ProcessHello (const olsr::MessageHeader &msg,
+                         const Ipv4Address &receiverIface,
+                         const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Hello &hello = msg.GetHello ();
+
+  LinkSensing (msg, hello, receiverIface, senderIface);
+
+#ifdef NS3_LOG_ENABLE
+  {
+    const LinkSet &links = m_state.GetLinks ();
+    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                  << "s ** BEGIN dump Link Set for OLSR Node " << m_mainAddress);
+    for (LinkSet::const_iterator link = links.begin (); link != links.end (); link++)
+      {
+        NS_LOG_DEBUG(*link);
+      }
+    NS_LOG_DEBUG ("** END dump Link Set for OLSR Node " << m_mainAddress);
+
+    const NeighborSet &neighbors = m_state.GetNeighbors ();
+    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                  << "s ** BEGIN dump Neighbor Set for OLSR Node " << m_mainAddress);
+    for (NeighborSet::const_iterator neighbor = neighbors.begin (); neighbor != neighbors.end (); neighbor++)
+      {
+        NS_LOG_DEBUG(*neighbor);
+      }
+    NS_LOG_DEBUG ("** END dump Neighbor Set for OLSR Node " << m_mainAddress);
+  }
+#endif
+
+  PopulateNeighborSet (msg, hello);
+  PopulateTwoHopNeighborSet (msg, hello);
+
+#ifdef NS3_LOG_ENABLE
+  {
+    const TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                  << "s ** BEGIN dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
+    for (TwoHopNeighborSet::const_iterator tuple = twoHopNeighbors.begin ();
+         tuple != twoHopNeighbors.end (); tuple++)
+      {
+        NS_LOG_DEBUG(*tuple);
+      }
+    NS_LOG_DEBUG ("** END dump TwoHopNeighbor Set for OLSR Node " << m_mainAddress);
+  }
+#endif
+
+  MprComputation ();
+  PopulateMprSelectorSet (msg, hello);
+}
+
+///
+/// \brief Processes a TC message following RFC 3626 specification.
+///
+/// The Topology Set is updated (if needed) with the information of
+/// the received TC message.
+///
+/// \param msg the %OLSR message which contains the TC message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+RoutingProtocol::ProcessTc (const olsr::MessageHeader &msg,
+                      const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Tc &tc = msg.GetTc ();
+  Time now = Simulator::Now ();
+	
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  const LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (link_tuple == NULL)
+    return;
+	
+  // 2. If there exist some tuple in the topology set where:
+  // 	T_last_addr == originator address AND
+  // 	T_seq       >  ANSN,
+  // then further processing of this TC message MUST NOT be
+  // performed.
+  const TopologyTuple *topologyTuple =
+    m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.ansn);
+  if (topologyTuple != NULL)
+    return;
+	
+  // 3. All tuples in the topology set where:
+  //	T_last_addr == originator address AND
+  //	T_seq       <  ANSN
+  // MUST be removed from the topology set.
+  m_state.EraseOlderTopologyTuples (msg.GetOriginatorAddress (), tc.ansn);
+
+  // 4. For each of the advertised neighbor main address received in
+  // the TC message:
+  for (std::vector<Ipv4Address>::const_iterator i = tc.neighborAddresses.begin ();
+       i != tc.neighborAddresses.end (); i++)
+    {
+      const Ipv4Address &addr = *i;
+      // 4.1. If there exist some tuple in the topology set where:
+      // 	T_dest_addr == advertised neighbor main address, AND
+      // 	T_last_addr == originator address,
+      // then the holding time of that tuple MUST be set to:
+      // 	T_time      =  current time + validity time.
+      TopologyTuple *topologyTuple =
+        m_state.FindTopologyTuple (addr, msg.GetOriginatorAddress ());
+
+      if (topologyTuple != NULL)
+        {
+          topologyTuple->expirationTime = now + msg.GetVTime ();
+        }
+      else
+        {
+          // 4.2. Otherwise, a new tuple MUST be recorded in the topology
+          // set where:
+          //	T_dest_addr = advertised neighbor main address,
+          //	T_last_addr = originator address,
+          //	T_seq       = ANSN,
+          //	T_time      = current time + validity time.
+          TopologyTuple topologyTuple;;
+          topologyTuple.destAddr = addr;
+          topologyTuple.lastAddr = msg.GetOriginatorAddress ();
+          topologyTuple.sequenceNumber = tc.ansn;
+          topologyTuple.expirationTime = now + msg.GetVTime ();
+          AddTopologyTuple (topologyTuple);
+
+          // Schedules topology tuple deletion
+          m_events.Track (Simulator::Schedule (DELAY (topologyTuple.expirationTime),
+                                               &RoutingProtocol::TopologyTupleTimerExpire,
+                                               this,
+                                               topologyTuple.destAddr,
+                                               topologyTuple.lastAddr));
+        }
+    }
+
+#ifdef NS3_LOG_ENABLE
+  {
+    const TopologySet &topology = m_state.GetTopologySet ();
+    NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                  << "s ** BEGIN dump TopologySet for OLSR Node " << m_mainAddress);
+    for (TopologySet::const_iterator tuple = topology.begin ();
+         tuple != topology.end (); tuple++)
+      {
+        NS_LOG_DEBUG (*tuple);
+      }
+    NS_LOG_DEBUG ("** END dump TopologySet Set for OLSR Node " << m_mainAddress);
+  }
+#endif
+}
+
+///
+/// \brief Processes a MID message following RFC 3626 specification.
+///
+/// The Interface Association Set is updated (if needed) with the information
+/// of the received MID message.
+///
+/// \param msg the %OLSR message which contains the MID message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+RoutingProtocol::ProcessMid (const olsr::MessageHeader &msg,
+                       const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Mid &mid = msg.GetMid ();
+  Time now = Simulator::Now ();
+  
+  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface);
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (linkTuple == NULL)
+    {
+      NS_LOG_LOGIC ("Node " << m_mainAddress <<
+                    ": the sender interface of this message is not in the "
+                    "symmetric 1-hop neighborhood of this node,"
+                    " the message MUST be discarded.");
+      return;
+    }
+	
+  // 2. For each interface address listed in the MID message
+  for (std::vector<Ipv4Address>::const_iterator i = mid.interfaceAddresses.begin ();
+       i != mid.interfaceAddresses.end (); i++)
+    {
+      bool updated = false;
+      IfaceAssocSet &ifaceAssoc = m_state.GetIfaceAssocSetMutable ();
+      for (IfaceAssocSet::iterator tuple = ifaceAssoc.begin();
+           tuple != ifaceAssoc.end(); tuple++)
+        {
+          if (tuple->ifaceAddr == *i
+              && tuple->mainAddr == msg.GetOriginatorAddress ())
+            {
+              NS_LOG_LOGIC ("IfaceAssoc updated: " << *tuple);
+              tuple->time = now + msg.GetVTime ();
+              updated = true;
+            }
+        }
+      if (!updated)
+        {
+          IfaceAssocTuple tuple;
+          tuple.ifaceAddr = *i;
+          tuple.mainAddr = msg.GetOriginatorAddress ();
+          tuple.time = now + msg.GetVTime ();
+          AddIfaceAssocTuple (tuple);
+          NS_LOG_LOGIC ("New IfaceAssoc added: " << tuple);
+          // Schedules iface association tuple deletion
+          Simulator::Schedule (DELAY (tuple.time),
+                               &RoutingProtocol::IfaceAssocTupleTimerExpire, this, tuple.ifaceAddr);
+        }
+    }
+
+  // 3. (not part of the RFC) iterate over all NeighborTuple's and
+  // TwoHopNeighborTuples, update the neighbor addresses taking into account
+  // the new MID information.
+  NeighborSet &neighbors = m_state.GetNeighbors ();
+  for (NeighborSet::iterator neighbor = neighbors.begin (); neighbor != neighbors.end(); neighbor++)
+    {
+      neighbor->neighborMainAddr = GetMainAddress (neighbor->neighborMainAddr);
+    }
+
+  TwoHopNeighborSet &twoHopNeighbors = m_state.GetTwoHopNeighbors ();
+  for (TwoHopNeighborSet::iterator twoHopNeighbor = twoHopNeighbors.begin ();
+       twoHopNeighbor != twoHopNeighbors.end(); twoHopNeighbor++)
+    {
+      twoHopNeighbor->neighborMainAddr = GetMainAddress (twoHopNeighbor->neighborMainAddr);
+      twoHopNeighbor->twoHopNeighborAddr = GetMainAddress (twoHopNeighbor->twoHopNeighborAddr);
+    }
+  NS_LOG_DEBUG ("Node " << m_mainAddress << " ProcessMid from " << senderIface << " -> END.");
+}
+
+
+///
+/// \brief OLSR's default forwarding algorithm.
+///
+/// See RFC 3626 for details.
+///
+/// \param p the %OLSR packet which has been received.
+/// \param msg the %OLSR message which must be forwarded.
+/// \param dup_tuple NULL if the message has never been considered for forwarding,
+/// or a duplicate tuple in other case.
+/// \param local_iface the address of the interface where the message was received from.
+///
+void
+RoutingProtocol::ForwardDefault (olsr::MessageHeader olsrMessage,
+                               DuplicateTuple *duplicated,
+                               const Ipv4Address &localIface,
+                               const Ipv4Address &senderAddress)
+{
+  Time now = Simulator::Now ();
+  
+  // If the sender interface address is not in the symmetric
+  // 1-hop neighborhood the message must not be forwarded
+  const LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderAddress, now);
+  if (linkTuple == NULL)
+    return;
+
+  // If the message has already been considered for forwarding,
+  // it must not be retransmitted again
+  if (duplicated != NULL && duplicated->retransmitted)
+    {
+      NS_LOG_LOGIC (Simulator::Now () << "Node " << m_mainAddress << " does not forward a message received"
+                    " from " << olsrMessage.GetOriginatorAddress () << " because it is duplicated");
+      return;
+    }
+	
+  // If the sender interface address is an interface address
+  // of a MPR selector of this node and ttl is greater than 1,
+  // the message must be retransmitted
+  bool retransmitted = false;
+  if (olsrMessage.GetTimeToLive () > 1)
+    {
+      const MprSelectorTuple *mprselTuple =
+        m_state.FindMprSelectorTuple (GetMainAddress (senderAddress));
+      if (mprselTuple != NULL)
+        {
+          olsrMessage.SetTimeToLive (olsrMessage.GetTimeToLive () - 1);
+          olsrMessage.SetHopCount (olsrMessage.GetHopCount () + 1);
+          // We have to introduce a random delay to avoid
+          // synchronization with neighbors.
+          QueueMessage (olsrMessage, JITTER);
+          retransmitted = true;
+        }
+    }
+	
+  // Update duplicate tuple...
+  if (duplicated != NULL)
+    {
+      duplicated->expirationTime = now + OLSR_DUP_HOLD_TIME;
+      duplicated->retransmitted = retransmitted;
+      duplicated->ifaceList.push_back (localIface);
+    }
+  // ...or create a new one
+  else
+    {
+      DuplicateTuple newDup;
+      newDup.address = olsrMessage.GetOriginatorAddress ();
+      newDup.sequenceNumber = olsrMessage.GetMessageSequenceNumber ();
+      newDup.expirationTime = now + OLSR_DUP_HOLD_TIME;
+      newDup.retransmitted = retransmitted;
+      newDup.ifaceList.push_back (localIface);
+      AddDuplicateTuple (newDup);
+      // Schedule dup tuple deletion
+      Simulator::Schedule (OLSR_DUP_HOLD_TIME,
+                           &RoutingProtocol::DupTupleTimerExpire, this,
+                           newDup.address, newDup.sequenceNumber);
+    }
+}
+
+///
+/// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
+///
+/// This buffering system is used in order to piggyback several %OLSR messages in
+/// a same %OLSR packet.
+///
+/// \param msg the %OLSR message which must be sent.
+/// \param delay maximum delay the %OLSR message is going to be buffered.
+///
+void
+RoutingProtocol::QueueMessage (const olsr::MessageHeader &message, Time delay)
+{
+  m_queuedMessages.push_back (message);
+  if (not m_queuedMessagesTimer.IsRunning ())
+    {
+      m_queuedMessagesTimer.SetDelay (delay);
+      m_queuedMessagesTimer.Schedule ();
+    }
+}
+
+void
+RoutingProtocol::SendPacket (Ptr<Packet> packet, 
+                       const MessageList &containedMessages)
+{
+  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
+
+  // Add a header
+  olsr::PacketHeader header;
+  header.SetPacketLength (header.GetSerializedSize () + packet->GetSize ());
+  header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
+  packet->AddHeader (header);
+
+  // Trace it
+  m_txPacketTrace (header, containedMessages);
+
+  // Send it
+  m_socketAddresses.begin ()->first->Send (packet);
+}
+
+///
+/// \brief Creates as many %OLSR packets as needed in order to send all buffered
+/// %OLSR messages.
+///
+/// Maximum number of messages which can be contained in an %OLSR packet is
+/// dictated by OLSR_MAX_MSGS constant.
+///
+void
+RoutingProtocol::SendQueuedMessages ()
+{
+  Ptr<Packet> packet = Create<Packet> ();
+  int numMessages = 0;
+
+  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
+
+  MessageList msglist;
+
+  for (std::vector<olsr::MessageHeader>::const_iterator message = m_queuedMessages.begin ();
+       message != m_queuedMessages.end ();
+       message++)
+    {
+      Ptr<Packet> p = Create<Packet> ();
+      p->AddHeader (*message);
+      packet->AddAtEnd (p);
+      msglist.push_back (*message);
+      if (++numMessages == OLSR_MAX_MSGS)
+        {
+          SendPacket (packet, msglist);
+          msglist.clear ();
+          // Reset variables for next packet
+          numMessages = 0;
+          packet = Create<Packet> ();
+        }
+    }
+
+  if (packet->GetSize ())
+    {
+      SendPacket (packet, msglist);
+    }
+
+  m_queuedMessages.clear ();
+}
+
+///
+/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendHello ()
+{
+  NS_LOG_FUNCTION (this);
+  
+  olsr::MessageHeader msg;
+  Time now = Simulator::Now ();
+
+  msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (1);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+  olsr::MessageHeader::Hello &hello = msg.GetHello ();
+
+  hello.SetHTime (Scalar (3) * m_helloInterval);
+  hello.willingness = m_willingness;
+
+  std::vector<olsr::MessageHeader::Hello::LinkMessage>
+    &linkMessages = hello.linkMessages;
+	
+  const LinkSet &links = m_state.GetLinks ();
+  for (LinkSet::const_iterator link_tuple = links.begin ();
+       link_tuple != links.end (); link_tuple++)
+    {
+      if (!(GetMainAddress (link_tuple->localIfaceAddr) == m_mainAddress
+            && link_tuple->time >= now))
+        {
+          continue;
+        }
+
+      uint8_t link_type, nb_type = 0xff;
+			
+      // Establishes link type
+      if (link_tuple->symTime >= now)
+        {
+          link_type = OLSR_SYM_LINK;
+        }
+      else if (link_tuple->asymTime >= now)
+        {
+          link_type = OLSR_ASYM_LINK;
+        }
+      else
+        {
+          link_type = OLSR_LOST_LINK;
+        }
+      // Establishes neighbor type.
+      if (m_state.FindMprAddress (GetMainAddress (link_tuple->neighborIfaceAddr)))
+        {
+          nb_type = OLSR_MPR_NEIGH;
+          NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+                        << " to be MPR_NEIGH.");
+        }
+      else
+        {
+          bool ok = false;
+          for (NeighborSet::const_iterator nb_tuple = m_state.GetNeighbors ().begin ();
+               nb_tuple != m_state.GetNeighbors ().end ();
+               nb_tuple++)
+            {
+              if (nb_tuple->neighborMainAddr == GetMainAddress (link_tuple->neighborIfaceAddr))
+                {
+                  if (nb_tuple->status == NeighborTuple::STATUS_SYM)
+                    {
+                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+                                    << " to be SYM_NEIGH.");
+                      nb_type = OLSR_SYM_NEIGH;
+                    }
+                  else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
+                    {
+                      nb_type = OLSR_NOT_NEIGH;
+                      NS_LOG_DEBUG ("I consider neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr)
+                                    << " to be NOT_NEIGH.");
+                    }
+                  else
+                    {
+                      NS_FATAL_ERROR ("There is a neighbor tuple with an unknown status!\n");
+                    }
+                  ok = true;
+                  break;
+                }
+            }
+          if (!ok)
+            {
+              NS_LOG_WARN ("I don't know the neighbor " << GetMainAddress (link_tuple->neighborIfaceAddr) << "!!!");
+              continue;
+            }
+        }
+
+      olsr::MessageHeader::Hello::LinkMessage linkMessage;
+      linkMessage.linkCode = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
+      linkMessage.neighborInterfaceAddresses.push_back
+        (link_tuple->neighborIfaceAddr);
+
+      std::vector<Ipv4Address> interfaces =
+        m_state.FindNeighborInterfaces (link_tuple->neighborIfaceAddr);
+
+      linkMessage.neighborInterfaceAddresses.insert
+        (linkMessage.neighborInterfaceAddresses.end (),
+         interfaces.begin (), interfaces.end ());
+
+      linkMessages.push_back (linkMessage);
+    }
+  NS_LOG_DEBUG ("OLSR HELLO message size: " << int (msg.GetSerializedSize ())
+                << " (with " << int (linkMessages.size ()) << " link messages)");
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendTc ()
+{
+  NS_LOG_FUNCTION (this);
+  
+  olsr::MessageHeader msg;
+
+  msg.SetVTime (OLSR_TOP_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+  
+  olsr::MessageHeader::Tc &tc = msg.GetTc ();
+  tc.ansn = m_ansn;
+  for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
+       mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
+    {
+      tc.neighborAddresses.push_back (mprsel_tuple->mainAddr);
+    }
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
+///
+void
+RoutingProtocol::SendMid ()
+{
+  olsr::MessageHeader msg;
+  olsr::MessageHeader::Mid &mid = msg.GetMid ();
+
+  // A node which has only a single interface address participating in
+  // the MANET (i.e., running OLSR), MUST NOT generate any MID
+  // message.
+
+  // A node with several interfaces, where only one is participating
+  // in the MANET and running OLSR (e.g., a node is connected to a
+  // wired network as well as to a MANET) MUST NOT generate any MID
+  // messages.
+
+  // A node with several interfaces, where more than one is
+  // participating in the MANET and running OLSR MUST generate MID
+  // messages as specified.
+
+  // [ Note: assuming here that all interfaces participate in the
+  // MANET; later we may want to make this configurable. ]
+
+  Ipv4Address loopback ("127.0.0.1");
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
+      if (addr != m_mainAddress && addr != loopback)
+        mid.interfaceAddresses.push_back (addr);
+    }
+  if (mid.interfaceAddresses.size () == 0)
+    return;
+  
+  msg.SetVTime (OLSR_MID_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
+///		specification). Neighbor Set is also updated if needed.
+void
+RoutingProtocol::LinkSensing (const olsr::MessageHeader &msg,
+                        const olsr::MessageHeader::Hello &hello,
+                        const Ipv4Address &receiverIface,
+                        const Ipv4Address &senderIface)
+{
+  Time now = Simulator::Now ();
+  bool updated = false;
+  bool created = false;
+  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
+                << ": LinkSensing(receiverIface=" << receiverIface
+                << ", senderIface=" << senderIface << ") BEGIN");
+	
+  NS_ASSERT (msg.GetVTime () > Seconds (0));
+  LinkTuple *link_tuple = m_state.FindLinkTuple (senderIface);
+  if (link_tuple == NULL)
+    {
+      LinkTuple newLinkTuple;
+      // We have to create a new tuple
+      newLinkTuple.neighborIfaceAddr = senderIface;
+      newLinkTuple.localIfaceAddr = receiverIface;
+      newLinkTuple.symTime = now - Seconds (1);
+      newLinkTuple.time = now + msg.GetVTime ();
+      link_tuple = &m_state.InsertLinkTuple (newLinkTuple);
+      created = true;
+      NS_LOG_LOGIC ("Existing link tuple did not exist => creating new one");
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Existing link tuple already exists => will update it");
+      updated = true;
+    }
+	
+  link_tuple->asymTime = now + msg.GetVTime ();
+  for (std::vector<olsr::MessageHeader::Hello::LinkMessage>::const_iterator linkMessage =
+         hello.linkMessages.begin ();
+       linkMessage != hello.linkMessages.end ();
+       linkMessage++)
+    {
+      int lt = linkMessage->linkCode & 0x03; // Link Type
+      int nt = (linkMessage->linkCode >> 2) & 0x03; // Neighbor Type
+
+#ifdef NS3_LOG_ENABLE
+      const char *linkTypeName;
+      switch (lt)
+        {
+        case OLSR_UNSPEC_LINK: linkTypeName = "UNSPEC_LINK"; break;
+        case OLSR_ASYM_LINK: linkTypeName = "ASYM_LINK"; break;
+        case OLSR_SYM_LINK: linkTypeName = "SYM_LINK"; break;
+        case OLSR_LOST_LINK: linkTypeName = "LOST_LINK"; break;
+        default: linkTypeName = "(invalid value!)";
+        }
+
+      const char *neighborTypeName;
+      switch (nt)
+        {
+        case OLSR_NOT_NEIGH: neighborTypeName = "NOT_NEIGH"; break;
+        case OLSR_SYM_NEIGH: neighborTypeName = "SYM_NEIGH"; break;
+        case OLSR_MPR_NEIGH: neighborTypeName = "MPR_NEIGH"; break;
+        default: neighborTypeName = "(invalid value!)";
+        }
+
+      NS_LOG_DEBUG ("Looking at HELLO link messages with Link Type "
+                    << lt << " (" << linkTypeName
+                    << ") and Neighbor Type " << nt
+                    << " (" << neighborTypeName << ")");
+#endif
+
+      // We must not process invalid advertised links
+      if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
+          (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
+           && nt != OLSR_NOT_NEIGH))
+        {
+          NS_LOG_LOGIC ("HELLO link code is invalid => IGNORING");
+          continue;
+        }
+      
+      for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
+             linkMessage->neighborInterfaceAddresses.begin ();
+           neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
+           neighIfaceAddr++)
+        {
+          NS_LOG_DEBUG ("   -> Neighbor: " << *neighIfaceAddr);
+          if (*neighIfaceAddr == receiverIface)
+            {
+              if (lt == OLSR_LOST_LINK)
+                {
+                  NS_LOG_LOGIC ("link is LOST => expiring it");
+                  link_tuple->symTime = now - Seconds (1);
+                  updated = true;
+                }
+              else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
+                {
+                  NS_LOG_DEBUG (*link_tuple << ": link is SYM or ASYM => should become SYM now"
+                                " (symTime being increased to " << now + msg.GetVTime ());
+                  link_tuple->symTime = now + msg.GetVTime ();
+                  link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
+                  updated = true;
+                }
+              else
+                {
+                  NS_FATAL_ERROR ("bad link type");
+                }
+              break;
+            }
+          else
+            {
+              NS_LOG_DEBUG ("     \\-> *neighIfaceAddr (" << *neighIfaceAddr
+                            << " != receiverIface (" << receiverIface << ") => IGNORING!");
+            }
+        }
+      NS_LOG_DEBUG ("Link tuple updated: " << int (updated));
+    }
+  link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
+
+  if (updated)
+    {
+      LinkTupleUpdated (*link_tuple, hello.willingness);
+    }
+
+  // Schedules link tuple deletion
+  if (created && link_tuple != NULL)
+    {
+      LinkTupleAdded (*link_tuple, hello.willingness);
+      m_events.Track (Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
+                                           &RoutingProtocol::LinkTupleTimerExpire, this,
+                                           link_tuple->neighborIfaceAddr));
+    }
+  NS_LOG_DEBUG ("@" << now.GetSeconds () << ": Olsr node " << m_mainAddress
+                << ": LinkSensing END");
+}
+
+///
+/// \brief	Updates the Neighbor Set according to the information contained in a new received
+///		HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateNeighborSet (const olsr::MessageHeader &msg,
+                                const olsr::MessageHeader::Hello &hello)
+{
+  NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
+  if (nb_tuple != NULL)
+    {
+      nb_tuple->willingness = hello.willingness;
+    }
+}
+
+
+///
+/// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
+                                      const olsr::MessageHeader::Hello &hello)
+{
+  Time now = Simulator::Now ();
+
+  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet BEGIN");
+	
+  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+       link_tuple != m_state.GetLinks ().end (); link_tuple++)
+    {
+      NS_LOG_LOGIC ("Looking at link tuple: " << *link_tuple);
+      if (GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ())
+        {
+          NS_LOG_LOGIC ("Link tuple ignored: "
+                        "GetMainAddress (link_tuple->neighborIfaceAddr) != msg.GetOriginatorAddress ()");
+          NS_LOG_LOGIC ("(GetMainAddress(" << link_tuple->neighborIfaceAddr << "): "
+                        << GetMainAddress (link_tuple->neighborIfaceAddr)
+                        << "; msg.GetOriginatorAddress (): " << msg.GetOriginatorAddress ());
+          continue;
+        }
+
+      if (link_tuple->symTime < now)
+        {
+          NS_LOG_LOGIC ("Link tuple ignored: expired.");
+          continue;
+        }
+
+      typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+      for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
+           linkMessage != hello.linkMessages.end (); linkMessage++)
+        {
+          int neighborType = (linkMessage->linkCode >> 2) & 0x3;
+#ifdef NS3_LOG_ENABLE
+          const char *neighborTypeNames[3] = { "NOT_NEIGH", "SYM_NEIGH", "MPR_NEIGH" };
+          const char *neighborTypeName = ((neighborType < 3)?
+                                          neighborTypeNames[neighborType]
+                                          : "(invalid value)");
+          NS_LOG_DEBUG ("Looking at Link Message from HELLO message: neighborType="
+                        << neighborType << " (" << neighborTypeName << ")");
+#endif
+
+          for (std::vector<Ipv4Address>::const_iterator nb2hop_addr_iter =
+                 linkMessage->neighborInterfaceAddresses.begin ();
+               nb2hop_addr_iter != linkMessage->neighborInterfaceAddresses.end ();
+               nb2hop_addr_iter++)
+            {
+              Ipv4Address nb2hop_addr = GetMainAddress (*nb2hop_addr_iter);
+              NS_LOG_DEBUG ("Looking at 2-hop neighbor address from HELLO message: "
+                            << *nb2hop_addr_iter
+                            << " (main address is " << nb2hop_addr << ")");
+              if (neighborType == OLSR_SYM_NEIGH || neighborType == OLSR_MPR_NEIGH)
+                {
+                  // If the main address of the 2-hop neighbor address == main address
+                  // of the receiving node, silently discard the 2-hop
+                  // neighbor address.
+                  if (nb2hop_addr == m_routingAgentAddr)
+                    {
+                      NS_LOG_LOGIC ("Ignoring 2-hop neighbor (it is the node itself)");
+                      continue;
+                    }
+
+                  // Otherwise, a 2-hop tuple is created
+                  TwoHopNeighborTuple *nb2hop_tuple =
+                    m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (), nb2hop_addr);
+                  NS_LOG_LOGIC ("Adding the 2-hop neighbor"
+                                << (nb2hop_tuple? " (refreshing existing entry)" : ""));
+                  if (nb2hop_tuple == NULL)
+                    {
+                      TwoHopNeighborTuple new_nb2hop_tuple;
+                      new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
+                      new_nb2hop_tuple.twoHopNeighborAddr = nb2hop_addr;
+                      new_nb2hop_tuple.expirationTime = now + msg.GetVTime ();
+                      AddTwoHopNeighborTuple (new_nb2hop_tuple);
+                      // Schedules nb2hop tuple deletion
+                      m_events.Track (Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
+                                                           &RoutingProtocol::Nb2hopTupleTimerExpire, this,
+                                                           new_nb2hop_tuple.neighborMainAddr,
+                                                           new_nb2hop_tuple.twoHopNeighborAddr));
+                    }
+                  else
+                    {
+                      nb2hop_tuple->expirationTime = now + msg.GetVTime ();
+                    }
+                }
+              else if (neighborType == OLSR_NOT_NEIGH)
+                {
+                  // For each 2-hop node listed in the HELLO message
+                  // with Neighbor Type equal to NOT_NEIGH all 2-hop
+                  // tuples where: N_neighbor_main_addr == Originator
+                  // Address AND N_2hop_addr == main address of the
+                  // 2-hop neighbor are deleted.
+                  NS_LOG_LOGIC ("2-hop neighbor is NOT_NEIGH => deleting matching 2-hop neighbor state");
+                  m_state.EraseTwoHopNeighborTuples (msg.GetOriginatorAddress (), nb2hop_addr);
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("*** WARNING *** Ignoring link message (inside HELLO) with bad"
+                                " neighbor type value: " << neighborType);
+                }
+            }
+        }
+    }
+
+  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": PopulateTwoHopNeighborSet END");
+}
+
+
+
+///
+/// \brief	Updates the MPR Selector Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+void
+RoutingProtocol::PopulateMprSelectorSet (const olsr::MessageHeader &msg,
+                                       const olsr::MessageHeader::Hello &hello)
+{
+  NS_LOG_FUNCTION (this);
+  
+  Time now = Simulator::Now ();
+	
+  typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+  for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
+       linkMessage != hello.linkMessages.end ();
+       linkMessage++)
+    {
+      int nt = linkMessage->linkCode >> 2;
+      if (nt == OLSR_MPR_NEIGH)
+        {
+          NS_LOG_DEBUG ("Processing a link message with neighbor type MPR_NEIGH");
+          
+          for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
+                 linkMessage->neighborInterfaceAddresses.begin ();
+               nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
+               nb_iface_addr++)
+            {
+              if (GetMainAddress (*nb_iface_addr) == m_mainAddress)
+                {
+                  NS_LOG_DEBUG ("Adding entry to mpr selector set for neighbor " << *nb_iface_addr);
+                  
+                  // We must create a new entry into the mpr selector set
+                  MprSelectorTuple *existing_mprsel_tuple =
+                    m_state.FindMprSelectorTuple (msg.GetOriginatorAddress ());
+                  if (existing_mprsel_tuple == NULL)
+                    {
+                      MprSelectorTuple mprsel_tuple;
+
+                      mprsel_tuple.mainAddr = msg.GetOriginatorAddress ();
+                      mprsel_tuple.expirationTime = now + msg.GetVTime ();
+                      AddMprSelectorTuple (mprsel_tuple);
+
+                      // Schedules mpr selector tuple deletion
+                      m_events.Track (Simulator::Schedule
+                                      (DELAY (mprsel_tuple.expirationTime),
+                                       &RoutingProtocol::MprSelTupleTimerExpire, this,
+                                       mprsel_tuple.mainAddr));
+                    }
+                  else
+                    {
+                      existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
+                    }
+                }
+            }
+        }
+    }
+  NS_LOG_DEBUG ("Computed MPR selector set for node " << m_mainAddress << ": " << m_state.PrintMprSelectorSet ());
+}
+
+
+#if 0
+///
+/// \brief	Drops a given packet because it couldn't be delivered to the corresponding
+///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
+///		actions are then taken.
+///
+/// \param p the packet which couldn't be delivered by the MAC layer.
+///
+void
+OLSR::mac_failed(Ptr<Packet> p) {
+	double now		= Simulator::Now ();
+	struct hdr_ip* ih	= HDR_IP(p);
+	struct hdr_cmn* ch	= HDR_CMN(p);
+	
+	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
+		now,
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(ch->next_hop()));
+	
+	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
+		drop(p, DROP_RTR_MAC_CALLBACK);
+		return;
+	}
+	
+	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
+	if (link_tuple != NULL) {
+		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		nb_loss(link_tuple);
+	}
+	drop(p, DROP_RTR_MAC_CALLBACK);
+}
+#endif
+
+
+
+
+///
+/// \brief Performs all actions needed when a neighbor loss occurs.
+///
+/// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
+///
+/// \param tuple link tuple with the information of the link to the neighbor which has been lost.
+///
+void
+RoutingProtocol::NeighborLoss (const LinkTuple &tuple)
+{
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                << "s: OLSR Node " << m_mainAddress
+                << " LinkTuple " << tuple.neighborIfaceAddr << " -> neighbor loss.");
+  LinkTupleUpdated (tuple, OLSR_WILL_DEFAULT);
+  m_state.EraseTwoHopNeighborTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  m_state.EraseMprSelectorTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  
+  MprComputation ();
+  RoutingTableComputation ();
+}
+
+///
+/// \brief Adds a duplicate tuple to the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be added.
+///
+void
+RoutingProtocol::AddDuplicateTuple (const DuplicateTuple &tuple)
+{
+	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
+		Simulator::Now (),
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(tuple->addr()),
+		tuple->seq_num());*/
+  m_state.InsertDuplicateTuple (tuple);
+}
+
+///
+/// \brief Removes a duplicate tuple from the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be removed.
+///
+void
+RoutingProtocol::RemoveDuplicateTuple (const DuplicateTuple &tuple)
+{
+  /*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
+    Simulator::Now (),
+    OLSR::node_id(ra_addr()),
+    OLSR::node_id(tuple->addr()),
+    tuple->seq_num());*/
+  m_state.EraseDuplicateTuple (tuple);
+}
+
+void
+RoutingProtocol::LinkTupleAdded (const LinkTuple &tuple, uint8_t willingness)
+{
+  // Creates associated neighbor tuple
+  NeighborTuple nb_tuple;
+  nb_tuple.neighborMainAddr = GetMainAddress (tuple.neighborIfaceAddr);
+  nb_tuple.willingness = willingness;
+
+  if (tuple.symTime >= Simulator::Now ())
+    {
+      nb_tuple.status = NeighborTuple::STATUS_SYM;
+    }
+  else
+    {
+      nb_tuple.status = NeighborTuple::STATUS_NOT_SYM;
+    }
+
+  AddNeighborTuple (nb_tuple);
+}
+
+///
+/// \brief Removes a link tuple from the Link Set.
+///
+/// \param tuple the link tuple to be removed.
+///
+void
+RoutingProtocol::RemoveLinkTuple (const LinkTuple &tuple)
+{
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                << "s: OLSR Node " << m_mainAddress
+                << " LinkTuple " << tuple << " REMOVED.");
+
+  m_state.EraseLinkTuple (tuple);
+  m_state.EraseNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+
+}
+
+///
+/// \brief	This function is invoked when a link tuple is updated. Its aim is to
+///		also update the corresponding neighbor tuple if it is needed.
+///
+/// \param tuple the link tuple which has been updated.
+///
+void
+RoutingProtocol::LinkTupleUpdated (const LinkTuple &tuple, uint8_t willingness)
+{
+  // Each time a link tuple changes, the associated neighbor tuple must be recomputed
+
+  NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                << "s: OLSR Node " << m_mainAddress
+                << " LinkTuple " << tuple << " UPDATED.");
+
+  NeighborTuple *nb_tuple =
+    m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+  
+  if (nb_tuple == NULL)
+    {
+      LinkTupleAdded (tuple, willingness);
+      nb_tuple = m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+    }
+
+  if (nb_tuple != NULL)
+    {
+#ifdef NS3_LOG_ENABLE
+      int statusBefore = nb_tuple->status;
+#endif
+      if (tuple.symTime >= Simulator::Now ())
+        {
+          nb_tuple->status = NeighborTuple::STATUS_SYM;
+          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_SYM; changed:"
+                        << int (statusBefore != nb_tuple->status));
+        }
+      else
+        {
+          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+          NS_LOG_DEBUG (*nb_tuple << "->status = STATUS_NOT_SYM; changed:"
+                        << int (statusBefore != nb_tuple->status));
+        }
+    }
+  else
+    {
+      NS_LOG_WARN ("ERROR! Wanted to update a NeighborTuple but none was found!");
+    }
+}
+
+///
+/// \brief Adds a neighbor tuple to the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be added.
+///
+void
+RoutingProtocol::AddNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+  
+  m_state.InsertNeighborTuple (tuple);
+  IncrementAnsn ();
+}
+
+///
+/// \brief Removes a neighbor tuple from the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be removed.
+///
+void
+RoutingProtocol::RemoveNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+	
+  m_state.EraseNeighborTuple (tuple);
+  IncrementAnsn ();
+}
+
+///
+/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be added.
+///
+void
+RoutingProtocol::AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+  
+  m_state.InsertTwoHopNeighborTuple (tuple);
+}
+
+///
+/// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be removed.
+///
+void
+RoutingProtocol::RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+
+  m_state.EraseTwoHopNeighborTuple (tuple);
+}
+
+void
+RoutingProtocol::IncrementAnsn ()
+{
+  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+