Merge with code.nsnam.org
authorKirill Andreev <andreev@iitp.ru>
Wed, 26 Aug 2009 15:29:03 +0400
changeset 5166 9d48acef10b3
parent 5165 08d3bef3b477 (current diff)
parent 4740 34acfd7ad508 (diff)
child 5167 a3ede758b713
Merge with code.nsnam.org
AUTHORS
examples/wscript
src/common/wscript
src/devices/wifi/wifi-mac-header.cc
src/devices/wifi/wifi-remote-station-manager.cc
src/devices/wifi/wifi-remote-station-manager.h
src/helper/wscript
src/internet-stack/sgi-hashmap.h
src/internet-stack/tcp-socket-impl.cc
src/node/wscript
src/wscript
--- a/AUTHORS	Tue Aug 25 20:12:53 2009 +0400
+++ b/AUTHORS	Wed Aug 26 15:29:03 2009 +0400
@@ -27,6 +27,6 @@
 Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu)
 Kulin Shah (m.kulin@gmail.com)
 Mauro Tortonesi (mauro.tortonesi@unife.it)
-Sebastien Vincent (vincent@lsiit.u-strasbg.fr)
+Sebastien Vincent (vincent@clarinet.u-strasbg.fr)
 Guillaume Vu-Brugier (gvubrugier@gmail.com)
 Florian Westphal (fw@strlen.de)
--- a/CHANGES.html	Tue Aug 25 20:12:53 2009 +0400
+++ b/CHANGES.html	Wed Aug 26 15:29:03 2009 +0400
@@ -52,6 +52,26 @@
 
 <h2>New API:</h2>
 <ul>
+<li><b>Athstats</b>
+<p>New classes AthstatsWifiTraceSink and AthstatsHelper.
+</p>
+</li>
+<li><b>WifiRemoteStationManager </b>
+<p>New trace sources exported by WifiRemoteStationManager: MacTxRtsFailed, MacTxDataFailed, MacTxFinalRtsFailed and MacTxFinalDataFailed.
+</p>
+</li>
+<li><b> IPv6 additions</b>
+<p> Add an IPv6 protocol and ICMPv6 capability.
+<ul>
+<li> new classes Ipv6, Ipv6Interface, Ipv6L3Protocol, Ipv6L4Protocol
+<li> Ipv6RawSocket (no UDP or TCP capability yet)
+<li> a set of classes to implement Icmpv6, including neighbor discovery,
+router solicitation, DAD
+<li> new applications Ping6 and Radvd
+<li> routing objects Ipv6Route and Ipv6MulticastRoute
+<li> routing protocols Ipv6ListRouting and Ipv6StaticRouting
+<li> examples: icmpv6-redirect.cc, ping6.cc, radvd.cc, radvd-two-prefix.cc, simple-routing-ping6.cc
+</ul> 
 </ul>
 
 <h2>Changes to existing API:</h2>
--- a/RELEASE_NOTES	Tue Aug 25 20:12:53 2009 +0400
+++ b/RELEASE_NOTES	Wed Aug 26 15:29:03 2009 +0400
@@ -30,13 +30,30 @@
 New user-visible features
 -------------------------
 
-  - Add an implementation of the minstrel rate control algorithm 
-    (Duy Nguyen for gsoc)
+  a) Add an implementation of the minstrel rate control algorithm 
+     (Duy Nguyen for gsoc)
+  
+  b) IPv6 models:
+    - IPv6 interface;
+    - IPv6 layer;
+    - IPv6 raw socket;
+    - Static IPv6 routing;
+    - ICMPv6 layer;
+    - Some ICMPv6 error messages (destination unreachable, ...);
+    - Neighbor Discovery Protocol (NS/NA, RS/RA, redirection);
+    - Ping6 application (send Echo request);
+    - Radvd application (send RA);
+    - Examples (ping6, simple-routing-ping6, radvd, radvd-two-prefix,
+      icmpv6-redirect).
 
+  c) added AthstatsHelper, which enables the wifi device to produce
+     periodic reports similar to the ones generated by madwifi's
+     athstats tool (Nicola Baldo)
+ 
  
 API changes from ns-3.5
 -----------------------
-API changes for this release are documented in the file CHANGES.html.  
+API changes for this release are documented in the file CHANGES.html. 
 XXX
 
 Known issues
--- a/bindings/python/ns3_module_core.py	Tue Aug 25 20:12:53 2009 +0400
+++ b/bindings/python/ns3_module_core.py	Wed Aug 26 15:29:03 2009 +0400
@@ -2199,7 +2199,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::string path) [member function]
+    ## 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]
     cls.add_method('Connect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -2207,7 +2207,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::string path) [member function]
+    ## 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]
     cls.add_method('Disconnect', 
                    'void', 
                    [param('ns3::CallbackBase const &', 'cb'), param('std::string', 'path')])
@@ -2375,7 +2375,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['long long'])
+                        template_parameters=['long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
@@ -2395,7 +2395,7 @@
     module.add_function('TypeNameGet', 
                         'std::string', 
                         [], 
-                        template_parameters=['unsigned long long'])
+                        template_parameters=['unsigned long'])
     ## type-name.h: extern std::string ns3::TypeNameGet() [free function]
     module.add_function('TypeNameGet', 
                         'std::string', 
--- a/bindings/python/ns3_module_node.py	Tue Aug 25 20:12:53 2009 +0400
+++ b/bindings/python/ns3_module_node.py	Wed Aug 26 15:29:03 2009 +0400
@@ -650,6 +650,11 @@
                    'ns3::Ipv4Mask', 
                    [], 
                    is_static=True)
+    ## ipv4-address.h: uint16_t ns3::Ipv4Mask::GetPrefixLength() const [member function]
+    cls.add_method('GetPrefixLength', 
+                   'uint16_t', 
+                   [], 
+                   is_const=True)
     ## ipv4-address.h: static ns3::Ipv4Mask ns3::Ipv4Mask::GetZero() [member function]
     cls.add_method('GetZero', 
                    'ns3::Ipv4Mask', 
--- a/bindings/python/ns3_module_olsr.py	Tue Aug 25 20:12:53 2009 +0400
+++ b/bindings/python/ns3_module_olsr.py	Wed Aug 26 15:29:03 2009 +0400
@@ -102,13 +102,13 @@
     module.add_container('std::vector< ns3::olsr::MessageHeader::Hello::LinkMessage >', 'ns3::olsr::MessageHeader::Hello::LinkMessage', container_type='vector')
     module.add_container('std::vector< ns3::olsr::MessageHeader::Hna::Association >', 'ns3::olsr::MessageHeader::Hna::Association', container_type='vector')
     typehandlers.add_type_alias('std::vector< ns3::olsr::DuplicateTuple, std::allocator< ns3::olsr::DuplicateTuple > >', 'ns3::olsr::DuplicateSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::NeighborTuple, std::allocator< ns3::olsr::NeighborTuple > >', 'ns3::olsr::NeighborSet')
     typehandlers.add_type_alias('std::set< ns3::Ipv4Address, std::less< ns3::Ipv4Address >, std::allocator< ns3::Ipv4Address > >', 'ns3::olsr::MprSet')
     typehandlers.add_type_alias('std::vector< ns3::olsr::MprSelectorTuple, std::allocator< ns3::olsr::MprSelectorTuple > >', 'ns3::olsr::MprSelectorSet')
+    typehandlers.add_type_alias('std::vector< ns3::olsr::TopologyTuple, std::allocator< ns3::olsr::TopologyTuple > >', 'ns3::olsr::TopologySet')
     typehandlers.add_type_alias('std::vector< ns3::olsr::MessageHeader, std::allocator< ns3::olsr::MessageHeader > >', 'ns3::olsr::MessageList')
     typehandlers.add_type_alias('std::vector< ns3::olsr::IfaceAssocTuple, std::allocator< ns3::olsr::IfaceAssocTuple > >', 'ns3::olsr::IfaceAssocSet')
-    typehandlers.add_type_alias('std::vector< ns3::olsr::NeighborTuple, std::allocator< ns3::olsr::NeighborTuple > >', 'ns3::olsr::NeighborSet')
     typehandlers.add_type_alias('std::vector< ns3::olsr::TwoHopNeighborTuple, std::allocator< ns3::olsr::TwoHopNeighborTuple > >', 'ns3::olsr::TwoHopNeighborSet')
-    typehandlers.add_type_alias('std::vector< ns3::olsr::TopologyTuple, std::allocator< ns3::olsr::TopologyTuple > >', 'ns3::olsr::TopologySet')
     typehandlers.add_type_alias('std::vector< ns3::olsr::LinkTuple, std::allocator< ns3::olsr::LinkTuple > >', 'ns3::olsr::LinkSet')
 
 def register_methods(root_module):
--- a/bindings/python/ns3_module_wifi.py	Tue Aug 25 20:12:53 2009 +0400
+++ b/bindings/python/ns3_module_wifi.py	Wed Aug 26 15:29:03 2009 +0400
@@ -10,7 +10,7 @@
     ## wifi-phy-standard.h: ns3::WifiPhyStandard [enumeration]
     module.add_enum('WifiPhyStandard', ['WIFI_PHY_STANDARD_80211a', 'WIFI_PHY_STANDARD_80211b', 'WIFI_PHY_STANDARD_80211_10Mhz', 'WIFI_PHY_STANDARD_80211_5Mhz', 'WIFI_PHY_STANDARD_holland', 'WIFI_PHY_UNKNOWN'])
     ## qos-utils.h: ns3::AccessClass [enumeration]
-    module.add_enum('AccessClass', ['AC_VO', 'AC_VI', 'AC_BE', 'AC_BK', 'AC_UNDEF'])
+    module.add_enum('AccessClass', ['AC_VO', 'AC_VI', 'AC_BE', 'AC_BK', 'AC_BE_NQOS', 'AC_UNDEF'])
     ## edca-txop-n.h: ns3::TypeOfStation [enumeration]
     module.add_enum('TypeOfStation', ['STA', 'AP', 'ADHOC_STA'])
     ## capability-information.h: ns3::CapabilityInformation [class]
@@ -123,10 +123,10 @@
     module.add_class('ConstantRateWifiManager', parent=root_module['ns3::WifiRemoteStationManager'])
     ## propagation-delay-model.h: ns3::ConstantSpeedPropagationDelayModel [class]
     module.add_class('ConstantSpeedPropagationDelayModel', parent=root_module['ns3::PropagationDelayModel'])
-    ## dca-txop.h: ns3::DcaTxop [class]
-    module.add_class('DcaTxop', parent=root_module['ns3::Object'])
+    ## dcf.h: ns3::Dcf [class]
+    module.add_class('Dcf', parent=root_module['ns3::Object'])
     ## edca-txop-n.h: ns3::EdcaTxopN [class]
-    module.add_class('EdcaTxopN', parent=root_module['ns3::Object'])
+    module.add_class('EdcaTxopN', parent=root_module['ns3::Dcf'])
     ## error-rate-model.h: ns3::ErrorRateModel [class]
     module.add_class('ErrorRateModel', parent=root_module['ns3::Object'])
     ## propagation-loss-model.h: ns3::FixedRssLossModel [class]
@@ -173,6 +173,8 @@
     module.add_class('YansWifiChannel', parent=root_module['ns3::WifiChannel'])
     ## aarf-wifi-manager.h: ns3::AarfWifiManager [class]
     module.add_class('AarfWifiManager', parent=root_module['ns3::ArfWifiManager'])
+    ## dca-txop.h: ns3::DcaTxop [class]
+    module.add_class('DcaTxop', parent=root_module['ns3::Dcf'])
     typehandlers.add_type_alias('std::vector< ns3::RateInfo, std::allocator< ns3::RateInfo > >', 'ns3::MinstrelRate')
     typehandlers.add_type_alias('std::vector< std::vector< unsigned int, std::allocator< unsigned int > >, std::allocator< std::vector< unsigned int, std::allocator< unsigned int > > > >', 'ns3::SampleRate')
     typehandlers.add_type_alias('std::vector< ns3::ThresholdsItem, std::allocator< ns3::ThresholdsItem > >', 'ns3::Thresholds')
@@ -279,7 +281,7 @@
     register_Ns3ArfWifiManager_methods(root_module, root_module['ns3::ArfWifiManager'])
     register_Ns3ConstantRateWifiManager_methods(root_module, root_module['ns3::ConstantRateWifiManager'])
     register_Ns3ConstantSpeedPropagationDelayModel_methods(root_module, root_module['ns3::ConstantSpeedPropagationDelayModel'])
-    register_Ns3DcaTxop_methods(root_module, root_module['ns3::DcaTxop'])
+    register_Ns3Dcf_methods(root_module, root_module['ns3::Dcf'])
     register_Ns3EdcaTxopN_methods(root_module, root_module['ns3::EdcaTxopN'])
     register_Ns3ErrorRateModel_methods(root_module, root_module['ns3::ErrorRateModel'])
     register_Ns3FixedRssLossModel_methods(root_module, root_module['ns3::FixedRssLossModel'])
@@ -304,6 +306,7 @@
     register_Ns3YansErrorRateModel_methods(root_module, root_module['ns3::YansErrorRateModel'])
     register_Ns3YansWifiChannel_methods(root_module, root_module['ns3::YansWifiChannel'])
     register_Ns3AarfWifiManager_methods(root_module, root_module['ns3::AarfWifiManager'])
+    register_Ns3DcaTxop_methods(root_module, root_module['ns3::DcaTxop'])
     return
 
 def register_Ns3CapabilityInformation_methods(root_module, cls):
@@ -2290,6 +2293,11 @@
     cls.add_method('ConfigureStandard', 
                    'void', 
                    [param('ns3::WifiPhyStandard', 'standard')])
+    ## wifi-mac.h: void ns3::WifiMac::ConfigureDcf(ns3::Ptr<ns3::Dcf> dcf, uint32_t cwmin, uint32_t cwmax, ns3::AccessClass ac) [member function]
+    cls.add_method('ConfigureDcf', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Dcf >', 'dcf'), param('uint32_t', 'cwmin'), param('uint32_t', 'cwmax'), param('ns3::AccessClass', 'ac')], 
+                   visibility='protected')
     ## wifi-mac.h: void ns3::WifiMac::FinishConfigureStandard(ns3::WifiPhyStandard standard) [member function]
     cls.add_method('FinishConfigureStandard', 
                    'void', 
@@ -3683,78 +3691,46 @@
                    is_const=True)
     return
 
-def register_Ns3DcaTxop_methods(root_module, cls):
-    ## dca-txop.h: static ns3::TypeId ns3::DcaTxop::GetTypeId() [member function]
+def register_Ns3Dcf_methods(root_module, cls):
+    ## dcf.h: ns3::Dcf::Dcf(ns3::Dcf const & arg0) [copy constructor]
+    cls.add_constructor([param('ns3::Dcf const &', 'arg0')])
+    ## dcf.h: ns3::Dcf::Dcf() [constructor]
+    cls.add_constructor([])
+    ## dcf.h: static ns3::TypeId ns3::Dcf::GetTypeId() [member function]
     cls.add_method('GetTypeId', 
                    'ns3::TypeId', 
                    [], 
                    is_static=True)
-    ## dca-txop.h: ns3::DcaTxop::DcaTxop() [constructor]
-    cls.add_constructor([])
-    ## dca-txop.h: void ns3::DcaTxop::SetLow(ns3::Ptr<ns3::MacLow> low) [member function]
-    cls.add_method('SetLow', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::MacLow >', 'low')])
-    ## dca-txop.h: void ns3::DcaTxop::SetManager(ns3::DcfManager * manager) [member function]
-    cls.add_method('SetManager', 
-                   'void', 
-                   [param('ns3::DcfManager *', 'manager')])
-    ## dca-txop.h: void ns3::DcaTxop::SetWifiRemoteStationManager(ns3::Ptr<ns3::WifiRemoteStationManager> remoteManager) [member function]
-    cls.add_method('SetWifiRemoteStationManager', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::WifiRemoteStationManager >', 'remoteManager')])
-    ## dca-txop.h: void ns3::DcaTxop::SetTxOkCallback(ns3::Callback<void, ns3::WifiMacHeader const&, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> callback) [member function]
-    cls.add_method('SetTxOkCallback', 
-                   'void', 
-                   [param('ns3::Callback< void, ns3::WifiMacHeader const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'callback')])
-    ## dca-txop.h: void ns3::DcaTxop::SetTxFailedCallback(ns3::Callback<void, ns3::WifiMacHeader const&, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> callback) [member function]
-    cls.add_method('SetTxFailedCallback', 
-                   'void', 
-                   [param('ns3::Callback< void, ns3::WifiMacHeader const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'callback')])
-    ## dca-txop.h: void ns3::DcaTxop::SetMaxQueueSize(uint32_t size) [member function]
-    cls.add_method('SetMaxQueueSize', 
-                   'void', 
-                   [param('uint32_t', 'size')])
-    ## dca-txop.h: void ns3::DcaTxop::SetMaxQueueDelay(ns3::Time delay) [member function]
-    cls.add_method('SetMaxQueueDelay', 
-                   'void', 
-                   [param('ns3::Time', 'delay')])
-    ## dca-txop.h: void ns3::DcaTxop::SetMinCw(uint32_t minCw) [member function]
+    ## dcf.h: void ns3::Dcf::SetMinCw(uint32_t minCw) [member function]
     cls.add_method('SetMinCw', 
                    'void', 
-                   [param('uint32_t', 'minCw')])
-    ## dca-txop.h: void ns3::DcaTxop::SetMaxCw(uint32_t maxCw) [member function]
+                   [param('uint32_t', 'minCw')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## dcf.h: void ns3::Dcf::SetMaxCw(uint32_t maxCw) [member function]
     cls.add_method('SetMaxCw', 
                    'void', 
-                   [param('uint32_t', 'maxCw')])
-    ## dca-txop.h: void ns3::DcaTxop::SetAifsn(uint32_t aifsn) [member function]
+                   [param('uint32_t', 'maxCw')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## dcf.h: void ns3::Dcf::SetAifsn(uint32_t aifsn) [member function]
     cls.add_method('SetAifsn', 
                    'void', 
-                   [param('uint32_t', 'aifsn')])
-    ## dca-txop.h: uint32_t ns3::DcaTxop::GetMinCw() const [member function]
+                   [param('uint32_t', 'aifsn')], 
+                   is_pure_virtual=True, is_virtual=True)
+    ## dcf.h: uint32_t ns3::Dcf::GetMinCw() const [member function]
     cls.add_method('GetMinCw', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
-    ## dca-txop.h: uint32_t ns3::DcaTxop::GetMaxCw() const [member function]
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    ## dcf.h: uint32_t ns3::Dcf::GetMaxCw() const [member function]
     cls.add_method('GetMaxCw', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
-    ## dca-txop.h: uint32_t ns3::DcaTxop::GetAifsn() const [member function]
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
+    ## dcf.h: uint32_t ns3::Dcf::GetAifsn() const [member function]
     cls.add_method('GetAifsn', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
-    ## dca-txop.h: void ns3::DcaTxop::Queue(ns3::Ptr<ns3::Packet const> packet, ns3::WifiMacHeader const & hdr) [member function]
-    cls.add_method('Queue', 
-                   'void', 
-                   [param('ns3::Ptr< ns3::Packet const >', 'packet'), param('ns3::WifiMacHeader const &', 'hdr')])
-    ## dca-txop.h: void ns3::DcaTxop::DoDispose() [member function]
-    cls.add_method('DoDispose', 
-                   'void', 
-                   [], 
-                   visibility='private', is_virtual=True)
+                   is_pure_virtual=True, is_const=True, is_virtual=True)
     return
 
 def register_Ns3EdcaTxopN_methods(root_module, cls):
@@ -3814,30 +3790,33 @@
     ## edca-txop-n.h: void ns3::EdcaTxopN::SetMinCw(uint32_t minCw) [member function]
     cls.add_method('SetMinCw', 
                    'void', 
-                   [param('uint32_t', 'minCw')])
+                   [param('uint32_t', 'minCw')], 
+                   is_virtual=True)
     ## edca-txop-n.h: void ns3::EdcaTxopN::SetMaxCw(uint32_t maxCw) [member function]
     cls.add_method('SetMaxCw', 
                    'void', 
-                   [param('uint32_t', 'maxCw')])
+                   [param('uint32_t', 'maxCw')], 
+                   is_virtual=True)
     ## edca-txop-n.h: void ns3::EdcaTxopN::SetAifsn(uint32_t aifsn) [member function]
     cls.add_method('SetAifsn', 
                    'void', 
-                   [param('uint32_t', 'aifsn')])
+                   [param('uint32_t', 'aifsn')], 
+                   is_virtual=True)
     ## edca-txop-n.h: uint32_t ns3::EdcaTxopN::GetMinCw() const [member function]
     cls.add_method('GetMinCw', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
+                   is_const=True, is_virtual=True)
     ## edca-txop-n.h: uint32_t ns3::EdcaTxopN::GetMaxCw() const [member function]
     cls.add_method('GetMaxCw', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
+                   is_const=True, is_virtual=True)
     ## edca-txop-n.h: uint32_t ns3::EdcaTxopN::GetAifsn() const [member function]
     cls.add_method('GetAifsn', 
                    'uint32_t', 
                    [], 
-                   is_const=True)
+                   is_const=True, is_virtual=True)
     ## edca-txop-n.h: ns3::Ptr<ns3::MacLow> ns3::EdcaTxopN::Low() [member function]
     cls.add_method('Low', 
                    'ns3::Ptr< ns3::MacLow >', 
@@ -5395,6 +5374,83 @@
                    visibility='private', is_virtual=True)
     return
 
+def register_Ns3DcaTxop_methods(root_module, cls):
+    ## dca-txop.h: static ns3::TypeId ns3::DcaTxop::GetTypeId() [member function]
+    cls.add_method('GetTypeId', 
+                   'ns3::TypeId', 
+                   [], 
+                   is_static=True)
+    ## dca-txop.h: ns3::DcaTxop::DcaTxop() [constructor]
+    cls.add_constructor([])
+    ## dca-txop.h: void ns3::DcaTxop::SetLow(ns3::Ptr<ns3::MacLow> low) [member function]
+    cls.add_method('SetLow', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::MacLow >', 'low')])
+    ## dca-txop.h: void ns3::DcaTxop::SetManager(ns3::DcfManager * manager) [member function]
+    cls.add_method('SetManager', 
+                   'void', 
+                   [param('ns3::DcfManager *', 'manager')])
+    ## dca-txop.h: void ns3::DcaTxop::SetWifiRemoteStationManager(ns3::Ptr<ns3::WifiRemoteStationManager> remoteManager) [member function]
+    cls.add_method('SetWifiRemoteStationManager', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::WifiRemoteStationManager >', 'remoteManager')])
+    ## dca-txop.h: void ns3::DcaTxop::SetTxOkCallback(ns3::Callback<void, ns3::WifiMacHeader const&, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> callback) [member function]
+    cls.add_method('SetTxOkCallback', 
+                   'void', 
+                   [param('ns3::Callback< void, ns3::WifiMacHeader const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'callback')])
+    ## dca-txop.h: void ns3::DcaTxop::SetTxFailedCallback(ns3::Callback<void, ns3::WifiMacHeader const&, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty> callback) [member function]
+    cls.add_method('SetTxFailedCallback', 
+                   'void', 
+                   [param('ns3::Callback< void, ns3::WifiMacHeader const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'callback')])
+    ## dca-txop.h: void ns3::DcaTxop::SetMaxQueueSize(uint32_t size) [member function]
+    cls.add_method('SetMaxQueueSize', 
+                   'void', 
+                   [param('uint32_t', 'size')])
+    ## dca-txop.h: void ns3::DcaTxop::SetMaxQueueDelay(ns3::Time delay) [member function]
+    cls.add_method('SetMaxQueueDelay', 
+                   'void', 
+                   [param('ns3::Time', 'delay')])
+    ## dca-txop.h: void ns3::DcaTxop::SetMinCw(uint32_t minCw) [member function]
+    cls.add_method('SetMinCw', 
+                   'void', 
+                   [param('uint32_t', 'minCw')], 
+                   is_virtual=True)
+    ## dca-txop.h: void ns3::DcaTxop::SetMaxCw(uint32_t maxCw) [member function]
+    cls.add_method('SetMaxCw', 
+                   'void', 
+                   [param('uint32_t', 'maxCw')], 
+                   is_virtual=True)
+    ## dca-txop.h: void ns3::DcaTxop::SetAifsn(uint32_t aifsn) [member function]
+    cls.add_method('SetAifsn', 
+                   'void', 
+                   [param('uint32_t', 'aifsn')], 
+                   is_virtual=True)
+    ## dca-txop.h: uint32_t ns3::DcaTxop::GetMinCw() const [member function]
+    cls.add_method('GetMinCw', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## dca-txop.h: uint32_t ns3::DcaTxop::GetMaxCw() const [member function]
+    cls.add_method('GetMaxCw', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## dca-txop.h: uint32_t ns3::DcaTxop::GetAifsn() const [member function]
+    cls.add_method('GetAifsn', 
+                   'uint32_t', 
+                   [], 
+                   is_const=True, is_virtual=True)
+    ## dca-txop.h: void ns3::DcaTxop::Queue(ns3::Ptr<ns3::Packet const> packet, ns3::WifiMacHeader const & hdr) [member function]
+    cls.add_method('Queue', 
+                   'void', 
+                   [param('ns3::Ptr< ns3::Packet const >', 'packet'), param('ns3::WifiMacHeader const &', 'hdr')])
+    ## dca-txop.h: void ns3::DcaTxop::DoDispose() [member function]
+    cls.add_method('DoDispose', 
+                   'void', 
+                   [], 
+                   visibility='private', is_virtual=True)
+    return
+
 def register_functions(root_module):
     module = root_module
     ## ssid.h: extern ns3::Ptr<ns3::AttributeChecker const> ns3::MakeSsidChecker() [free function]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/icmpv6-redirect.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,176 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: David Gross <david.gross@eturs.u-strasbg.fr>
+ */
+
+// Network topology
+//
+//             STA2
+//              |
+//              |
+//   R1         R2
+//   |          |
+//   |          |
+//   ------------
+//           |
+//           |
+//          STA 1
+//
+// - Initial configuration :
+//         - STA1 default route : R1
+//         - R1 static route to STA2 : R2
+//         - STA2 default route : R2
+// - STA1 send Echo Request to STA2 using its default route to R1
+// - R1 receive Echo Request from STA1, and forward it to R2
+// - R1 send an ICMPv6 Redirection to STA1 with Target STA2 and Destination R2
+// - Next Echo Request from STA1 to STA2 are directly sent to R2
+
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/helper-module.h"
+
+#include "ns3/ipv6-routing-table-entry.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("Icmpv6RedirectExample");
+
+class StackHelper
+{
+  public:
+    /**
+     * \brief Print the routing table.
+     * \param n the node
+     */
+    inline void PrintRoutingTable (Ptr<Node>& n)
+    {
+      Ptr<Ipv6StaticRouting> routing = 0;
+      Ipv6StaticRoutingHelper routingHelper;
+      Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+      uint32_t nbRoutes = 0;
+      Ipv6RoutingTableEntry route;
+
+      routing = routingHelper.GetStaticRouting (ipv6);
+
+      std::cout << "Routing table of " << n << " : " << std::endl;
+      std::cout << "Destination\t\t\t\t" << "Gateway\t\t\t\t\t" << "Interface\t" << std::endl;
+
+      nbRoutes = routing->GetNRoutes ();
+      for(uint32_t i = 0 ; i < nbRoutes ; i++)
+      {
+        route = routing->GetRoute (i);
+        std::cout << route.GetDest () << "\t"
+          << route.GetGateway () << "\t"
+          << route.GetInterface () << "\t" << std::endl;
+      }
+    }
+
+    inline void AddHostRouteTo (Ptr<Node>& n, Ipv6Address dst, Ipv6Address nextHop, uint32_t interface)
+    {
+      Ptr<Ipv6StaticRouting> routing = 0;
+      Ipv6StaticRoutingHelper routingHelper;
+      Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+
+      routing = routingHelper.GetStaticRouting (ipv6);
+
+      routing->AddHostRouteTo (dst, nextHop, interface);
+    }
+};
+
+
+int main (int argc, char **argv)
+{
+#if 0 
+  LogComponentEnable ("Icmpv6RedirectExample", LOG_LEVEL_INFO);
+  LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_INFO);
+  LogComponentEnable("Ipv6L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv6StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv6Interface", LOG_LEVEL_ALL);
+  LogComponentEnable("Icmpv6L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("NdiscCache", LOG_LEVEL_ALL);
+#endif
+
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
+  NS_LOG_INFO ("Create nodes.");
+  Ptr<Node> sta1 = CreateObject<Node> ();
+  Ptr<Node> r1 = CreateObject<Node> ();
+  Ptr<Node> r2 = CreateObject<Node> ();
+  Ptr<Node> sta2 = CreateObject<Node> ();
+  NodeContainer net1(sta1, r1, r2);
+  NodeContainer net2(r2, sta2);
+  NodeContainer all(sta1, r1, r2, sta2);
+
+  StackHelper stackHelper;
+  
+  InternetStackHelper internetv6;
+  internetv6.Install (all);
+
+  NS_LOG_INFO ("Create channels.");
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue(5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue(MilliSeconds (2)));
+  NetDeviceContainer ndc1 = csma.Install (net1); 
+  NetDeviceContainer ndc2 = csma.Install (net2);
+
+  NS_LOG_INFO ("Assign IPv6 Addresses.");
+  Ipv6AddressHelper ipv6;
+
+  ipv6.NewNetwork (Ipv6Address ("2001:1::"), 64);
+  Ipv6InterfaceContainer iic1 = ipv6.Assign (ndc1);
+  iic1.SetRouter (2, true);
+  iic1.SetRouter (1, true);
+
+  ipv6.NewNetwork (Ipv6Address ("2001:2::"), 64);
+  Ipv6InterfaceContainer iic2 = ipv6.Assign (ndc2);
+  iic2.SetRouter (0, true);
+
+  stackHelper.AddHostRouteTo (r1, iic2.GetAddress (1, 1), iic1.GetAddress (2, 1), iic1.GetInterfaceIndex (1));
+  
+  Simulator::Schedule(Seconds(0.0), &StackHelper::PrintRoutingTable, &stackHelper, r1);
+  Simulator::Schedule(Seconds(3.0), &StackHelper::PrintRoutingTable, &stackHelper, sta1);
+
+  NS_LOG_INFO ("Create Applications.");
+  uint32_t packetSize = 1024;
+  uint32_t maxPacketCount = 5;
+  Time interPacketInterval = Seconds (1.);
+  Ping6Helper ping6;
+
+  ping6.SetLocal (iic1.GetAddress(0, 1));
+  ping6.SetRemote (iic2.GetAddress(1, 1));
+  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+  ping6.SetAttribute ("Interval", TimeValue(interPacketInterval));
+  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  ApplicationContainer apps = ping6.Install (sta1);
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (10.0));
+
+  std::ofstream ascii;
+  ascii.open ("icmpv6-redirect.tr");
+  CsmaHelper::EnablePcapAll ("icmpv6-redirect", true);
+  CsmaHelper::EnableAsciiAll (ascii);
+
+  /* Now, do the actual simulation. */
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
+
--- a/examples/multi-rate-first.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/examples/multi-rate-first.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -1,10 +1,16 @@
 /**
  *
  * Instructions:
- * ./waf --run multi-rate-first > m.data
- * gnuplot m.data
- * eog *.png
+ * ./waf --run multi-rate-first
+ * gnuplot multi-rate-first-scen*.plt
  *
+ * Output: 
+ * multi-rate-first-scen1.eps
+ * multi-rate-first-scen2.eps
+ * multi-rate-first-scen3.eps
+ * multi-rate-first-scen4.eps
+ *
+ * Side Note: It may take some time.
  */
 
 #include "ns3/core-module.h"
@@ -15,6 +21,7 @@
 #include "ns3/contrib-module.h"
 
 #include <iostream>
+#include <fstream>
 
 NS_LOG_COMPONENT_DEFINE ("Main");
 
@@ -34,6 +41,7 @@
   void AdvancePosition (Ptr<Node> node);
   void BackTrackPosition (Ptr<Node> node);
   void StationaryPosition (Ptr<Node> node);
+  void MultiPosition (Ptr<Node> node1, Ptr<Node> node2);
   Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
 
   uint32_t m_bytesTotal;
@@ -108,6 +116,26 @@
   m_output.Add ((Simulator::Now()).GetSeconds(), mbs);
 
 }
+void
+Experiment::MultiPosition (Ptr<Node> n1, Ptr<Node> n2)
+{
+  Vector pos1 = GetPosition(n1);
+  Vector pos2 = GetPosition(n2);
+  double mbs = ((m_bytesTotal * 8.0) / 1000000);
+  m_bytesTotal = 0;
+  m_output.Add ((Simulator::Now()).GetSeconds(), mbs);
+  
+  if( pos1.x < 230)
+    {
+      pos1.x += 1.0;
+      SetPosition (n1, pos1);
+    }
+  if( pos2.x > 0)
+    {
+      pos2.x -= 1.0;
+      SetPosition (n2, pos2);
+    }
+}
 
 void
 Experiment::ReceivePacket (Ptr<Socket> socket)
@@ -169,21 +197,30 @@
 
   Ptr<Socket> recvSink = SetupPacketReceive (c.Get (1));
 
-  if(positionStep == 1)
+  if (positionStep == 1)
     {
       Simulator::Schedule (Seconds (1.5), &Experiment::AdvancePosition, this, c.Get (1));
     }
-  else if(positionStep == -1)
+  else if (positionStep == -1)
     {
       Simulator::Schedule (Seconds (1.5), &Experiment::BackTrackPosition, this, c.Get (1));
     }
-  else if(positionStep == 0)
+  else if (positionStep == 0)
     {
       for(int i = 1; i <= 210; i++) 
         {
           Simulator::Schedule (Seconds (i), &Experiment::StationaryPosition, this, c.Get (1));
         }
     }
+  else if (positionStep == 2)
+    {
+      for(int i = 1; i <= 210; i++) 
+        {
+          Simulator::Schedule (Seconds (i), &Experiment::MultiPosition, this, c.Get(0), c.Get (1));
+        }
+    }
+
+     
   Simulator::Run ();
   Simulator::Destroy ();
 
@@ -192,6 +229,11 @@
 
 int main (int argc, char *argv[])
 {
+  std::ofstream outfile ("multi-rate-first-scen1.plt");
+  std::ofstream outfile2 ("multi-rate-first-scen2.plt");
+  std::ofstream outfile3 ("multi-rate-first-scen3.plt");
+  std::ofstream outfile4 ("multi-rate-first-scen4.plt");
+
   // disable fragmentation
   Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
   Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
@@ -199,119 +241,158 @@
   CommandLine cmd;
   cmd.Parse (argc, argv);
 
-  Gnuplot gnuplot = Gnuplot ("multi-rate-first.png");
+
+  MobilityHelper mobility;
   Experiment experiment;
+  Gnuplot gnuplot;
+  int myPositionStep; 
+  Ptr<ListPositionAllocator> positionAlloc;
+  Gnuplot2dDataset dataset;
   WifiHelper wifi = WifiHelper::Default ();
   NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
   YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
   YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
-  Gnuplot2dDataset dataset;
-  int myPositionStep = 0; 
-
-/*
 
-  // Scenario 1: moving away from one another
-  // Initially set them 5 meters apart 
-  // Set  positionStep parameter of Experiment::Run to 1  
-  // Set RateErrorModel of Experiment::Run to 0
+  // Scenario 1: two nodes within transmission range about 5 meters apart
+  // Fix a node stationary, move the second node away from it
+
+  // moving forward 
   myPositionStep = 1;
 
-  MobilityHelper mobility;
-  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  gnuplot = Gnuplot ("multi-rate-first-scen1.eps");
+
+  positionAlloc = CreateObject<ListPositionAllocator> ();
   positionAlloc->Add (Vector (0.0, 0.0, 0.0));
   positionAlloc->Add (Vector (5.0, 0.0, 0.0));
   mobility.SetPositionAllocator (positionAlloc);
   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
 
   wifiMac.SetType ("ns3::AdhocWifiMac");
-
-  gnuplot = Gnuplot ("multi-rate-first.png");
   wifi.SetStandard (WIFI_PHY_STANDARD_holland);
 
-  NS_LOG_DEBUG ("minstrel");
   experiment = Experiment ("minstrel");
   wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
   dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  NS_LOG_DEBUG ("ideal");
   experiment = Experiment ("ideal");
   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
   dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  gnuplot.GenerateOutput (std::cout);
-  */
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("Time (Seconds)", "Throughput(Mbps)");
+  gnuplot.SetExtra  ("set xrange [0:250]");
+  gnuplot.SetTitle ("Throughput vs Time");
+  gnuplot.GenerateOutput (outfile);
+  outfile.close ();
 
 
-  // Scenario 2: two nodes out of range, moving into transmission range range
-  // Initially set them 230 meters apart 
-  // Set positionStep parameter of Experiment::Rung to -1
-  // set RateErrorModel of Experiment::Run to 0
+  // Scenario 2: two nodes out of transmission range about 230 meters apart
+  // Fix a node stationary, move the second node into transmission range
 
+  // moving backward
   myPositionStep = -1;
 
-  MobilityHelper mobility;
-  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  gnuplot = Gnuplot ("multi-rate-first-scen2.eps");
+
+  positionAlloc = CreateObject<ListPositionAllocator> ();
   positionAlloc->Add (Vector (0.0, 0.0, 0.0));
   positionAlloc->Add (Vector (230.0, 0.0, 0.0));
   mobility.SetPositionAllocator (positionAlloc);
   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
 
   wifiMac.SetType ("ns3::AdhocWifiMac");
-
-  gnuplot = Gnuplot ("multi-rate-first.png");
   wifi.SetStandard (WIFI_PHY_STANDARD_holland);
 
-  NS_LOG_DEBUG ("minstrel");
   experiment = Experiment ("minstrel");
   wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
-  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  NS_LOG_DEBUG ("ideal");
   experiment = Experiment ("ideal");
   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
-  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  gnuplot.GenerateOutput (std::cout);
-
-
 
-/*
-  // Scenario 3:
-  // Initially set them 25 meters apart, stationary
-  // Set positionStep parameter of Experiment::Rung to 0 
-  // This is a sanity check
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("Time (Seconds)", "Throughput(Mbps)");
+  gnuplot.SetExtra  ("set xrange [0:250]");
+  gnuplot.SetTitle ("Throughput vs Time");
+  gnuplot.GenerateOutput (outfile2);
+  outfile2.close ();
+
 
+  // Scenario 3: two nodes within transmission range 25 meters part
+  // Set both nodes stationary
+  // this is more like a sanity check
+
+  // Set position stationary 
   myPositionStep = 0;
-  MobilityHelper mobility;
-  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+
+  gnuplot = Gnuplot ("multi-rate-first-scen3.eps");
+
+  positionAlloc = CreateObject<ListPositionAllocator> ();
   positionAlloc->Add (Vector (0.0, 0.0, 0.0));
   positionAlloc->Add (Vector (25.0, 0.0, 0.0));
   mobility.SetPositionAllocator (positionAlloc);
   mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
 
   wifiMac.SetType ("ns3::AdhocWifiMac");
-
-  gnuplot = Gnuplot ("multi-rate-first.png");
   wifi.SetStandard (WIFI_PHY_STANDARD_holland);
 
-  NS_LOG_DEBUG ("minstrel");
   experiment = Experiment ("minstrel");
   wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
-  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  NS_LOG_DEBUG ("ideal");
   experiment = Experiment ("ideal");
   wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
-  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
   gnuplot.AddDataset (dataset);
 
-  gnuplot.GenerateOutput (std::cout);
-  */
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("Time (Seconds)", "Throughput(Mbps)");
+  gnuplot.SetExtra  ("set xrange [0:250]");
+  gnuplot.SetTitle ("Throughput vs Time");
+  gnuplot.GenerateOutput (outfile3);
+  outfile3.close ();
+
+  // Scenario 4: Two nodes in opposite direction about 230 meters apart
+  // moving into transmission range and out of transmission range
+  myPositionStep = 2;
+
+  gnuplot = Gnuplot ("multi-rate-first-scen4.eps");
+
+  positionAlloc = CreateObject<ListPositionAllocator> ();
+  // initial position of node 1
+  positionAlloc->Add (Vector (0.0, 25.0, 0.0));
+  // initial position of node 2
+  positionAlloc->Add (Vector (230.0, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+
+  wifiMac.SetType ("ns3::AdhocWifiMac");
+  wifi.SetStandard (WIFI_PHY_STANDARD_holland);
+
+  experiment = Experiment ("minstrel");
+  wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  gnuplot.AddDataset (dataset);
+
+  experiment = Experiment ("ideal");
+  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
+  dataset= experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility, myPositionStep);
+  gnuplot.AddDataset (dataset);
+
+  gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
+  gnuplot.SetLegend ("Time (Seconds)", "Throughput(Mbps)");
+  gnuplot.SetExtra  ("set xrange [0:250]");
+  gnuplot.SetTitle ("Throughput vs Time");
+  gnuplot.GenerateOutput (outfile4);
+  outfile4.close ();
+  
 
   return 0;
 }
--- a/examples/multi-rate-second.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/examples/multi-rate-second.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -95,13 +95,10 @@
 {
   Vector pos = GetPosition(node);
 
-  ///to offset the start time
-  double offSetTime = 100;
-
   if (pktCount > 0)
     {
       ///To simulate nodes moving in and out of transmission constantly
-      if(pos.x <= 305 && advanceStep)
+      if(pos.x <= 230 && advanceStep)
         {
           ///keep moving away
           pos.x += .1;
@@ -110,7 +107,7 @@
       else
         {
           if(pos.x < 150)
-	    {
+            {
               advanceStep=true;
             }
           else
@@ -128,7 +125,7 @@
     }
   else
     {
-      m_output.Add((Simulator::Now()).GetSeconds() - offSetTime , m_pktsTotal); 
+      m_output.Add((Simulator::Now()).GetSeconds(), m_pktsTotal); 
     }
 }
 
@@ -172,32 +169,30 @@
   source->Connect (remote);
   uint32_t packetSize = 1014;
   uint32_t maxPacketCount = 1000;
-  Time interPacketInterval = Seconds (.1);
+  Time interPacketInterval = Seconds (1.);
 
   Ptr<Node> n1 = c.Get(0);
   Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4> ();
-
+  // parameters for Ipv4::SetDown and SetUp
+  // The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
+  // then the next p2p is numbered 2
 
-
+  double downTime = 0.0;
   for (int i= 1; i <= 100; i++) 
     {
 
       Simulator::Schedule (Seconds (i), &Experiment::GenerateTraffic,
                            this, source, packetSize, maxPacketCount,interPacketInterval, c.Get(1));
-
-      if( i % 5 == 0 )
+      if ( i % 10 == 0 )
         {
           ///bring a network interface down 
-          Simulator::Schedule (Seconds (i+.5), &Ipv4::SetDown, ipv41, 1); 
-          i++;
-          Simulator::Schedule (Seconds (i), &Experiment::GenerateTraffic,
-                               this, source, packetSize, maxPacketCount,interPacketInterval, c.Get(1));
+          Simulator::Schedule (Seconds (i+.1), &Ipv4::SetDown, ipv41, 1); 
 	
+          //duration of the down time
+          downTime += .1;
+
           ///bring a network interface up
-          Simulator::Schedule (Seconds (i+.2), &Ipv4::SetUp, ipv41, 1); 
-          i++;
-          Simulator::Schedule (Seconds (i), &Experiment::GenerateTraffic,
-                               this, source, packetSize, maxPacketCount,interPacketInterval, c.Get(1));
+          Simulator::Schedule (Seconds (i + downTime), &Ipv4::SetUp, ipv41, 1); 
         }
     }
 
@@ -209,13 +204,15 @@
 
 int main (int argc, char *argv[])
 {
+  std::ofstream outfile ("multi-rate-second.plt");
+
   std::vector <std::string> ratesControl;
+  ratesControl.push_back ("Minstrel");
   ratesControl.push_back ("Ideal");
-  ratesControl.push_back ("Minstrel");
 
   std::vector <std::string> wifiManager;
+  wifiManager.push_back("ns3::MinstrelWifiManager");
   wifiManager.push_back("ns3::IdealWifiManager");
-  wifiManager.push_back("ns3::MinstrelWifiManager");
 
   // disable fragmentation
   Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
@@ -228,12 +225,13 @@
   
   for (uint32_t i = 0; i < ratesControl.size(); i++)
   {
+    std::cout << ratesControl[i] << std::endl;
+    std::cout << wifiManager[i] << std::endl;
     Gnuplot2dDataset dataset (ratesControl[i]);
     dataset.SetStyle (Gnuplot2dDataset::LINES);
     Experiment experiment;
 
-
-    WifiHelper wifi = WifiHelper::Default ();
+    WifiHelper wifi;
     NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
     YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
     YansWifiChannelHelper wifiChannel  = YansWifiChannelHelper::Default ();
@@ -243,14 +241,18 @@
     NS_LOG_DEBUG (ratesControl[i]);
 
     experiment = Experiment (ratesControl[i]);
+    wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+    wifi.SetRemoteStationManager (wifiManager[i]);
     dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel);
     gnuplot.AddDataset (dataset);
 
   }
   gnuplot.SetTerminal ("postscript eps color enh \"Times-BoldItalic\"");
-  gnuplot.SetLegend ("Time (Seconds)", "Number of packets received");
-  gnuplot.SetExtra  ("set xrange [0:100]");
-  gnuplot.GenerateOutput (std::cout);
+  gnuplot.SetLegend ("Time ", "Number of packets received");
+  gnuplot.SetExtra  ("set xrange [1000:1100]");
+  gnuplot.SetTitle ("Number of Packets Received vs Time");
+  gnuplot.GenerateOutput (outfile);
+  outfile.close ();
 
   return 0;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/ping6.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+// Network topology
+//
+//       n0    n1  
+//       |     |
+//       =================
+//              LAN
+//
+// - ICMPv6 echo request flows from n0 to n1 and back with ICMPv6 echo reply
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "ping6.tr"
+
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/helper-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("Ping6Example");
+
+int main (int argc, char **argv)
+{
+#if 0 
+  LogComponentEnable ("Ping6Example", LOG_LEVEL_INFO);
+  LogComponentEnable ("Ipv6EndPointDemux", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6ListRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
+  LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
+  LogComponentEnable ("NdiscCache", LOG_LEVEL_ALL);
+#endif
+
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+  
+  NS_LOG_INFO ("Create nodes.");
+  NodeContainer n;
+  n.Create (4);
+
+  /* Install IPv4/IPv6 stack */
+  InternetStackHelper internetv6;
+  internetv6.SetIpv4StackInstall (false);
+  internetv6.Install (n);
+
+  NS_LOG_INFO ("Create channels.");
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+  NetDeviceContainer d = csma.Install (n);
+
+  Ipv6AddressHelper ipv6;
+  NS_LOG_INFO ("Assign IPv6 Addresses.");
+  Ipv6InterfaceContainer i = ipv6.Assign (d);
+
+  NS_LOG_INFO ("Create Applications.");
+
+  /* Create a Ping6 application to send ICMPv6 echo request from node zero to
+   * all-nodes (ff02::1).
+   */
+  uint32_t packetSize = 1024;
+  uint32_t maxPacketCount = 5;
+  Time interPacketInterval = Seconds (1.);
+  Ping6Helper ping6;
+
+/*
+  ping6.SetLocal (i.GetAddress (0, 1)); 
+  ping6.SetRemote (i.GetAddress (1, 1));
+*/
+  ping6.SetIfIndex (i.GetInterfaceIndex (0));
+  ping6.SetRemote (Ipv6Address::GetAllNodesMulticast ());
+
+  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+  ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
+  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  ApplicationContainer apps = ping6.Install (n.Get (0));
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (10.0));
+
+  std::ofstream ascii;
+  ascii.open ("ping6.tr");
+  CsmaHelper::EnablePcapAll (std::string ("ping6"), true);
+  CsmaHelper::EnableAsciiAll (ascii);
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/radvd-two-prefix.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,216 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: David Gross <gdavid.devel@gmail.com>
+ *         Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+// Network topology
+// //
+// //             n0   R    n1
+// //             |    _    |
+// //             ====|_|====
+// //                router
+// // - R sends RA to n0's subnet (2001:1::/64 and 2001:ABCD::/64);
+// // - R interface to n0 has two addresses with following prefixes 2001:1::/64 and 2001:ABCD::/64;
+// // - R sends RA to n1's subnet (2001:2::/64);
+// // - n0 ping6 n1.
+// //
+// // - Tracing of queues and packet receptions to file "radvd-two-prefix.tr"
+
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/helper-module.h"
+
+#include "ns3/ipv6-routing-table-entry.h"
+#include "ns3/radvd.h"
+#include "ns3/radvd-interface.h"
+#include "ns3/radvd-prefix.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("RadvdExample");
+
+class StackHelper
+{
+  public:
+
+    /**
+     * \brief Add an address to a IPv6 node.
+     * \param n node
+     * \param interface interface index
+     * \param address IPv6 address to add
+     */
+    inline void AddAddress (Ptr<Node>& n, uint32_t interface, Ipv6Address address)
+    {
+      Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+      ipv6->AddAddress (interface, address);
+    }
+
+    /**
+     * \brief Print the routing table.
+     * \param n the node
+     */
+    inline void PrintRoutingTable (Ptr<Node>& n)
+    {
+      Ptr<Ipv6StaticRouting> routing = 0;
+      Ipv6StaticRoutingHelper routingHelper;
+      Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+      uint32_t nbRoutes = 0;
+      Ipv6RoutingTableEntry route;
+
+      routing = routingHelper.GetStaticRouting (ipv6);
+
+      std::cout << "Routing table of " << n << " : " << std::endl;
+      std::cout << "Destination\t\t\t\t" << "Gateway\t\t\t\t\t" << "Interface\t" << std::endl;
+
+      nbRoutes = routing->GetNRoutes ();
+      for (uint32_t i = 0 ; i < nbRoutes ; i++)
+      {
+        route = routing->GetRoute (i);
+        std::cout << route.GetDest () << "\t"
+          << route.GetGateway () << "\t"
+          << route.GetInterface () << "\t" << std::endl;
+      }
+    }
+};
+
+int main (int argc, char** argv)
+{
+#if 0 
+  LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6RawSocketImpl", LOG_LEVEL_ALL);
+  LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
+  LogComponentEnable ("RadvdApplication", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
+#endif
+
+	CommandLine cmd;
+  cmd.Parse (argc, argv);
+  
+	NS_LOG_INFO ("Create nodes.");
+	Ptr<Node> n0 = CreateObject<Node> ();
+	Ptr<Node> r = CreateObject<Node> ();
+	Ptr<Node> n1 = CreateObject<Node> ();
+
+	NodeContainer net1 (n0, r);
+	NodeContainer net2 (r, n1);
+	NodeContainer all (n0, r, n1);
+  StackHelper stackHelper;
+
+	NS_LOG_INFO ("Create IPv6 Internet Stack");
+  InternetStackHelper internetv6;
+  internetv6.Install (all);
+
+  NS_LOG_INFO ("Create channels.");
+	CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+	NetDeviceContainer d1 = csma.Install (net1); /* n0 - R */
+	NetDeviceContainer d2 = csma.Install (net2); /* R - n1 */
+
+	NS_LOG_INFO ("Create networks and assign IPv6 Addresses.");
+	Ipv6AddressHelper ipv6;
+
+  /* first subnet */
+  ipv6.NewNetwork (Ipv6Address ("2001:1::"), 64);
+  NetDeviceContainer tmp;
+  tmp.Add (d1.Get (0)); /* n0 */
+  Ipv6InterfaceContainer iic1 = ipv6.AssignWithoutAddress (tmp); /* n0 interface */
+
+  NetDeviceContainer tmp2;
+  tmp2.Add (d1.Get (1)); /* R */
+  Ipv6InterfaceContainer iicr1 = ipv6.Assign (tmp2); /* R interface to the first subnet is just statically assigned */
+  iicr1.SetRouter (0, true);
+  iic1.Add (iicr1);
+
+  /* add another IPv6 address for second prefix advertised on first subnet */
+  stackHelper.AddAddress (r, iic1.GetInterfaceIndex (1), Ipv6Address ("2001:ABCD::2"));
+
+  /* second subnet R - n1 */
+  ipv6.NewNetwork (Ipv6Address ("2001:2::"), 64);
+  NetDeviceContainer tmp3;
+  tmp3.Add (d2.Get (0)); /* R */
+  Ipv6InterfaceContainer iicr2 = ipv6.Assign (tmp3); /* R interface */
+  iicr2.SetRouter (0, true);
+
+  NetDeviceContainer tmp4;
+  tmp4.Add (d2.Get (1)); /* n1 */
+  Ipv6InterfaceContainer iic2 = ipv6.AssignWithoutAddress (tmp4); 
+  iic2.Add (iicr2);
+
+  /* radvd configuration */
+  Ipv6Address prefix ("2001:1::0"); /* create the prefix */
+  Ipv6Address prefixBis ("2001:ABCD::0"); /* create the prefix */
+  Ipv6Address prefix2 ("2001:2::0"); /* create the prefix */
+  uint32_t indexRouter = iic1.GetInterfaceIndex (1); /* R interface (n0 - R) */
+  uint32_t indexRouter2 = iic2.GetInterfaceIndex (1); /* R interface (R - n1) */
+  Ptr<Radvd> radvd = CreateObject<Radvd> ();
+  Ptr<RadvdInterface> routerInterface = Create<RadvdInterface> (indexRouter, 2000, 1000);
+  Ptr<RadvdPrefix> routerPrefix = Create<RadvdPrefix> (prefix, 64, 3, 5);
+  Ptr<RadvdPrefix> routerPrefixBis = Create<RadvdPrefix> (prefixBis, 64, 3, 5);
+  Ptr<RadvdInterface> routerInterface2 = Create<RadvdInterface> (indexRouter2, 2000, 1000);
+  Ptr<RadvdPrefix> routerPrefix2 = Create<RadvdPrefix> (prefix2, 64, 3, 5);
+
+  /* first interface advertise two prefixes (2001:1::/64 and 2001:ABCD::/64) */
+  /* prefix is added in the inverse order in packet */
+  routerInterface->AddPrefix (routerPrefix);
+  routerInterface->AddPrefix (routerPrefixBis);
+  routerInterface2->AddPrefix (routerPrefix2);
+  radvd->AddConfiguration (routerInterface);
+  radvd->AddConfiguration (routerInterface2);
+
+  r->AddApplication (radvd);
+  radvd->Start (Seconds (1.0));
+  radvd->Stop (Seconds (2.0));
+
+  /* Create a Ping6 application to send ICMPv6 echo request from n0 to n1 via R */
+  uint32_t packetSize = 1024;
+  uint32_t maxPacketCount = 8;
+  Time interPacketInterval = Seconds (1.);
+  Ping6Helper ping6;
+
+  /* ping6.SetLocal (iic1.GetAddress (0, 1)); */
+  ping6.SetRemote (Ipv6Address ("2001:2::200:ff:fe00:4")); /* should be n1 address after autoconfiguration */
+  ping6.SetIfIndex (iic1.GetInterfaceIndex (0));
+
+  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+  ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
+  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  ApplicationContainer apps = ping6.Install (net1.Get (0));
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (9.0));
+
+  /* RA should be received, two prefixes + routes + default route should be present */
+  Simulator::Schedule (Seconds (2.0), &StackHelper::PrintRoutingTable, &stackHelper, n0); 
+  /* at the end, RA addresses and routes should be cleared */
+  Simulator::Schedule (Seconds (10.0), &StackHelper::PrintRoutingTable, &stackHelper, n0); 
+
+	std::ofstream ascii;
+  ascii.open ("radvd-two-prefix.tr");
+  CsmaHelper::EnablePcapAll (std::string ("radvd-two-prefix"), true);
+  CsmaHelper::EnableAsciiAll (ascii);
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/radvd.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,156 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: David Gross <gdavid.devel@gmail.com>
+ *         Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+// Network topology
+// //
+// //             n0   R    n1
+// //             |    _    |
+// //             ====|_|====
+// //                router
+// // - R sends RA to n0's subnet (2001:1::/64);
+// // - R sends RA to n1's subnet (2001:2::/64);
+// // - n0 ping6 n1.
+// //
+// // - Tracing of queues and packet receptions to file "radvd.tr"
+
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/helper-module.h"
+
+#include "ns3/radvd.h"
+#include "ns3/radvd-interface.h"
+#include "ns3/radvd-prefix.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("RadvdExample");
+
+int main (int argc, char** argv)
+{
+#if 0 
+  LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6RawSocketImpl", LOG_LEVEL_ALL);
+  LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
+  LogComponentEnable ("RadvdApplication", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
+#endif
+
+	CommandLine cmd;
+  cmd.Parse (argc, argv);
+  
+	NS_LOG_INFO ("Create nodes.");
+	Ptr<Node> n0 = CreateObject<Node> ();
+	Ptr<Node> r = CreateObject<Node> ();
+	Ptr<Node> n1 = CreateObject<Node> ();
+
+	NodeContainer net1 (n0, r);
+	NodeContainer net2 (r, n1);
+	NodeContainer all (n0, r, n1);
+
+	NS_LOG_INFO ("Create IPv6 Internet Stack");
+  InternetStackHelper internetv6;
+  internetv6.Install (all);
+
+  NS_LOG_INFO ("Create channels.");
+	CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+	NetDeviceContainer d1 = csma.Install (net1); /* n0 - R */
+	NetDeviceContainer d2 = csma.Install (net2); /* R - n1 */
+
+	NS_LOG_INFO ("Create networks and assign IPv6 Addresses.");
+	Ipv6AddressHelper ipv6;
+
+  /* first subnet */
+  ipv6.NewNetwork (Ipv6Address ("2001:1::"), 64);
+  NetDeviceContainer tmp;
+  tmp.Add (d1.Get (0)); /* n0 */
+  Ipv6InterfaceContainer iic1 = ipv6.AssignWithoutAddress (tmp); /* n0 interface */
+
+  NetDeviceContainer tmp2;
+  tmp2.Add (d1.Get (1)); /* R */
+  Ipv6InterfaceContainer iicr1 = ipv6.Assign (tmp2); /* R interface to the first subnet is just statically assigned */
+  iicr1.SetRouter (0, true);
+  iic1.Add (iicr1);
+
+  /* second subnet R - n1 */
+  ipv6.NewNetwork (Ipv6Address ("2001:2::"), 64);
+  NetDeviceContainer tmp3;
+  tmp3.Add (d2.Get (0)); /* R */
+  Ipv6InterfaceContainer iicr2 = ipv6.Assign (tmp3); /* R interface */
+  iicr2.SetRouter (0, true);
+
+  NetDeviceContainer tmp4;
+  tmp4.Add (d2.Get (1)); /* n1 */
+  Ipv6InterfaceContainer iic2 = ipv6.AssignWithoutAddress (tmp4); 
+  iic2.Add (iicr2);
+
+  /* radvd configuration */
+  Ipv6Address prefix ("2001:1::0"); /* create the prefix */
+  Ipv6Address prefix2 ("2001:2::0"); /* create the prefix */
+  uint32_t indexRouter = iic1.GetInterfaceIndex (1); /* R interface (n0 - R) */
+  uint32_t indexRouter2 = iic2.GetInterfaceIndex (1); /* R interface (R - n1) */
+  Ptr<Radvd> radvd = CreateObject<Radvd> ();
+  Ptr<RadvdInterface> routerInterface = Create<RadvdInterface> (indexRouter, 5000, 1000);
+  Ptr<RadvdPrefix> routerPrefix = Create<RadvdPrefix> (prefix, 64, 3, 5);
+  Ptr<RadvdInterface> routerInterface2 = Create<RadvdInterface> (indexRouter2, 5000, 1000);
+  Ptr<RadvdPrefix> routerPrefix2 = Create<RadvdPrefix> (prefix2, 64, 3, 5);
+
+  routerInterface->AddPrefix (routerPrefix);
+  routerInterface2->AddPrefix (routerPrefix2);
+  radvd->AddConfiguration (routerInterface);
+  radvd->AddConfiguration (routerInterface2);
+
+  r->AddApplication (radvd);
+  radvd->Start (Seconds (1.0));
+  radvd->Stop (Seconds (10.0));
+
+  /* Create a Ping6 application to send ICMPv6 echo request from n0 to n1 via R */
+  uint32_t packetSize = 1024;
+  uint32_t maxPacketCount = 5;
+  Time interPacketInterval = Seconds (1.);
+  Ping6Helper ping6;
+
+  /* ping6.SetLocal (iic1.GetAddress (0, 1)); */
+  ping6.SetRemote (Ipv6Address ("2001:2::200:ff:fe00:4")); /* should be n1 address after autoconfiguration */
+  ping6.SetIfIndex (iic1.GetInterfaceIndex (0));
+
+  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+  ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
+  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  ApplicationContainer apps = ping6.Install (net1.Get (0));
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (7.0));
+
+	std::ofstream ascii;
+  ascii.open ("radvd.tr");
+  CsmaHelper::EnablePcapAll (std::string ("radvd"), true);
+  CsmaHelper::EnableAsciiAll (ascii);
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-routing-ping6.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,110 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: David Gross <david.gross@eturs.u-strasbg.fr>
+ *         Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+// Network topology
+// //
+// //             n0   r    n1
+// //             |    _    |
+// //             ====|_|====
+// //                router
+// //
+// // - Tracing of queues and packet receptions to file "simple-routing-ping6.tr"
+
+#include <fstream>
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/helper-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("SimpleRoutingUdp6Example");
+
+int 
+main (int argc, char** argv)
+{
+#if 0 
+  LogComponentEnable ("Ipv6L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL);
+#endif
+
+	CommandLine cmd;
+  cmd.Parse (argc, argv);
+  
+	NS_LOG_INFO ("Create nodes.");
+	Ptr<Node> n0 = CreateObject<Node> ();
+	Ptr<Node> r = CreateObject<Node> ();
+	Ptr<Node> n1 = CreateObject<Node> ();
+
+	NodeContainer net1 (n0, r);
+	NodeContainer net2 (r, n1);
+	NodeContainer all (n0, r, n1);
+
+	NS_LOG_INFO ("Create IPv6 Internet Stack");
+  InternetStackHelper internetv6;
+  internetv6.Install (all);
+
+  NS_LOG_INFO ("Create channels.");
+	CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+	NetDeviceContainer d1 = csma.Install (net1);
+	NetDeviceContainer d2 = csma.Install (net2);
+
+	NS_LOG_INFO ("Create networks and assign IPv6 Addresses.");
+	Ipv6AddressHelper ipv6;
+	ipv6.NewNetwork (Ipv6Address ("2001:1::"), 64);
+	Ipv6InterfaceContainer i1 = ipv6.Assign (d1);
+  i1.SetRouter (1, true);
+	ipv6.NewNetwork (Ipv6Address ("2001:2::"), 64);
+	Ipv6InterfaceContainer i2 = ipv6.Assign (d2);
+  i2.SetRouter (0, true);
+
+  /* Create a Ping6 application to send ICMPv6 echo request from n0 to n1 via r */
+  uint32_t packetSize = 1024;
+  uint32_t maxPacketCount = 5;
+  Time interPacketInterval = Seconds (1.);
+  Ping6Helper ping6;
+
+  ping6.SetLocal (i1.GetAddress (0, 1));
+  ping6.SetRemote (i2.GetAddress (1, 1)); 
+  /* ping6.SetRemote (Ipv6Address::GetAllNodesMulticast ()); */
+
+  ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount));
+  ping6.SetAttribute ("Interval", TimeValue (interPacketInterval));
+  ping6.SetAttribute ("PacketSize", UintegerValue (packetSize));
+  ApplicationContainer apps = ping6.Install (net1.Get (0));
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (20.0));
+
+	std::ofstream ascii;
+  ascii.open ("simple-routing-ping6.tr");
+  CsmaHelper::EnablePcapAll (std::string ("simple-routing-ping6"), true);
+  CsmaHelper::EnableAsciiAll (ascii);
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
+
--- a/examples/static-routing-slash32.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/examples/static-routing-slash32.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -87,12 +87,12 @@
   int32_t ifIndexA = ipv4A->AddInterface (deviceA);
   int32_t ifIndexC = ipv4C->AddInterface (deviceC);
     
-  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255"));
+  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("/32"));
   ipv4A->AddAddress (ifIndexA, ifInAddrA);
   ipv4A->SetMetric (ifIndexA, 1);
   ipv4A->SetUp (ifIndexA);
 
-  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255"));
+  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("/32"));
   ipv4C->AddAddress (ifIndexC, ifInAddrC);
   ipv4C->SetMetric (ifIndexC, 1);
   ipv4C->SetUp (ifIndexC);
--- a/examples/wifi-ap.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/examples/wifi-ap.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -26,6 +26,7 @@
 #include "ns3/mobility-module.h"
 #include "ns3/contrib-module.h"
 #include "ns3/wifi-module.h"
+#include "ns3/athstats-helper.h"
 
 #include <iostream>
 
@@ -110,6 +111,9 @@
 
 int main (int argc, char *argv[])
 {
+  CommandLine cmd;
+   cmd.Parse (argc, argv);
+   
   Packet::EnablePrinting ();
 
   // enable rts cts all the time.
@@ -175,6 +179,10 @@
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/RxError", MakeCallback (&PhyRxErrorTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/Tx", MakeCallback (&PhyTxTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Phy/State/State", MakeCallback (&PhyStateTrace));
+  
+  AthstatsHelper athstats;
+  athstats.EnableAthstats("athstats-sta", stas);
+  athstats.EnableAthstats("athstats-ap", ap);
 
   Simulator::Run ();
 
--- a/examples/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/examples/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -151,6 +151,26 @@
       ['point-to-point', 'internet-stack'])
     obj.source = 'test-ipv6.cc'
 
+    obj = bld.create_ns3_program('ping6',
+      ['csma', 'internet-stack'])
+    obj.source = 'ping6.cc'
+
+    obj = bld.create_ns3_program('simple-routing-ping6',
+      ['csma', 'internet-stack'])
+    obj.source = 'simple-routing-ping6.cc'
+
+    obj = bld.create_ns3_program('icmpv6-redirect',
+      ['csma', 'internet-stack'])
+    obj.source = 'icmpv6-redirect.cc'
+
+    obj = bld.create_ns3_program('radvd',
+      ['csma', 'internet-stack'])
+    obj.source = 'radvd.cc'
+
+    obj = bld.create_ns3_program('radvd-two-prefix',
+      ['csma', 'internet-stack'])
+    obj.source = 'radvd-two-prefix.cc'
+
     env = bld.env_of_name('default')
     if env['ENABLE_EMU']:
         obj = bld.create_ns3_program('emu-udp-echo', ['emu', 'internet-stack'])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/ping6/ping6.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,236 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+#include "ns3/socket-factory.h"
+#include "ns3/packet.h"
+#include "ns3/socket.h"
+#include "ns3/uinteger.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/icmpv6-header.h"
+#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/ipv6-header.h"
+
+#include "ping6.h"
+
+namespace ns3 
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ping6Application");
+
+NS_OBJECT_ENSURE_REGISTERED (Ping6);
+
+TypeId Ping6::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ping6")
+    .SetParent<Application>()
+    .AddConstructor<Ping6>()
+    .AddAttribute ("MaxPackets", 
+        "The maximum number of packets the application will send",
+        UintegerValue (100),
+        MakeUintegerAccessor (&Ping6::m_count),
+        MakeUintegerChecker<uint32_t>())
+    .AddAttribute ("Interval", 
+        "The time to wait between packets",
+        TimeValue (Seconds (1.0)),
+        MakeTimeAccessor (&Ping6::m_interval),
+        MakeTimeChecker ())
+    .AddAttribute ("RemoteIpv6", 
+        "The Ipv6Address of the outbound packets",
+        Ipv6AddressValue (),
+        MakeIpv6AddressAccessor (&Ping6::m_peerAddress),
+        MakeIpv6AddressChecker ())
+    .AddAttribute ("LocalIpv6", 
+        "Local Ipv6Address of the sender",
+        Ipv6AddressValue (),
+        MakeIpv6AddressAccessor (&Ping6::m_localAddress),
+        MakeIpv6AddressChecker ())
+    .AddAttribute ("PacketSize", 
+        "Size of packets generated",
+        UintegerValue (100),
+        MakeUintegerAccessor (&Ping6::m_size),
+        MakeUintegerChecker<uint32_t>())
+    ;
+  return tid;
+}
+
+Ping6::Ping6 ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_sent = 0;
+  m_socket = 0;
+  m_seq = 0;
+  m_sendEvent = EventId ();
+}
+
+Ping6::~Ping6 ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_socket = 0;
+}
+
+void Ping6::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Application::DoDispose ();
+}
+
+void Ping6::StartApplication ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (!m_socket)
+  {
+    TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
+    m_socket = Socket::CreateSocket (GetNode (), tid);
+
+    NS_ASSERT (m_socket);
+
+    m_socket->Bind (Inet6SocketAddress (m_localAddress, 0));
+    m_socket->Connect (Inet6SocketAddress (m_peerAddress, 0));
+    m_socket->SetAttribute ("Protocol", UintegerValue (58)); /* ICMPv6 */
+    m_socket->SetRecvCallback (MakeCallback (&Ping6::HandleRead, this));
+  }
+
+  ScheduleTransmit (Seconds (0.));
+}
+
+void Ping6::SetLocal (Ipv6Address ipv6) 
+{
+  NS_LOG_FUNCTION (this << ipv6);
+  m_localAddress = ipv6;
+}
+
+void Ping6::SetRemote (Ipv6Address ipv6)
+{
+  NS_LOG_FUNCTION (this << ipv6);
+  m_peerAddress = ipv6;
+}
+
+void Ping6::StopApplication ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_socket)
+  {
+    m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> >());
+  }
+
+  Simulator::Cancel (m_sendEvent);
+}
+
+void Ping6::SetIfIndex (uint32_t ifIndex)
+{
+  m_ifIndex = ifIndex;
+}
+
+void Ping6::ScheduleTransmit (Time dt)
+{
+  NS_LOG_FUNCTION (this << dt);
+  m_sendEvent = Simulator::Schedule (dt, &Ping6::Send, this);
+}
+
+void Ping6::Send ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_ASSERT (m_sendEvent.IsExpired ());
+  Ptr<Packet> p = 0;
+  uint8_t data[4];
+  Ipv6Address src;
+  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
+
+  if (m_ifIndex > 0)
+  {
+    /* hack to have ifIndex in Ipv6RawSocketImpl
+     * maybe add a SetIfIndex in Ipv6RawSocketImpl directly 
+     */
+    src = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, 0).GetAddress ();
+  }
+  else
+  {
+    src = m_localAddress;
+  }
+
+  data[0] = 0xDE;
+  data[1] = 0xAD;
+  data[2] = 0xBE;
+  data[3] = 0xEF;
+
+  p = Create<Packet>(data, sizeof (data));
+  Icmpv6Echo req (1);
+
+  req.SetId (0xBEEF);
+  req.SetSeq (m_seq);
+  m_seq++;
+  
+  /* we do not calculate pseudo header checksum here, because we are not sure about 
+   * source IPv6 address. Checksum is calculated in Ipv6RawSocketImpl.
+   */
+
+  p->AddHeader (req);
+  m_socket->Bind (Inet6SocketAddress (src, 0));
+  m_socket->Send (p, 0);
+  ++m_sent;
+
+  NS_LOG_INFO ("Sent " << p->GetSize () << " bytes to " << m_peerAddress);
+
+  if (m_sent < m_count)
+  {
+    ScheduleTransmit (m_interval);
+  }
+}
+
+void Ping6::HandleRead (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+
+  Ptr<Packet> packet=0;
+  Address from;
+  while (packet = socket->RecvFrom (from))
+  {
+    if (Inet6SocketAddress::IsMatchingType (from))
+    {
+      Ipv6Header hdr;
+      Icmpv6Echo reply (0);
+      Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from);
+
+      packet->RemoveHeader (hdr);
+
+      switch (*packet->PeekData ())
+      {
+        case Icmpv6Header::ICMPV6_ECHO_REPLY:
+          packet->RemoveHeader (reply);
+
+          NS_LOG_INFO ("Received Echo Reply size  = " << std::dec << packet->GetSize () << " bytes from " << address.GetIpv6 () << " id =  " << (uint16_t)reply.GetId () << " seq = " << (uint16_t)reply.GetSeq ());
+          break;
+        default:
+          /* other type, discard */
+          break;
+      }
+    }
+  }
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/ping6/ping6.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,171 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef PING6_H
+#define PING6_H
+
+#include "ns3/application.h"
+#include "ns3/event-id.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv6-address.h"
+
+namespace ns3
+{
+
+class Packet;
+class Socket;
+
+/**
+ * \class Ping6
+ * \brief A ping6 application.
+ */
+class Ping6 : public Application
+{
+  public:
+    /**
+     * \brief Get the type ID.
+     * \return type ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Constructor.
+     */
+    Ping6 ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ping6 ();
+
+    /**
+     * \brief Set the local address.
+     * \param ipv6 the local IPv6 address
+     */
+    void SetLocal (Ipv6Address ipv6);
+
+    /**
+     * \brief Set the remote peer.
+     * \param ipv6 IPv6 address of the peer
+     */
+    void SetRemote (Ipv6Address ipv6);
+
+    /**
+     * \brief Set the out interface index.
+     * This is to send to link-local (unicast or multicast) address
+     * when a node has multiple interfaces.
+     * \param ifIndex interface index
+     */
+    void SetIfIndex (uint32_t ifIndex);
+
+  protected:
+    /**
+     * \brief Dispose this object;
+     */
+    virtual void DoDispose ();
+
+  private:
+    /**
+     * \brief Start the application.
+     */
+    virtual void StartApplication ();
+
+    /**
+     * \brief Stop the application.
+     */
+    virtual void StopApplication ();
+
+    /**
+     * \brief Schedule sending a packet.
+     * \param dt interval between packet
+     */
+    void ScheduleTransmit (Time dt);
+
+    /**
+     * \brief Send a packet.
+     */
+    void Send ();
+
+    /**
+     * \brief Receive method.
+     * \param socket socket that receive a packet
+     */
+    void HandleRead (Ptr<Socket> socket);
+
+    /**
+     * \brief Peer IPv6 address.
+     */
+    Ipv6Address m_address;
+
+    /**
+     * \brief Number of "Echo request" packets that will be sent.
+     */
+    uint32_t m_count;
+
+    /**
+     * \brief Number of packets sent.
+     */
+    uint32_t m_sent;
+
+    /**
+     * \brief Size of the packet.
+     */
+    uint32_t m_size;
+
+    /**
+     * \brief Intervall between packets sent.
+     */
+    Time m_interval;
+
+    /**
+     * \brief Local address.
+     */
+    Ipv6Address m_localAddress;
+
+    /**
+     * \brief Peer address.
+     */
+    Ipv6Address m_peerAddress;
+
+    /**
+     * \brief Local socket.
+     */
+    Ptr<Socket> m_socket;
+
+    /**
+     * \brief Sequence number.
+     */
+    uint16_t m_seq;
+
+    /**
+     * \brief Event ID.
+     */
+    EventId m_sendEvent;
+
+    /**
+     * \brief Out interface (i.e. for link-local communication).
+     */
+    uint32_t m_ifIndex;
+};
+
+} /* namespace ns3 */
+
+#endif /* PING6_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/ping6/waf	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/ping6/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,13 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('ping6', ['internet-stack'])
+    module.source = [
+        'ping6.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'ping6'
+    headers.source = [
+        'ping6.h',
+        ]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd-interface.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,292 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "radvd-interface.h"
+
+namespace ns3 
+{
+
+RadvdInterface::RadvdInterface (uint32_t interface)
+  : m_interface (interface)
+{
+  /* initialize default value as specified in radvd.conf manpage */
+  m_sendAdvert = true;
+  m_maxRtrAdvInterval = 600000;
+  m_minRtrAdvInterval = (uint32_t)(double)(0.33 * m_maxRtrAdvInterval);
+  m_minDelayBetweenRAs = 3000;
+  m_managedFlag = false;
+  m_otherConfigFlag = false;
+  m_linkMtu = 0; /* 0 means not sending MTU option in RA */
+  m_reachableTime = 0; /* means unspecified for the router */
+  m_retransTimer = 0; /* means unspecified for the router */
+  m_curHopLimit = 64;
+  m_defaultLifeTime = 3 * m_maxRtrAdvInterval;
+  m_defaultPreference = 1;
+  m_sourceLLAddress = true;
+  m_homeAgentFlag = false;
+  m_homeAgentInfo = false;
+  m_homeAgentLifeTime = 0;
+  m_homeAgentPreference = 0;
+  m_mobRtrSupportFlag = false;
+  m_intervalOpt = false;
+}
+
+RadvdInterface::RadvdInterface (uint32_t interface, uint32_t maxRtrAdvInterval, uint32_t minRtrAdvInterval)
+  : m_interface (interface)
+{
+  NS_ASSERT (maxRtrAdvInterval > minRtrAdvInterval);
+  m_sendAdvert = true;
+  m_maxRtrAdvInterval = maxRtrAdvInterval;
+  m_minRtrAdvInterval = minRtrAdvInterval;
+  m_minDelayBetweenRAs = 3000;
+  m_managedFlag = false;
+  m_otherConfigFlag = false;
+  m_linkMtu = 0; /* 0 means not sending MTU option in RA */
+  m_reachableTime = 0; /* means unspecified for the router */
+  m_retransTimer = 0; /* means unspecified for the router */
+  m_curHopLimit = 64;
+  m_defaultLifeTime = 3 * m_maxRtrAdvInterval;
+  m_defaultPreference = 1;
+  m_sourceLLAddress = true;
+  m_homeAgentFlag = false;
+  m_homeAgentInfo = false;
+  m_homeAgentLifeTime = 0;
+  m_homeAgentPreference = 0;
+  m_mobRtrSupportFlag = false;
+  m_intervalOpt = false;
+}
+
+RadvdInterface::~RadvdInterface ()
+{
+  /* clear prefixes */
+  for (RadvdPrefixListI it = m_prefixes.begin () ; it != m_prefixes.end () ; ++it)
+  {
+    (*it) = 0;
+  }
+  m_prefixes.clear ();
+}
+
+void RadvdInterface::AddPrefix (Ptr<RadvdPrefix> routerPrefix)
+{
+  m_prefixes.push_back (routerPrefix);
+}
+
+
+uint32_t RadvdInterface::GetInterface () const
+{
+  return m_interface;
+}
+
+std::list<Ptr<RadvdPrefix> > RadvdInterface::GetPrefixes () const
+{
+  return m_prefixes;
+}
+
+bool RadvdInterface::IsSendAdvert () const
+{
+  return m_sendAdvert;
+}
+
+void RadvdInterface::SetSendAdvert (bool sendAdvert)
+{
+  m_sendAdvert = sendAdvert;
+}
+
+uint32_t RadvdInterface::GetMaxRtrAdvInterval () const
+{
+  return m_maxRtrAdvInterval;
+}
+
+void RadvdInterface::SetMaxRtrAdvInterval (uint32_t maxRtrAdvInterval)
+{
+  m_maxRtrAdvInterval = maxRtrAdvInterval;
+}
+
+uint32_t RadvdInterface::GetMinRtrAdvInterval () const
+{
+  return m_minRtrAdvInterval;
+}
+
+void RadvdInterface::SetMinRtrAdvInterval (uint32_t minRtrAdvInterval)
+{
+  m_minRtrAdvInterval = minRtrAdvInterval;
+}
+
+uint32_t RadvdInterface::GetMinDelayBetweenRAs () const
+{
+  return m_minDelayBetweenRAs;
+}
+
+void RadvdInterface::SetMinDelayBetweenRAs (uint32_t minDelayBetweenRAs)
+{
+  m_minDelayBetweenRAs = minDelayBetweenRAs;
+}
+
+bool RadvdInterface::IsManagedFlag () const
+{
+  return m_managedFlag;
+}
+
+void RadvdInterface::SetManagedFlag (bool managedFlag)
+{
+  m_managedFlag = managedFlag;
+}
+
+bool RadvdInterface::IsOtherConfigFlag () const
+{
+  return m_otherConfigFlag;
+}
+
+void RadvdInterface::SetOtherConfigFlag (bool otherConfigFlag)
+{
+  m_otherConfigFlag = otherConfigFlag;
+}
+
+uint32_t RadvdInterface::GetLinkMtu () const
+{
+  return m_linkMtu;
+}
+
+void RadvdInterface::SetLinkMtu (uint32_t linkMtu)
+{
+  m_linkMtu = linkMtu;
+}
+
+uint32_t RadvdInterface::GetReachableTime () const
+{
+  return m_reachableTime;
+}
+
+void RadvdInterface::SetReachableTime (uint32_t reachableTime)
+{
+  m_reachableTime = reachableTime;
+}
+
+uint32_t RadvdInterface::GetDefaultLifeTime () const
+{
+  return m_defaultLifeTime;
+}
+
+void RadvdInterface::SetDefaultLifeTime (uint32_t defaultLifeTime)
+{
+  m_defaultLifeTime = defaultLifeTime;
+}
+
+uint32_t RadvdInterface::GetRetransTimer () const
+{
+  return m_retransTimer;
+}
+
+void RadvdInterface::SetRetransTimer (uint32_t retransTimer)
+{
+  m_retransTimer = retransTimer;
+}
+
+uint8_t RadvdInterface::GetCurHopLimit () const
+{
+  return m_curHopLimit;
+}
+
+void RadvdInterface::SetCurHopLimit (uint8_t curHopLimit)
+{
+  m_curHopLimit = curHopLimit;
+}
+
+uint8_t RadvdInterface::GetDefaultPreference () const
+{
+  return m_defaultPreference;
+}
+
+void RadvdInterface::SetDefaultPreference (uint8_t defaultPreference)
+{
+  m_defaultPreference = defaultPreference;
+}
+
+bool RadvdInterface::IsSourceLLAddress () const
+{
+  return m_sourceLLAddress;
+}
+
+void RadvdInterface::SetSourceLLAddress (bool sourceLLAddress)
+{
+  m_sourceLLAddress = sourceLLAddress;
+}
+
+bool RadvdInterface::IsHomeAgentFlag () const
+{
+  return m_homeAgentFlag;
+}
+
+void RadvdInterface::SetHomeAgentFlag (bool homeAgentFlag)
+{
+  m_homeAgentFlag = homeAgentFlag;
+}
+
+bool RadvdInterface::IsHomeAgentInfo () const
+{
+  return m_homeAgentInfo;
+}
+
+void RadvdInterface::SetHomeAgentInfo (bool homeAgentInfo)
+{
+  m_homeAgentInfo = homeAgentInfo;
+}
+
+uint32_t RadvdInterface::GetHomeAgentLifeTime () const
+{
+  return m_homeAgentLifeTime;
+}
+
+void RadvdInterface::SetHomeAgentLifeTime (uint32_t homeAgentLifeTime)
+{
+  m_homeAgentLifeTime = homeAgentLifeTime;
+}
+
+uint32_t RadvdInterface::GetHomeAgentPreference () const
+{
+  return m_homeAgentPreference;
+}
+
+void RadvdInterface::SetHomeAgentPreference (uint32_t homeAgentPreference)
+{
+  m_homeAgentPreference = homeAgentPreference;
+}
+
+bool RadvdInterface::IsMobRtrSupportFlag () const
+{
+  return m_mobRtrSupportFlag;
+}
+
+void RadvdInterface::SetMobRtrSupportFlag (bool mobRtrSupportFlag)
+{
+  m_mobRtrSupportFlag = mobRtrSupportFlag;
+}
+
+bool RadvdInterface::IsIntervalOpt () const
+{
+  return m_intervalOpt;
+}
+
+void RadvdInterface::SetIntervalOpt (bool intervalOpt)
+{
+  m_intervalOpt = intervalOpt;
+}
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd-interface.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,420 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef RADVD_INTERFACE_H
+#define RADVD_INTERFACE_H
+
+#include <list>
+
+#include "radvd-prefix.h"
+
+namespace ns3
+{
+
+/**
+ * \class RadvdInterface
+ * \brief Radvd interface configuration.
+ */
+class RadvdInterface : public RefCountBase
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param interface interface index
+     */
+    RadvdInterface (uint32_t interface);
+
+    /**
+     * \brief Constructor.
+     * \param interface interface index
+     * \param maxRtrAdvInterval maximum RA interval (ms)
+     * \param minRtrAdvInterval minimum RA interval (ms)
+     */
+    RadvdInterface (uint32_t interface, uint32_t maxRtrAdvInterval, uint32_t minRtrAdvInterval);
+
+    /**
+     * \brief Destructor.
+     */
+    ~RadvdInterface ();
+
+    /**
+     * \brief Get interface index for this configuration.
+     * \return interface index
+     */
+    uint32_t GetInterface () const;
+
+    /**
+     * \brief Get list of prefixes advertised for this interface.     
+     * \return list of IPv6 prefixes
+     */
+    std::list <Ptr<RadvdPrefix> > GetPrefixes () const;
+
+    /**
+     * \brief Add a prefix to advertise on interface.
+     * \param routerPrefix prefix to advertise
+     */
+    void AddPrefix (Ptr<RadvdPrefix> routerPrefix);
+    
+    /**
+     * \brief Is send advert enabled (periodic RA and reply to RS) ?
+     * \return send advert flag
+     */
+    bool IsSendAdvert () const;
+    
+    /**
+     * \brief Set send advert flag.
+     * \return sendAdvert value
+     */
+    void SetSendAdvert (bool sendAdvert);
+
+    /**
+     * \brief Get maximum RA interval.
+     * \return RA interval (ms)
+     */
+    uint32_t GetMaxRtrAdvInterval () const;
+
+    /**
+     * \brief Get maximum RA interval.
+     * \param maxRtrAdvInterval RA interval (ms)
+     */
+    void SetMaxRtrAdvInterval (uint32_t maxRtrAdvInterval);
+
+    /**
+     * \brief Get minimum RA interval 
+     * \return RA interval (ms)
+     */
+    uint32_t GetMinRtrAdvInterval () const;
+    
+    /**
+     * \brief Get minimum RA interval 
+     * \param minRtrAdvInterval RA interval (ms).
+     */
+    void SetMinRtrAdvInterval (uint32_t minRtrAdvInterval);
+
+    /**
+     * \brief Get minimum delay between RAs.
+     * \return minimum delay (ms)
+     */
+    uint32_t GetMinDelayBetweenRAs () const;
+    
+    /**
+     * \brief Set minimum delay between RAs.
+     * \param minDelayBetweenRAs minimum delay (ms)
+     */
+    void SetMinDelayBetweenRAs (uint32_t minDelayBetweenRAs);
+
+    /**
+     * \brief Is managed flag enabled ?
+     * \return managed flag
+     */
+    bool IsManagedFlag () const;
+    
+    /**
+     * \brief Set managed flag
+     * \param managedFlag value
+     */
+    void SetManagedFlag (bool managedFlag);
+
+    /**
+     * \brief Is "other config" flag enabled ?
+     * \return other config flag
+     */
+    bool IsOtherConfigFlag () const;
+    
+    /**
+     * \brief Set "other config" flag
+     * \param otherConfigFlag value
+     */
+    void SetOtherConfigFlag (bool otherConfigFlag);
+
+    /**
+     * \brief Get link MTU.
+     * \return link MTU
+     */
+    uint32_t GetLinkMtu () const;
+    
+    /**
+     * \brief Set link MTU.
+     * \param linkMtu link MTU
+     */
+    void SetLinkMtu (uint32_t linkMtu); 
+
+    /**
+     * \brief Get reachable time.
+     * \return reachable time
+     */
+    uint32_t GetReachableTime () const;
+    
+    /**
+     * \brief Set reachable time.
+     * \param reachableTime reachable time
+     */
+    void SetReachableTime (uint32_t reachableTime);
+
+    /**
+     * \brief Get default lifetime.
+     * \return default lifetime
+     */
+    uint32_t GetDefaultLifeTime () const;
+    
+    /**
+     * \brief Set default lifetime.
+     * \param defaultLifeTime default lifetime
+     */
+    void SetDefaultLifeTime (uint32_t defaultLifeTime);
+
+    /**
+     * \brief Get retransmission timer.
+     * \return retransmission timer
+     */
+    uint32_t GetRetransTimer () const;
+    
+    /**
+     * \brief Set retransmission timer.
+     * \param retransTimer retransmission timer
+     */
+    void SetRetransTimer (uint32_t retransTimer);
+
+    /**
+     * \brief Get current hop limit.
+     * \return current hop limit for the link
+     */
+    uint8_t GetCurHopLimit () const;
+    
+    /**
+     * \brief Set current hop limit.
+     * \param curHopLimit current hop limit for the link
+     */
+    void SetCurHopLimit (uint8_t curHopLimit); 
+
+    /**
+     * \brief Get default preference.
+     * \return default preference
+     */
+    uint8_t GetDefaultPreference () const;
+    
+    /**
+     * \brief Set default preference.
+     * \param defaultPreference default preference
+     */
+    void SetDefaultPreference (uint8_t defaultPreference);
+
+    /**
+     * \brief Is source LLA option should be included in RA ?
+     * \return true if source address is added in RA, false otherwise
+     */
+    bool IsSourceLLAddress () const;
+    
+    /**
+     * \brief Set flag to add or not LLA to RA.
+     * \param sourceLLAddress value
+     */
+    void SetSourceLLAddress (bool sourceLLAddress);
+
+    /**
+     * \brief Is "home agent" flag enabled ?
+     * \return "home agent" flag
+     */
+    bool IsHomeAgentFlag () const;
+    
+    /**
+     * \brief Set "home agent" flag.
+     * \param homeAgentFlag value
+     */
+    void SetHomeAgentFlag (bool homeAgentFlag);
+
+    /**
+     * \brief Is Home Agent Information option should be included in RA ?
+     * \return true if HA information option is added in RA, false otherwise
+     */
+    bool IsHomeAgentInfo () const;
+    
+    /**
+     * \brief Set flag to add or not HA information option to RA.
+     * \param homeAgentFlag value
+     */
+    void SetHomeAgentInfo (bool homeAgentFlag);
+    
+    /**
+     * \brief Get home agent lifetime.
+     * \return home agent lifetime
+     */
+    uint32_t GetHomeAgentLifeTime () const;
+    
+    /**
+     * \brief Set home agent lifetime.
+     * \param homeAgentLifeTime home agent lifetime
+     */
+    void SetHomeAgentLifeTime (uint32_t homeAgentLifeTime);
+    
+    /**
+     * \brief Get home agent preference.
+     * \return home agent preference
+     */
+    uint32_t GetHomeAgentPreference () const;
+    
+    /**
+     * \brief Set home agent preference.
+     * \param homeAgentPreference home agent preference
+     */
+    void SetHomeAgentPreference (uint32_t homeAgentPreference);
+
+    /**
+     * \brief Is "mobile router support" flag enabled ?
+     * \return "mobile router support" flag
+     */
+    bool IsMobRtrSupportFlag () const;
+    
+    /**
+     * \brief Set "mobile router support" flag.
+     * \param mobRtrSupportFlag value
+     */
+    void SetMobRtrSupportFlag (bool mobRtrSupportFlag);
+    
+    /**
+     * \brief Is advertisement interval option should be included in RA ?
+     * \return true if advertisement interval option is added in RA, false otherwise
+     */
+    bool IsIntervalOpt () const;
+    
+    /**
+     * \brief Set flag to add or not advertisement interval to RA.
+     * \param intervalOpt value
+     */
+    void SetIntervalOpt (bool intervalOpt);
+
+  private:
+    typedef std::list<Ptr<RadvdPrefix> > RadvdPrefixList;
+    typedef std::list<Ptr<RadvdPrefix> >::iterator RadvdPrefixListI;
+
+    /**
+     * \brief Interface to advertise RA.
+     */
+    uint32_t m_interface;
+
+    /**
+     * \brief List of prefixes to advertise.
+     */
+    RadvdPrefixList m_prefixes;
+
+    /**
+     * \brief Flag whether or not router sends periodic RA and respond to RS.
+     */
+    bool m_sendAdvert;
+
+    /**
+     * \brief Maximum RA interval in milliseconds.
+     */
+    uint32_t m_maxRtrAdvInterval;
+
+    /**
+     * \brief Minimum RA interval in milliseconds.
+     */
+    uint32_t m_minRtrAdvInterval;
+
+    /**
+     * \brief Minimum delay between RA in milliseconds.
+     */
+    uint32_t m_minDelayBetweenRAs;
+
+    /**
+     * \brief Managed flag. If true host use the stateful protocol for address autoconfiguration.
+     */
+    bool m_managedFlag;
+
+    /**
+     * \brief Other configuration flag. If true host use stateful protocol for other (non-address) information.
+     */
+    bool m_otherConfigFlag;
+
+    /**
+     * \brief Link MTU to use.
+     */
+    uint32_t m_linkMtu;
+
+    /**
+     * \brief Reachable time in milliseconds.
+     */
+    uint32_t m_reachableTime;
+
+    /**
+     * \brief Retransmission timer in milliseconds.
+     */
+    uint32_t m_retransTimer;
+
+    /**
+     * \brief Current hop limit (TTL).
+     */
+    uint32_t m_curHopLimit;
+
+    /**
+     * \brief Default life time in seconds.
+     */
+    uint32_t m_defaultLifeTime;
+
+    /**
+     * \brief Preference associated with default router.
+     * 0 = low
+     * 1 = medium
+     * 2 = high
+     */
+    uint8_t m_defaultPreference;
+
+    /**
+     * \brief Flag to add link-layer address in RA.
+     */
+    bool m_sourceLLAddress;
+
+    /**
+     * \brief Flag to add HA (home agent) flag in RA.
+     */
+    bool m_homeAgentFlag;
+
+    /**
+     * \brief Flag to add Home Agent Information option (Mobile IPv6).
+     * Currently not implemented.
+     */
+    bool m_homeAgentInfo;
+
+    /**
+     * \brief Home agent lifetime in seconds. Ignored if home agent info is not set.
+     */
+    uint32_t m_homeAgentLifeTime;
+
+    /**
+     * \brief Home agent preference. Ignored if home agent info is not set.
+     */
+    uint32_t m_homeAgentPreference;
+
+    /**
+     * \brief Flag for HA to signals it supports Mobile Router registrations (NEMO Basic).
+     */
+    bool m_mobRtrSupportFlag;
+
+    /**
+     * \brief Flag to add Advertisement Interval option in RA.
+     */
+    bool m_intervalOpt;
+};
+
+} /* namespace ns3 */
+
+#endif /* RADVD_INTERFACE_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd-prefix.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,112 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "radvd-prefix.h"
+
+namespace ns3
+{
+
+RadvdPrefix::RadvdPrefix (Ipv6Address network, uint8_t prefixLength, uint32_t preferredLifeTime, uint32_t validLifeTime, bool onLinkFlag, bool autonomousFlag, bool routerAddrFlag)
+  : m_network (network),
+  m_prefixLength (prefixLength),
+  m_preferredLifeTime (preferredLifeTime),
+  m_validLifeTime (validLifeTime),
+  m_onLinkFlag (onLinkFlag),
+  m_autonomousFlag (autonomousFlag),
+  m_routerAddrFlag (routerAddrFlag)
+{
+}
+
+RadvdPrefix::~RadvdPrefix ()
+{
+}
+
+Ipv6Address RadvdPrefix::GetNetwork () const
+{
+  return m_network;
+}
+
+void RadvdPrefix::SetNetwork (Ipv6Address network)
+{
+  m_network = network;
+}
+
+uint8_t RadvdPrefix::GetPrefixLength () const
+{
+  return m_prefixLength;
+}
+
+void RadvdPrefix::SetPrefixLength (uint8_t prefixLength)
+{
+  m_prefixLength = prefixLength;
+}
+
+uint32_t RadvdPrefix::GetValidLifeTime () const
+{
+  return m_validLifeTime;
+}
+
+void RadvdPrefix::SetValidLifeTime (uint32_t validLifeTime)
+{
+  m_validLifeTime = validLifeTime;
+}
+
+uint32_t RadvdPrefix::GetPreferredLifeTime () const
+{
+  return m_preferredLifeTime;
+}
+
+void RadvdPrefix::SetPreferredLifeTime (uint32_t preferredLifeTime)
+{
+  m_preferredLifeTime = preferredLifeTime;
+}
+
+bool RadvdPrefix::IsOnLinkFlag () const
+{
+  return m_onLinkFlag;
+}
+
+void RadvdPrefix::SetOnLinkFlag (bool onLinkFlag)
+{
+  m_onLinkFlag = onLinkFlag;
+}
+
+bool RadvdPrefix::IsAutonomousFlag () const
+{
+  return m_autonomousFlag; 
+}
+
+void RadvdPrefix::SetAutonomousFlag (bool autonomousFlag)
+{
+  m_autonomousFlag = autonomousFlag;
+}
+
+bool RadvdPrefix::IsRouterAddrFlag () const
+{
+  return m_routerAddrFlag;
+}
+
+void RadvdPrefix::SetRouterAddrFlag (bool routerAddrFlag)
+{
+  m_routerAddrFlag = routerAddrFlag;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd-prefix.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,180 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef RADVD_PREFIX_H
+#define RADVD_PREFIX_H 
+
+#include <stdint.h>
+
+#include "ns3/ipv6-address.h"
+
+namespace ns3
+{
+
+/**
+ * \class RadvdPrefix
+ * \brief Router prefix for radvd application.
+ */
+class RadvdPrefix : public RefCountBase
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param network network prefix advertised
+     * \param prefixLength prefix length ( 0 < x <= 128)
+     * \param preferredLifeTime preferred life time in seconds (default 7 days)
+     * \param validLifeTime valid life time in seconds (default 30 days)
+     * \param onLinkFlag on link flag
+     * \param autonomousFlag autonomous link flag
+     * \param routerAddrFlag router address flag (for Mobile IPv6)
+     */
+    RadvdPrefix (Ipv6Address network, uint8_t prefixLength, uint32_t preferredLifeTime = 604800, uint32_t validLifeTime = 2592000, bool onLinkFlag = true, bool autonomousFlag = true, bool routerAddrFlag = false);
+
+    /**
+     * \brief Destructor.
+     */
+    ~RadvdPrefix ();
+
+    /**
+     * \brief Get network prefix.
+     * \return network prefix
+     */
+    Ipv6Address GetNetwork () const;
+
+    /**
+     * \brief Set network prefix.
+     * \param network network prefix
+     */
+    void SetNetwork (Ipv6Address network);
+
+    /**
+     * \brief Get prefix length.
+     * \return prefix length
+     */
+    uint8_t GetPrefixLength () const;
+
+    /**
+     * \brief Set prefix length.
+     * \param prefixLength prefix length
+     */
+    void SetPrefixLength (uint8_t prefixLength);
+
+    /**
+     * \brief Get preferred lifetime.
+     * \return lifetime
+     */
+    uint32_t GetPreferredLifeTime () const;
+
+    /**
+     * \brief Set preferred lifetime.
+     * \param preferredLifeTime lifetime
+     */
+    void SetPreferredLifeTime (uint32_t preferredLifeTime);
+
+    /**
+     * \brief Get valid lifetime.
+     * \return lifetime
+     */
+    uint32_t GetValidLifeTime () const;
+
+    /**
+     * \brief Set valid lifetime.
+     * \param validLifeTime lifetime
+     */
+    void SetValidLifeTime (uint32_t validLifeTime);
+
+    /**
+     * \brief Is on-link flag ?
+     * \return true if on-link is activated, false otherwise
+     */
+    bool IsOnLinkFlag () const;
+
+    /**
+     * \brief Set on-link flag.
+     * \param onLinkFlag value
+     */
+    void SetOnLinkFlag (bool onLinkFlag);
+
+    /**
+     * \brief Is autonomous flag ?
+     * \return true if autonomous is activated, false otherwise
+     */
+    bool IsAutonomousFlag () const;
+
+    /**
+     * \brief Set autonomous flag.
+     * \param autonomousFlag value
+     */
+    void SetAutonomousFlag (bool autonomousFlag);
+
+    /**
+     * \brief Is router address flag ?
+     * \return true if router address is activated, false otherwise
+     */
+    bool IsRouterAddrFlag () const;
+
+    /**
+     * \brief Set router address flag.
+     * \param routerAddrFlag value
+     */
+    void SetRouterAddrFlag (bool routerAddrFlag);
+
+  private:
+    /**
+     * \brief Network prefix.
+     */
+    Ipv6Address m_network;
+
+    /**
+     * \brief Prefix length.
+     */
+    uint8_t m_prefixLength;
+
+    /**
+     * \brief Preferred time.
+     */
+    uint32_t m_preferredLifeTime;
+
+    /**
+     * \brief Valid time.
+     */
+    uint32_t m_validLifeTime;
+
+    /**
+     * \brief On link flag, indicates that this prefix can be used for on-link determination.
+     */
+    bool m_onLinkFlag;
+
+    /**
+     * \brief Autonomous flag, it is used for autonomous address configuration (RFC 2462).
+     */
+    bool m_autonomousFlag;
+
+    /**
+     * \brief Router address flag, indicates that router address is sent instead 
+     * of network prefix as is required by Mobile IPv6.
+     */
+    bool m_routerAddrFlag;
+};
+
+} /* namespace ns3 */
+
+#endif /* RADVD_PREFIX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,273 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Telecom Bretagne
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#include "ns3/log.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/nstime.h"
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/net-device.h"
+#include "ns3/uinteger.h"
+#include "ns3/random-variable.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-raw-socket-factory.h"
+#include "ns3/ipv6-header.h"
+#include "ns3/icmpv6-header.h"
+
+#include "radvd.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("RadvdApplication");
+
+NS_OBJECT_ENSURE_REGISTERED (Radvd);
+
+TypeId Radvd::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Radvd")
+    .SetParent<Application> ()
+    .AddConstructor<Radvd> ()
+  ;
+  return tid;
+}
+ 
+Radvd::Radvd ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Radvd::~Radvd ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (RadvdInterfaceListI it = m_configurations.begin () ; it != m_configurations.end () ; ++it)
+  {
+    *it = 0;
+  }
+  m_configurations.clear ();
+  m_socket = 0;
+}
+
+void Radvd::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Application::DoDispose ();
+}
+
+void Radvd::StartApplication ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (!m_socket)
+  {
+    TypeId tid = TypeId::LookupByName ("ns3::Ipv6RawSocketFactory");
+    m_socket = Socket::CreateSocket (GetNode (), tid);
+
+    NS_ASSERT (m_socket);
+
+/*    m_socket->Bind (Inet6SocketAddress (m_localAddress, 0)); */
+/*    m_socket->Connect (Inet6SocketAddress (Ipv6Address::GetAllNodesMulticast (), 0)); */
+    m_socket->SetAttribute ("Protocol", UintegerValue (58)); /* ICMPv6 */
+    m_socket->SetRecvCallback (MakeCallback (&Radvd::HandleRead, this));
+  }
+
+  for (RadvdInterfaceListCI it = m_configurations.begin () ; it != m_configurations.end () ; it++)
+  {
+    m_eventIds[(*it)->GetInterface ()] = EventId ();
+    ScheduleTransmit (Seconds (0.), (*it), m_eventIds[(*it)->GetInterface ()]);
+  }
+}
+
+void Radvd::StopApplication ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_socket)
+  {
+    m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
+  }
+
+  for (EventIdMapI it = m_eventIds.begin () ; it != m_eventIds.end () ; ++it)
+  {
+    Simulator::Cancel ((*it).second);
+  }
+  m_eventIds.clear ();
+}
+
+void Radvd::AddConfiguration (Ptr<RadvdInterface> routerInterface)
+{
+  m_configurations.push_back (routerInterface);
+}
+
+void Radvd::ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId)
+{
+  NS_LOG_FUNCTION (this << dt);
+  eventId = Simulator::Schedule (dt, &Radvd::Send, this, config, Ipv6Address::GetAllNodesMulticast ());
+}
+
+void Radvd::Send (Ptr<RadvdInterface> config, Ipv6Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+  NS_ASSERT (m_eventIds[config->GetInterface ()].IsExpired ());
+  Icmpv6RA raHdr;
+  Icmpv6OptionLinkLayerAddress llaHdr;
+  Icmpv6OptionMtu mtuHdr;
+  Icmpv6OptionPrefixInformation prefixHdr;
+
+  if (m_eventIds.size () == 0)
+  {
+    return;
+  }
+
+  std::list<Ptr<RadvdPrefix> > prefixes = config->GetPrefixes ();
+  Ptr<Packet> p = Create<Packet> ();
+  Ptr<Ipv6> ipv6 = GetNode ()->GetObject<Ipv6> ();
+
+  /* set RA header information */
+  raHdr.SetFlagM (config->IsManagedFlag ());
+  raHdr.SetFlagO (config->IsOtherConfigFlag ());
+  raHdr.SetFlagH (config->IsHomeAgentFlag ());
+  raHdr.SetCurHopLimit (config->GetCurHopLimit ());
+  raHdr.SetLifeTime (config->GetDefaultLifeTime ());
+  raHdr.SetReachableTime (config->GetReachableTime ());
+  raHdr.SetRetransmissionTime (config->GetRetransTimer ());
+    
+  if (config->IsSourceLLAddress ())
+  {
+    /* Get L2 address from NetDevice */
+    Address addr = ipv6->GetNetDevice (config->GetInterface ())->GetAddress ();
+    llaHdr = Icmpv6OptionLinkLayerAddress (true, addr);
+    p->AddHeader (llaHdr);
+  }
+
+  if (config->GetLinkMtu ())
+  {
+    NS_ASSERT (config->GetLinkMtu () >= 1280);
+    mtuHdr = Icmpv6OptionMtu (config->GetLinkMtu ());
+    p->AddHeader (mtuHdr);
+  }
+
+  /* add list of prefixes */
+  for (std::list<Ptr<RadvdPrefix> >::const_iterator jt = prefixes.begin () ; jt != prefixes.end () ; jt++)
+  {
+    uint8_t flags = 0;
+    prefixHdr = Icmpv6OptionPrefixInformation ();
+    prefixHdr.SetPrefix ((*jt)->GetNetwork ());
+    prefixHdr.SetPrefixLength ((*jt)->GetPrefixLength ());
+    prefixHdr.SetValidTime ((*jt)->GetValidLifeTime ());
+    prefixHdr.SetPreferredTime ((*jt)->GetPreferredLifeTime ());
+
+    if ((*jt)->IsOnLinkFlag ())
+    {
+       flags += 1 << 7;
+    }
+    
+    if ((*jt)->IsAutonomousFlag ())
+    {
+      flags += 1 << 6;
+    }
+
+    if ((*jt)->IsRouterAddrFlag ())
+    {
+      flags += 1 << 5;
+    }
+
+    prefixHdr.SetFlags (flags);
+
+    p->AddHeader (prefixHdr);
+  }
+
+  Ipv6Address src = ipv6->GetAddress (config->GetInterface (), 0).GetAddress ();
+  m_socket->Bind (Inet6SocketAddress (src, 0));
+  m_socket->Connect (Inet6SocketAddress (dst, 0));
+
+  /* as we know interface index that will be used to send RA and 
+   * we always send RA with router's link-local address, we can 
+   * calculate checksum here.
+   */
+  raHdr.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + raHdr.GetSerializedSize (), 58 /* ICMPv6 */);
+  p->AddHeader (raHdr);
+
+  /* send RA */
+  NS_LOG_LOGIC ("Send RA");
+  m_socket->Send (p, 0);
+
+  UniformVariable rnd;
+  uint64_t delay = static_cast<uint64_t> (rnd.GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5);
+  Time t = MilliSeconds (delay);
+  ScheduleTransmit (t, config, m_eventIds[config->GetInterface ()]);
+}
+
+void Radvd::HandleRead (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+  Ptr<Packet> packet = 0;
+  Address from;
+
+  while (packet = socket->RecvFrom (from))
+  {
+    if (Inet6SocketAddress::IsMatchingType (from))
+    {
+      Ipv6Header hdr;
+      Icmpv6RS rsHdr;
+      Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from);
+      uint64_t delay = 0;
+      UniformVariable rnd;
+      Time t;
+
+      packet->RemoveHeader (hdr);
+
+      switch (*packet->PeekData ())
+      {
+        case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION:
+          /* send RA in response of a RS */
+          packet->RemoveHeader (rsHdr);
+          NS_LOG_INFO ("Received ICMPv6 Router Solicitation from " << hdr.GetSourceAddress () << " code = " << (uint32_t)rsHdr.GetCode ());
+
+          delay = static_cast<uint64_t> (rnd.GetValue (0, MAX_RA_DELAY_TIME) + 0.5); 
+          t = Simulator::Now () + MilliSeconds (delay);
+
+#if 0
+          NS_LOG_INFO ("schedule new RA : " << t.GetTimeStep () << " next scheduled RA" << (int64_t)m_sendEvent.GetTs ());
+
+          if (t.GetTimeStep () < static_cast<int64_t> (m_sendEvent.GetTs ()))
+          {
+            /* send multicast RA */
+            /* maybe replace this by a unicast RA (it is a SHOULD in the RFC) */
+            NS_LOG_INFO ("Respond to RS");
+            /* XXX advertise just the prefix for the interface not all */
+            t = MilliSeconds (delay);
+            /* XXX schedule packet send */
+            /* ScheduleTransmit (t); */
+          }
+#endif
+          break;
+        default:
+          break;
+      }
+    }
+  }
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/radvd.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,135 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 Telecom Bretagne
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#ifndef RADVD_H
+#define RADVD_H
+
+#include <map>
+
+#include "ns3/application.h"
+#include "ns3/socket.h"
+
+#include "radvd-interface.h"
+
+namespace ns3
+{
+
+/**
+ * \class Radvd
+ * \brief Router advertisement daemon.
+ */
+class Radvd : public Application
+{
+  public:
+     /**
+      * \brief Get the type ID.
+      * \return type ID
+      */
+     static TypeId GetTypeId (void);
+
+     /**
+      * \brief Constructor.
+      */
+     Radvd ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Radvd ();
+
+    /**
+     * \brief Default value for maximum delay of RA (ms)
+     */
+    static const uint32_t MAX_RA_DELAY_TIME = 500;
+
+    /**
+     * \brief Add configuration for an interface;
+     * \param routerInterface configuration
+     */
+    void AddConfiguration (Ptr<RadvdInterface> routerInterface);
+
+  protected:
+    /**
+     * \brief Dispose the instance.
+     */
+    virtual void DoDispose ();
+  
+  private:
+    typedef std::list<Ptr<RadvdInterface> > RadvdInterfaceList;
+    typedef std::list<Ptr<RadvdInterface> >::iterator RadvdInterfaceListI;
+    typedef std::list<Ptr<RadvdInterface> >::const_iterator RadvdInterfaceListCI;
+
+    typedef std::map<uint32_t, EventId> EventIdMap;
+    typedef std::map<uint32_t, EventId>::iterator EventIdMapI;
+    typedef std::map<uint32_t, EventId>::const_iterator EventIdMapCI;
+
+    /**
+     * \brief Start the application.
+     */
+    virtual void StartApplication ();
+
+    /**
+     * \brief Stop the application.
+     */
+    virtual void StopApplication ();
+
+    /**
+     * \brief Schedule sending a packet.
+     * \param dt interval between packet
+     * \param config interface configuration
+     * \param eventId event ID associated
+     */
+    void ScheduleTransmit (Time dt, Ptr<RadvdInterface> config, EventId& eventId);
+
+    /**
+     * \brief Send a packet.
+     * \param config interface configuration
+     * \param dst destination address (default ff02::1)
+     */
+    void Send (Ptr<RadvdInterface> config, Ipv6Address dst = Ipv6Address::GetAllNodesMulticast ());
+
+    /**
+     * \brief Handle received packet, especially router solicitation
+     * \param socket socket to read data from
+     */
+    void HandleRead (Ptr<Socket> socket);
+
+    /**
+     * \brief Raw socket to send RA.
+     */
+    Ptr<Socket> m_socket;
+
+    /**
+     * \brief List of configuration for interface.
+     */
+    RadvdInterfaceList m_configurations;
+
+    /**
+     * \brief Event ID map.
+     */
+    EventIdMap m_eventIds;
+};
+
+} /* namespace ns3 */
+
+#endif /* RADVD_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/radvd/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,17 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('radvd', ['internet-stack'])
+    module.source = [
+        'radvd.cc',
+        'radvd-interface.cc',
+        'radvd-prefix.cc',
+        ]
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'radvd'
+    headers.source = [
+        'radvd.h',
+        'radvd-interface.h',
+        'radvd-prefix.h',
+        ]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/sgi-hashmap.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,38 @@
+/* This code snippet was ripped out of the gcc 
+ * documentation and slightly modified to work
+ * with gcc 4.x
+ */
+#ifndef SGI_HASHMAP_H
+#define SGI_HASHMAP_H
+
+/* To use gcc extensions.
+ */
+#ifdef __GNUC__
+  #if __GNUC__ < 3
+     #include <hash_map.h>
+namespace sgi { using ::hash_map; }; // inherit globals
+  #else 
+     #if __GNUC__ < 4
+       #include <ext/hash_map>
+       #if __GNUC_MINOR__ == 0
+namespace sgi = std;         // GCC 3.0
+       #else
+namespace sgi = ::__gnu_cxx;       // GCC 3.1 and later
+       #endif
+     #else  // gcc 4.x and later
+       #if __GNUC_MINOR__ < 3
+       #include <ext/hash_map>
+namespace sgi = ::__gnu_cxx;
+       #else
+#undef __DEPRECATED
+       #include <backward/hash_map>
+namespace sgi = ::__gnu_cxx;
+       #endif
+     #endif
+  #endif
+#else      // ...  there are other compilers, right?
+namespace sgi = std;
+#endif
+
+
+#endif /* SGI_HASHMAP_H */
--- a/src/common/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/common/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -37,4 +37,5 @@
         'tag-buffer.h',
         'packet-tag-list.h',
         'ascii-writer.h',
+        'sgi-hashmap.h',
         ]
--- a/src/core/random-variable.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/core/random-variable.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -778,23 +778,19 @@
   double m_bound;     // Bound on value's difference from the mean (absolute value)
   bool   m_nextValid; // True if next valid
   double m_next;      // The algorithm produces two values at a time
-  static bool   m_static_nextValid;
-  static double m_static_next;
 };
 
-bool         NormalVariableImpl::m_static_nextValid = false;
-double       NormalVariableImpl::m_static_next;
 const double NormalVariableImpl::INFINITE_VALUE = 1e307;
 
 NormalVariableImpl::NormalVariableImpl() 
   : m_mean(0.0), m_variance(1.0), m_bound(INFINITE_VALUE), m_nextValid(false){}
 
-NormalVariableImpl::NormalVariableImpl(double m, double v, double b/*=INFINITE_VALUE*/)
+NormalVariableImpl::NormalVariableImpl(double m, double v, double b)
   : m_mean(m), m_variance(v), m_bound(b), m_nextValid(false) { }
 
 NormalVariableImpl::NormalVariableImpl(const NormalVariableImpl& c)
   : RandomVariableBase(c), m_mean(c.m_mean), m_variance(c.m_variance),
-    m_bound(c.m_bound) { }
+    m_bound(c.m_bound), m_nextValid(false) { }
 
 double NormalVariableImpl::GetValue()
 {
--- a/src/devices/wifi/wifi-mac-header.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/devices/wifi/wifi-mac-header.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -896,9 +896,9 @@
 void 
 WifiMacHeader::PrintFrameControl (std::ostream &os) const
 {
-  os << "ToDS=" << m_ctrlToDs << ", FromDS=" << m_ctrlFromDs 
-     << ", MoreFrag=" << m_ctrlMoreFrag << ", Retry=" << m_ctrlRetry 
-     << ", MoreData=" << m_ctrlMoreData 
+  os << "ToDS=" << std::hex << (int) m_ctrlToDs << ", FromDS=" << std::hex << (int) m_ctrlFromDs 
+     << ", MoreFrag=" <<  std::hex << (int) m_ctrlMoreFrag << ", Retry=" << std::hex << (int) m_ctrlRetry 
+     << ", MoreData=" <<  std::hex << (int) m_ctrlMoreData << std::dec 
     ;
 }
 
@@ -935,7 +935,7 @@
       PrintFrameControl (os);
       os << " Duration/ID=" << m_duration << "us"
          << ", DA=" << m_addr1 << ", SA=" << m_addr2
-         << ", BSSID=" << m_addr3 << ", FragNumber=" << m_seqFrag
+         << ", BSSID=" << m_addr3 << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec
          << ", SeqNumber=" << m_seqSeq;
       break;
     case WIFI_MAC_MGT_ACTION:
@@ -943,11 +943,11 @@
       PrintFrameControl (os);
       os << " Duration/ID=" << m_duration << "us"
          << "DA=" << m_addr1 << ", SA=" << m_addr2 << ", BSSID=" << m_addr3
-         << ", FragNumber=" << m_seqFrag << ", SeqNumber=" << m_seqSeq;
+         << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec << ", SeqNumber=" << m_seqSeq;
     case WIFI_MAC_MGT_MULTIHOP_ACTION:
       os << " Duration/ID=" << m_duration << "us"
          << "RA=" << m_addr1 << ", TA=" << m_addr2 << ", DA=" << m_addr3
-         << ", FragNumber=" << m_seqFrag << ", SeqNumber=" << m_seqSeq;
+         << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec << ", SeqNumber=" << m_seqSeq;
     case WIFI_MAC_DATA:
       PrintFrameControl (os);
       os << " Duration/ID=" << m_duration << "us";
@@ -971,7 +971,7 @@
         {
           NS_FATAL_ERROR ("Impossible ToDs and FromDs flags combination");
         }
-      os << ", FragNumber=" << m_seqFrag
+      os << ", FragNumber=" << std::hex << (int) m_seqFrag << std::dec
          << ", SeqNumber=" << m_seqSeq;
       break;
     case WIFI_MAC_DATA_CFACK:
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -159,6 +159,18 @@
                    WifiModeValue (),
                    MakeWifiModeAccessor (&WifiRemoteStationManager::m_nonUnicastMode),
                    MakeWifiModeChecker ())
+    .AddTraceSource ("MacTxRtsFailed", 
+                     "The transmission of a RTS by the MAC layer has failed",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxRtsFailed))
+    .AddTraceSource ("MacTxDataFailed", 
+                     "The transmission of a data packet by the MAC layer has failed",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxDataFailed))
+    .AddTraceSource ("MacTxFinalRtsFailed", 
+                     "The transmission of a RTS has exceeded the maximum number of attempts",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalRtsFailed))
+    .AddTraceSource ("MacTxFinalDataFailed", 
+                     "The transmission of a data packet has exceeded the maximum number of attempts",
+                     MakeTraceSourceAccessor (&WifiRemoteStationManager::m_macTxFinalDataFailed))
     ;
   return tid;
 }
@@ -175,7 +187,7 @@
 {
   for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
     {
-      delete (*i).second;
+      delete (*i);
     }
   m_stations.clear ();
   delete m_nonUnicast;
@@ -237,14 +249,15 @@
     }
   for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++) 
     {
-      if ((*i).first == address)
+      if ((*i)->GetAddress () == address)
         {
-          return (*i).second;
+          return (*i);
         }
     }
   WifiRemoteStation *station = CreateStation ();
+  station->SetAddress(address);
   station->Reset ();
-  m_stations.push_back (std::make_pair (address, station));
+  m_stations.push_back (station);
   return station;
 }
 
@@ -264,7 +277,7 @@
 {
   for (Stations::const_iterator i = m_stations.begin (); i != m_stations.end (); i++)
     {
-      delete i->second;
+      delete (*i);
     }
   m_stations.clear ();
   m_basicModes.clear ();
@@ -318,6 +331,33 @@
     return m_nonUnicastMode;
 }
 
+
+void 
+WifiRemoteStationManager::NotifyTxRtsFailed (Mac48Address address)
+{
+  m_macTxRtsFailed (address);
+}
+
+void 
+WifiRemoteStationManager::NotifyTxDataFailed (Mac48Address address)
+{
+  m_macTxDataFailed (address);
+}
+
+void 
+WifiRemoteStationManager::NotifyTxFinalRtsFailed (Mac48Address address)
+{
+  m_macTxFinalRtsFailed (address);
+}
+
+void 
+WifiRemoteStationManager::NotifyTxFinalDataFailed (Mac48Address address)
+{
+  m_macTxFinalDataFailed (address);
+}
+
+
+
 } // namespace ns3
 
 /***************************************************************
@@ -564,6 +604,16 @@
 {
   return m_avgSlrc;
 }
+void 
+WifiRemoteStation::SetAddress(Mac48Address address)
+{
+  m_address = address;
+}  
+Mac48Address 
+WifiRemoteStation::GetAddress()
+{
+  return m_address;
+}
 uint32_t 
 WifiRemoteStation::GetNSupportedModes (void) const
 {
@@ -698,6 +748,7 @@
 WifiRemoteStation::ReportRtsFailed (void)
 {
   m_ssrc++;
+  GetManager ()->NotifyTxRtsFailed (m_address);
   DoReportRtsFailed ();
 }
 
@@ -705,6 +756,7 @@
 WifiRemoteStation::ReportDataFailed (void)
 {
   m_slrc++;
+  GetManager ()->NotifyTxDataFailed (m_address);
   DoReportDataFailed ();
 }
 
@@ -727,6 +779,7 @@
 WifiRemoteStation::ReportFinalRtsFailed (void)
 {
   m_ssrc = 0;
+  GetManager ()->NotifyTxFinalRtsFailed (m_address);
   DoReportFinalRtsFailed ();
 }
 
@@ -734,6 +787,7 @@
 WifiRemoteStation::ReportFinalDataFailed (void)
 {
   m_slrc = 0;
+  GetManager ()->NotifyTxFinalDataFailed (m_address);
   DoReportFinalDataFailed ();
 }
 
--- a/src/devices/wifi/wifi-remote-station-manager.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Wed Aug 26 15:29:03 2009 +0400
@@ -88,7 +88,7 @@
   friend class WifiRemoteStation;
   virtual void DoDispose (void);
 private:
-  typedef std::vector <std::pair<Mac48Address, WifiRemoteStation *> > Stations;
+  typedef std::vector <WifiRemoteStation *> Stations;
   virtual class WifiRemoteStation *CreateStation (void) = 0;
   Stations m_stations;
   WifiMode m_defaultTxMode;
@@ -100,6 +100,63 @@
   uint32_t m_rtsCtsThreshold;
   uint32_t m_fragmentationThreshold;
   WifiMode m_nonUnicastMode;
+
+
+  /**
+   * Public method used to fire a MacTxRtsFailed trace.
+   * Implemented for encapsulation purposes.
+   */
+  void NotifyTxRtsFailed (Mac48Address address);  
+
+  /**
+   * Public method used to fire a MacTxDataFailed trace.
+   * Implemented for encapsulation purposes. 
+   */
+  void NotifyTxDataFailed (Mac48Address address);  
+
+  /**
+   * Public method used to fire a MacTxFinalRtsFailed trace.
+   * Implemented for encapsulation purposes.
+   */
+  void NotifyTxFinalRtsFailed (Mac48Address address);  
+
+  /**
+   * Public method used to fire a MacTxFinalDataFailed trace.
+   * Implemented for encapsulation purposes. 
+   */
+  void NotifyTxFinalDataFailed (Mac48Address address);    
+
+
+  /**
+   * The trace source fired when the transmission of a RTS has failed
+   *
+   * \see class CallBackTraceSource
+   */
+  TracedCallback<Mac48Address> m_macTxRtsFailed;
+
+  /**
+   * The trace source fired when the transmission of a data packet has failed 
+   *
+   * \see class CallBackTraceSource
+   */
+  TracedCallback<Mac48Address> m_macTxDataFailed;
+
+  /**
+   * The trace source fired when the transmission of a RTS has
+   * exceeded the maximum number of attempts
+   *
+   * \see class CallBackTraceSource
+   */
+  TracedCallback<Mac48Address> m_macTxFinalRtsFailed;
+
+  /**
+   * The trace source fired when the transmission of a data packet has
+   * exceeded the maximum number of attempts
+   *
+   * \see class CallBackTraceSource
+   */
+  TracedCallback<Mac48Address> m_macTxFinalDataFailed;
+
 };
 
 } // namespace ns3
@@ -264,6 +321,18 @@
    * \return exponentially weighted average SLRC, this is used by Airtime link metric of 802.11s
    */
   double GetAvgSlrc () const;
+  /** 
+   * set the address of the remote stationt represented by this instance of WifiRemoteStation
+   * 
+   * @param address the MAC address of the remote station
+   */
+  void SetAddress(Mac48Address address);
+  /** 
+   * get the address of the remote stationt represented by this instance of WifiRemoteStation
+   * 
+   * @return the MAC address of the remote station
+   */
+  Mac48Address GetAddress();
 private:
   virtual Ptr<WifiRemoteStationManager> GetManager (void) const = 0;
   virtual WifiMode DoGetDataMode (uint32_t size) = 0;
@@ -294,6 +363,7 @@
   TracedValue<uint32_t> m_slrc;
   double m_avgSlrcCoefficient;
   double m_avgSlrc;
+  Mac48Address m_address;
 };
 
 } // namespace ns3 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/athstats-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,309 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/abort.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/config.h"
+#include "athstats-helper.h"
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+
+
+NS_LOG_COMPONENT_DEFINE("Athstats");
+
+namespace ns3 {
+
+
+AthstatsHelper::AthstatsHelper ()
+  : m_interval (Seconds (1.0))
+{
+}
+
+void
+AthstatsHelper::EnableAthstats (std::string filename,  uint32_t nodeid, uint32_t deviceid)
+{
+   Ptr<AthstatsWifiTraceSink> athstats = CreateObject<AthstatsWifiTraceSink> ();
+  std::ostringstream oss;
+  oss << filename
+      << "_" << std::setfill ('0') << std::setw (3) << std::right <<  nodeid 
+      << "_" << std::setfill ('0') << std::setw (3) << std::right << deviceid;
+  athstats->Open (oss.str ());
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid;
+  std::string devicepath = oss.str ();
+
+  Config::Connect (devicepath + "/Mac/MacTx", MakeCallback (&AthstatsWifiTraceSink::DevTxTrace, athstats));
+  Config::Connect (devicepath + "/Mac/MacRx", MakeCallback (&AthstatsWifiTraceSink::DevRxTrace, athstats));
+
+  Config::Connect (devicepath + "/RemoteStationManager/TxRtsFailed", MakeCallback (&AthstatsWifiTraceSink::TxRtsFailedTrace, athstats));
+  Config::Connect (devicepath + "/RemoteStationManager/MacTxDataFailed", MakeCallback (&AthstatsWifiTraceSink::TxDataFailedTrace, athstats));
+  Config::Connect (devicepath + "/RemoteStationManager/MacTxFinalRtsFailed", MakeCallback (&AthstatsWifiTraceSink::TxFinalRtsFailedTrace, athstats));
+  Config::Connect (devicepath + "/RemoteStationManager/MacTxFinalDataFailed", MakeCallback (&AthstatsWifiTraceSink::TxFinalDataFailedTrace, athstats));
+
+  Config::Connect (devicepath + "/Phy/State/RxOk", MakeCallback (&AthstatsWifiTraceSink::PhyRxOkTrace, athstats));
+  Config::Connect (devicepath + "/Phy/State/RxError", MakeCallback (&AthstatsWifiTraceSink::PhyRxErrorTrace, athstats));
+  Config::Connect (devicepath + "/Phy/State/Tx", MakeCallback (&AthstatsWifiTraceSink::PhyTxTrace, athstats));
+  Config::Connect (devicepath + "/Phy/State/State", MakeCallback (&AthstatsWifiTraceSink::PhyStateTrace, athstats));
+}
+
+void
+AthstatsHelper::EnableAthstats (std::string filename, Ptr<NetDevice> nd)
+{
+  EnableAthstats (filename, nd->GetNode ()->GetId (), nd->GetIfIndex ());
+}
+
+
+void 
+AthstatsHelper::EnableAthstats (std::string filename, NetDeviceContainer d)
+{
+  for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i)
+    {
+      Ptr<NetDevice> dev = *i;
+      EnableAthstats (filename, dev->GetNode ()->GetId (), dev->GetIfIndex ());
+    }
+}
+
+
+void
+AthstatsHelper::EnableAthstats (std::string filename, NodeContainer n)
+{
+  NetDeviceContainer devs;
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      for (uint32_t j = 0; j < node->GetNDevices (); ++j)
+        {
+          devs.Add (node->GetDevice (j));
+        }
+    }
+  EnableAthstats (filename, devs);
+}
+
+
+
+
+
+NS_OBJECT_ENSURE_REGISTERED (AthstatsWifiTraceSink);
+
+TypeId 
+AthstatsWifiTraceSink::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::AthstatsWifiTraceSink")
+    .SetParent<Object> ()
+    .AddConstructor<AthstatsWifiTraceSink> ()
+    .AddAttribute ("Interval",
+                   "Time interval between reports",
+                   TimeValue (Seconds(1.0)),
+                   MakeTimeAccessor (&AthstatsWifiTraceSink::m_interval),
+                   MakeTimeChecker ())
+    ;
+  return tid;
+}
+
+AthstatsWifiTraceSink::AthstatsWifiTraceSink ()
+  :   m_txCount (0),
+      m_rxCount (0),
+      m_shortRetryCount (0),
+      m_longRetryCount (0),
+      m_exceededRetryCount (0),
+      m_phyRxOkCount (0),
+      m_phyRxErrorCount (0),
+      m_phyTxCount (0),
+      m_writer (0)
+{
+  Simulator::ScheduleNow (&AthstatsWifiTraceSink::WriteStats, this);
+}
+
+AthstatsWifiTraceSink::~AthstatsWifiTraceSink ()
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_writer != 0)
+    {
+      NS_LOG_LOGIC ("m_writer nonzero " << m_writer);
+      if (m_writer->is_open ())
+        {
+          NS_LOG_LOGIC ("m_writer open.  Closing " << m_writer);
+          m_writer->close ();
+        }
+
+      NS_LOG_LOGIC ("Deleting writer " << m_writer);
+      delete m_writer;
+
+      NS_LOG_LOGIC ("m_writer = 0");
+      m_writer = 0;
+    }
+  else
+    {
+      NS_LOG_LOGIC ("m_writer == 0");
+    }
+}
+
+void    
+AthstatsWifiTraceSink::ResetCounters ()
+{
+  m_txCount = 0;
+  m_rxCount = 0;
+  m_shortRetryCount = 0;
+  m_longRetryCount = 0;
+  m_exceededRetryCount = 0;
+  m_phyRxOkCount = 0;
+  m_phyRxErrorCount = 0;
+  m_phyTxCount = 0;
+}
+
+void
+AthstatsWifiTraceSink::DevTxTrace (std::string context, Ptr<const Packet> p)
+{
+  NS_LOG_FUNCTION (this << context <<p);
+  ++m_txCount;
+}
+
+void
+AthstatsWifiTraceSink::DevRxTrace (std::string context, Ptr<const Packet> p)
+{
+  NS_LOG_FUNCTION (this << context <<p);
+  ++m_rxCount;
+}
+
+
+void
+AthstatsWifiTraceSink::TxRtsFailedTrace (std::string context, Mac48Address address)
+{
+  NS_LOG_FUNCTION (this << context << address);
+  ++m_shortRetryCount;
+}
+
+void
+AthstatsWifiTraceSink::TxDataFailedTrace (std::string context, Mac48Address address)
+{
+  NS_LOG_FUNCTION (this << context << address);
+  ++m_longRetryCount;
+}
+
+void
+AthstatsWifiTraceSink::TxFinalRtsFailedTrace (std::string context, Mac48Address address)
+{
+  NS_LOG_FUNCTION (this << context << address);
+  ++m_exceededRetryCount;
+}
+
+void
+AthstatsWifiTraceSink::TxFinalDataFailedTrace (std::string context, Mac48Address address)
+{
+  NS_LOG_FUNCTION (this << context << address);
+  ++m_exceededRetryCount;
+}
+
+
+
+void
+AthstatsWifiTraceSink::PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble)
+{
+  NS_LOG_FUNCTION (this << context <<packet<< " mode=" << mode << " snr=" << snr );
+  ++m_phyRxOkCount;
+}
+
+void
+AthstatsWifiTraceSink::PhyRxErrorTrace (std::string context, Ptr<const Packet> packet, double snr)
+{
+  NS_LOG_FUNCTION (this << context <<packet <<" snr=" << snr );
+  ++m_phyRxErrorCount;
+}
+
+void
+AthstatsWifiTraceSink::PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower)
+{
+  NS_LOG_FUNCTION (this << context << packet << "PHYTX mode=" << mode );
+  ++m_phyTxCount;
+}
+
+
+void
+AthstatsWifiTraceSink::PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state)
+{
+  NS_LOG_FUNCTION (this << context << start << duration << state);
+
+}
+
+
+
+void
+AthstatsWifiTraceSink::Open (std::string const &name)
+{
+  NS_LOG_FUNCTION (this << name);
+  NS_ABORT_MSG_UNLESS (m_writer == 0, "AthstatsWifiTraceSink::Open (): m_writer already allocated (std::ofstream leak detected)");
+
+  m_writer = new std::ofstream ();
+  NS_ABORT_MSG_UNLESS (m_writer, "AthstatsWifiTraceSink::Open (): Cannot allocate m_writer");
+
+  NS_LOG_LOGIC ("Created writer " << m_writer);
+
+  m_writer->open (name.c_str (), std::ios_base::binary | std::ios_base::out);
+  NS_ABORT_MSG_IF (m_writer->fail (), "AthstatsWifiTraceSink::Open (): m_writer->open (" << name.c_str () << ") failed");
+
+  NS_ASSERT_MSG (m_writer->is_open (), "AthstatsWifiTraceSink::Open (): m_writer not open");
+
+  NS_LOG_LOGIC ("Writer opened successfully");
+}
+
+
+void
+AthstatsWifiTraceSink::WriteStats ()
+{
+  NS_ABORT_MSG_UNLESS (this, "function called with null this pointer, now=" << Now () );
+  // the comments below refer to how each value maps to madwifi's athstats
+  // I know C strings are ugly but that's the quickest way to use exactly the same format as in madwifi
+  char str[200];
+  snprintf (str, 200, "%8u %8u %7u %7u %7u %6u %6u %6u %7u %4u %3uM\n",
+           m_txCount, // /proc/net/dev transmitted packets to which we should subract mgmt frames
+           m_rxCount, // /proc/net/dev received packets but subracts mgmt frames from it
+           0,         // ast_tx_altrate,
+           m_shortRetryCount,     // ast_tx_shortretry,
+           m_longRetryCount,      // ast_tx_longretry,
+           m_exceededRetryCount,  // ast_tx_xretries,
+           m_phyRxErrorCount,     // ast_rx_crcerr,
+           0,         // ast_rx_badcrypt,
+           0,         // ast_rx_phyerr,
+           0,         // ast_rx_rssi,
+           0          // rate
+           );
+
+  if (m_writer)
+    {
+      
+      *m_writer << str;
+      
+      ResetCounters ();
+      Simulator::Schedule (m_interval, &AthstatsWifiTraceSink::WriteStats, this);
+    }
+}
+
+
+
+
+} // namespace ns3
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/athstats-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,226 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 CTTC
+ *
+ * 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: Nicola Baldo <nbaldo@cttc.es>
+ */
+
+#ifndef ATHSTATS_HELPER_H
+#define ATHSTATS_HELPER_H
+
+#include<string>
+#include "ns3/object.h"
+#include "ns3/attribute.h"
+#include "ns3/object-factory.h"
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+#include "ns3/nstime.h"
+#include "ns3/wifi-phy.h"
+#include "ns3/double.h"
+#include "ns3/mac48-address.h"
+
+namespace ns3 {
+
+
+class NetDevice;
+
+/**
+ * @brief create AthstatsWifiTraceSink instances and connect them to wifi devices
+ *
+ * 
+ */
+class AthstatsHelper
+{
+public:
+  AthstatsHelper ();
+  void EnableAthstats (std::string filename,  uint32_t nodeid, uint32_t deviceid);
+  void EnableAthstats (std::string filename, Ptr<NetDevice> nd);
+  void EnableAthstats (std::string filename, NetDeviceContainer d);
+  void EnableAthstats (std::string filename, NodeContainer n);
+  
+private:
+  Time m_interval;    
+};
+
+
+
+
+/**
+ * @brief trace sink for wifi device that mimics madwifi's athstats tool.
+ *
+ * The AthstatsWifiTraceSink class is a trace sink to be connected to several of the traces
+ * available within a wifi device. The purpose of AthstatsWifiTraceSink is to
+ * mimic the behavior of the athstats tool distributed wih the madwifi
+ * driver. In particular, the reproduced behavior is that obtained
+ * when executing athstats without parameters: a report written in
+ * text format is produced every fixed interval, based on the events
+ * observed by the wifi device. 
+ * 
+ * Differences with the "real" athstats:
+ *
+ * - AthstatsWifiTraceSink is expected to write its output to a file
+ *   (not to stdout).
+ *
+ * - only a subset of the metrics supported by athstats is supported
+ *   by AthstatsWifiTraceSink
+ * 
+ * - AthstatsWifiTraceSink does never produce a cumulative report.
+ */
+class AthstatsWifiTraceSink  : public Object
+{
+public: 
+  static TypeId GetTypeId (void);
+  AthstatsWifiTraceSink ();
+  virtual ~AthstatsWifiTraceSink ();
+    
+
+  /** 
+   * function to be called when the net device transmittes a packet
+   * 
+   * @param context 
+   * @param p the packet being transmitted
+   */
+  void DevTxTrace (std::string context, Ptr<const Packet> p);
+
+  /** 
+   * function to be called when the net device receives a packet
+   * 
+   * @param context 
+   * @param p the packet being received
+   */
+  void DevRxTrace (std::string context, Ptr<const Packet> p);
+
+  /** 
+   * Function to be called when a RTS frame transmission by the considered
+   * device has failed
+   * 
+   * @param context 
+   * @param address the MAC address of the remote station
+   */
+  void TxRtsFailedTrace (std::string context, Mac48Address address);  
+
+  /** 
+   * Function to be called when a data frame transmission by the considered
+   * device has failed
+   * 
+   * @param context 
+   * @param address the MAC address of the remote station
+   */
+  void TxDataFailedTrace (std::string context, Mac48Address address);  
+
+  /** 
+   * Function to be called when the transmission of a RTS frame has
+   * exceeded the retry limit
+   * 
+   * @param context 
+   * @param address the MAC address of the remote station
+   */
+  void TxFinalRtsFailedTrace (std::string context, Mac48Address address);  
+
+  /** 
+   * Function to be called when the transmission of a data frame has
+   * exceeded the retry limit
+   * 
+   * @param context 
+   * @param address the MAC address of the remote station
+   */  
+  void TxFinalDataFailedTrace (std::string context, Mac48Address address);    
+
+
+  /** 
+   * Function to be called when the PHY layer  of the considered
+   * device receives a frame
+   * 
+   * @param context 
+   * @param packet 
+   * @param snr 
+   * @param mode 
+   * @param preamble 
+   */
+  void PhyRxOkTrace (std::string context, Ptr<const Packet> packet, double snr, WifiMode mode, enum WifiPreamble preamble);
+
+  /** 
+   * Function to be called when a frame reception by the PHY
+   * layer  of the considered device resulted in an error due to a failure in the CRC check of
+   * the frame
+   * 
+   * @param context 
+   * @param packet 
+   * @param snr 
+   */
+  void PhyRxErrorTrace (std::string context, Ptr<const Packet> packet, double snr);
+
+  /** 
+   * Function to be called when a frame is being transmitted by the
+   * PHY layer of the considered device
+   * 
+   * @param context 
+   * @param packet 
+   * @param mode 
+   * @param preamble 
+   * @param txPower 
+   */
+  void PhyTxTrace (std::string context, Ptr<const Packet> packet, WifiMode mode, WifiPreamble preamble, uint8_t txPower);
+
+  /** 
+   * Function to be called when the PHY layer of the considered device
+   * changes state
+   * 
+   * @param context 
+   * @param start 
+   * @param duration 
+   * @param state 
+   */
+  void PhyStateTrace (std::string context, Time start, Time duration, enum WifiPhy::State state);
+
+  /** 
+   * Open a file for output
+   * 
+   * @param name the name of the file to be opened.
+   */
+  void Open (std::string const& name);
+
+private:
+
+  void WriteStats ();
+  void ResetCounters ();
+
+
+  uint32_t m_txCount;
+  uint32_t m_rxCount;
+  uint32_t m_shortRetryCount;
+  uint32_t m_longRetryCount;
+  uint32_t m_exceededRetryCount;
+  uint32_t m_phyRxOkCount;
+  uint32_t m_phyRxErrorCount;
+  uint32_t m_phyTxCount;
+
+  std::ofstream *m_writer;
+
+  Time m_interval;    
+
+
+}; // class AthstatsWifiTraceSink
+
+
+
+  
+} // namespace ns3
+
+
+
+
+#endif /* ATHSTATS_HELPER_H */
--- a/src/helper/internet-stack-helper.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/helper/internet-stack-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -153,6 +153,7 @@
 #include "ns3/object.h"
 #include "ns3/names.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv6.h"
 #include "ns3/packet-socket-factory.h"
 #include "ns3/config.h"
 #include "ns3/simulator.h"
@@ -167,6 +168,8 @@
 #include "ipv4-list-routing-helper.h"
 #include "ipv4-static-routing-helper.h"
 #include "ipv4-global-routing-helper.h"
+#include "ipv6-list-routing-helper.h"
+#include "ipv6-static-routing-helper.h"
 #include <limits>
 
 namespace ns3 {
@@ -176,19 +179,28 @@
 bool InternetStackHelper::m_isInitialized = false;
 
 InternetStackHelper::InternetStackHelper ()
+  : m_ipv4Enabled (true),
+  m_ipv6Enabled (true)
 {
   SetTcp ("ns3::TcpL4Protocol");
   static Ipv4StaticRoutingHelper staticRouting;
   static Ipv4GlobalRoutingHelper globalRouting;
   static Ipv4ListRoutingHelper listRouting;
+  static Ipv6ListRoutingHelper listRoutingv6;
+  static Ipv6StaticRoutingHelper staticRoutingv6;
   if (m_isInitialized == false)
     {
       // Only add these once
       listRouting.Add (staticRouting, 0);
       listRouting.Add (globalRouting, -10);
+
+      /* IPv6 */
+      listRoutingv6.Add (staticRoutingv6, 0);
+      /* TODO add IPv6 global routing */
       m_isInitialized = true;
     }
   SetRoutingHelper (listRouting);
+  SetRoutingHelper (listRoutingv6);
 }
 
 void 
@@ -198,9 +210,26 @@
 }
 
 void
+InternetStackHelper::SetRoutingHelper (const Ipv6RoutingHelper &routing)
+{
+  m_routingv6 = &routing;
+}
+
+void
+InternetStackHelper::SetIpv4StackInstall (bool enable)
+{
+  m_ipv4Enabled = enable;
+}
+
+void InternetStackHelper::SetIpv6StackInstall (bool enable)
+{
+  m_ipv6Enabled = enable;
+}
+
+void
 InternetStackHelper::Cleanup (void)
 {
-  uint32_t illegal = std::numeric_limits<uint32_t>::max();
+  uint32_t illegal = std::numeric_limits<uint32_t>::max ();
 
   for (std::vector<Trace>::iterator i = m_traces.begin ();
        i != m_traces.end (); i++)
@@ -244,7 +273,7 @@
 InternetStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId)
 {
   ObjectFactory factory;
-  factory.SetTypeId(typeId);
+  factory.SetTypeId (typeId);
   Ptr<Object> protocol = factory.Create <Object> ();
   node->AggregateObject (protocol);
 }
@@ -252,24 +281,45 @@
 void
 InternetStackHelper::Install (Ptr<Node> node) const
 {
-  if (node->GetObject<Ipv4> () != 0)
+  if (m_ipv4Enabled)
     {
-      NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " 
-                      "an InternetStack to a node with an existing Ipv4 object");
-      return;
+      if (node->GetObject<Ipv4> () != 0)
+        {
+          NS_FATAL_ERROR ("InternetStackHelper::Install (): Aggregating " 
+                          "an InternetStack to a node with an existing Ipv4 object");
+          return;
+        }
+
+      CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
+      CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
+      CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
+      CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
+      node->AggregateObject (m_tcpFactory.Create<Object> ());
+      Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
+      node->AggregateObject (factory);
+      // Set routing
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create (node);
+      ipv4->SetRoutingProtocol (ipv4Routing);
     }
 
-  CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
-  CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
-  CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");
-  CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
-  node->AggregateObject (m_tcpFactory.Create<Object> ());
-  Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory> ();
-  node->AggregateObject (factory);
-  // Set routing
-  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-  Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create (node);
-  ipv4->SetRoutingProtocol (ipv4Routing);
+  if (m_ipv6Enabled)
+    {
+      /* IPv6 stack */
+      if (node->GetObject<Ipv6> () != 0)
+        {
+          NS_FATAL_ERROR ("InternetStackHelper::Install (): Aggregating " 
+                          "an InternetStack to a node with an existing Ipv6 object");
+          return;
+        }
+    
+      CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv6L3Protocol");
+      CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv6L4Protocol");
+      /* TODO add UdpL4Protocol / TcpL4Protocol for IPv6 */
+      Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+      Ptr<Ipv6RoutingProtocol> ipv6Routing = m_routingv6->Create (node);
+      ipv6->SetRoutingProtocol (ipv6Routing);
+    }
 }
 
 void
@@ -293,6 +343,9 @@
       oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop";
       Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEvent, writer));
       oss.str ("");
+      oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv6L3Protocol/Drop";
+      Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEvent, writer));
+      oss.str ("");
     }
 }
 
@@ -312,6 +365,12 @@
                    MakeCallback (&InternetStackHelper::LogTxIp));
   Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Rx",
                    MakeCallback (&InternetStackHelper::LogRxIp));
+
+  /* IPv6 */
+  Config::Connect ("/NodeList/*/$ns3::Ipv6L3Protocol/Tx",
+                   MakeCallback (&InternetStackHelper::LogTxIp));
+  Config::Connect ("/NodeList/*/$ns3::Ipv6L3Protocol/Rx",
+                   MakeCallback (&InternetStackHelper::LogRxIp));
 }
 
 uint32_t
--- a/src/helper/internet-stack-helper.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/helper/internet-stack-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -31,6 +31,7 @@
 
 class Node;
 class Ipv4RoutingHelper;
+class Ipv6RoutingHelper;
 
 /**
  * \brief aggregate IP/TCP/UDP functionality to existing Nodes.
@@ -59,9 +60,15 @@
    * ns3::Ipv4::SetRoutingProtocol.
    */
   void SetRoutingHelper (const Ipv4RoutingHelper &routing);
+  
+  /**
+   * \brief Set IPv6 routing helper.
+   * \param routing IPv6 routing helper
+   */
+  void SetRoutingHelper (const Ipv6RoutingHelper &routing);
 
   /**
-   * Aggregate implementations of the ns3::Ipv4, ns3::Udp, and ns3::Tcp classes
+   * Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes
    * onto the provided node.  This method will assert if called on a node that 
    * already has an Ipv4 object aggregated to it.
    * 
@@ -70,7 +77,7 @@
   void Install (std::string nodeName) const;
 
   /**
-   * Aggregate implementations of the ns3::Ipv4, ns3::Udp, and ns3::Tcp classes
+   * Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes
    * onto the provided node.  This method will assert if called on a node that 
    * already has an Ipv4 object aggregated to it.
    * 
@@ -80,7 +87,7 @@
 
   /**
    * For each node in the input container, aggregate implementations of the 
-   * ns3::Ipv4, ns3::Udp, and, ns3::Tcp classes.  The program will assert 
+   * ns3::Ipv4, ns3::Ipv6, ns3::Udp, and, ns3::Tcp classes.  The program will assert 
    * if this method is called on a container with a node that already has
    * an Ipv4 object aggregated to it.
    * 
@@ -90,11 +97,11 @@
   void Install (NodeContainer c) const;
 
   /**
-   * Aggregate ip, udp, and tcp stacks to all nodes in the simulation
+   * Aggregate IPv4, IPv6, UDP, and TCP stacks to all nodes in the simulation
    */
   void InstallAll (void) const;
 
- /**
+  /**
    * \brief set the Tcp stack which will not need any other parameter.  
    *
    * This function sets up the tcp stack to the given TypeId. It should not be 
@@ -128,6 +135,7 @@
    * Enable ascii output on these drop traces, for each node in the NodeContainer..
    * /NodeList/[i]/$ns3ArpL3Protocol/Drop 
    * /NodeList/[i]/$ns3Ipv4L3Protocol/Drop 
+   * /NodeList/[i]/$ns3Ipv6L3Protocol/Drop 
    */
   static void EnableAscii (std::ostream &os, NodeContainer n);
 
@@ -137,12 +145,14 @@
    * Enable ascii output on these drop traces, for all nodes.
    * /NodeList/[i]/$ns3ArpL3Protocol/Drop 
    * /NodeList/[i]/$ns3Ipv4L3Protocol/Drop 
+   * /NodeList/[i]/$ns3Ipv6L3Protocol/Drop 
    */
   static void EnableAsciiAll (std::ostream &os);
 
   /**
    * Enable pcap output on each protocol instance which is of the
-   * ns3::Ipv4L3Protocol type.  Both Tx and Rx events will be logged.
+   * ns3::Ipv4L3Protocol or ns3::Ipv6L3Protocol type.  Both Tx and 
+   * Rx events will be logged.
    *
    * \param filename filename prefix to use for pcap files.
    *
@@ -155,9 +165,27 @@
    */
   static void EnablePcapAll (std::string filename);
 
+  /**
+   * \brief Enable/disable IPv4 stack install.
+   * \param enable enable state
+   */
+  void SetIpv4StackInstall (bool enable);
+
+  /**
+   * \brief Enable/disable IPv6 stack install.
+   * \param enable enable state
+   */
+  void SetIpv6StackInstall (bool enable);
+
 private:
   ObjectFactory m_tcpFactory;
   const Ipv4RoutingHelper *m_routing;
+  
+  /**
+   * \brief IPv6 routing helper.
+   */
+  const Ipv6RoutingHelper *m_routingv6;
+
   static void CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId);
   static void Cleanup (void);
   static void LogRxIp (std::string context, Ptr<const Packet> packet, uint32_t deviceId);
@@ -173,6 +201,16 @@
   static uint32_t GetNodeIndex (std::string context);
   static std::vector<Trace> m_traces;
   static bool m_isInitialized;
+
+  /**
+   * \brief IPv4 install state (enabled/disabled) ?
+   */
+  bool m_ipv4Enabled;
+
+  /**
+   * \brief IPv6 install state (enabled/disabled) ?
+   */
+  bool m_ipv6Enabled;
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-address-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,167 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/mac48-address.h"
+#include "ns3/ipv6.h"
+
+#include "ipv6-address-helper.h"
+
+namespace ns3 
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6AddressHelper");
+
+Ipv6AddressHelper::Ipv6AddressHelper ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_network = Ipv6Address ("2001::");
+  m_prefix = Ipv6Prefix (64);
+}
+
+Ipv6Address Ipv6AddressHelper::NewAddress (Address addr)
+{
+  NS_LOG_FUNCTION (this << addr);
+
+  switch (addr.GetLength ())
+  {
+    case 6:
+      return Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), m_network);
+    default:
+      return Ipv6Address ("::");
+  }
+  /* never reached */
+  return Ipv6Address ("::");
+}
+
+void Ipv6AddressHelper::NewNetwork (Ipv6Address network, Ipv6Prefix prefix)
+{
+  NS_LOG_FUNCTION (this << network << prefix);
+
+  m_network = network;
+  m_prefix = prefix;
+}
+
+Ipv6InterfaceContainer Ipv6AddressHelper::Assign (const NetDeviceContainer &c)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv6InterfaceContainer retval;
+
+  for (uint32_t i = 0; i < c.GetN (); ++i) 
+  {
+    Ptr<NetDevice> device = c.Get (i);
+
+    Ptr<Node> node = device->GetNode ();
+    NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node");
+
+    Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+    NS_ASSERT_MSG (ipv6, "Ipv6AddressHelper::Allocate (): Bad ipv6");
+    int32_t ifIndex = 0;
+
+    ifIndex = ipv6->GetInterfaceForDevice (device);
+    if (ifIndex == -1)
+    {
+      ifIndex = ipv6->AddInterface (device);
+    }
+    NS_ASSERT_MSG (ifIndex >= 0, "Ipv6AddressHelper::Allocate (): "
+        "Interface index not found");
+
+    Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (NewAddress (device->GetAddress ()), m_prefix);
+    ipv6->SetMetric (ifIndex, 1);
+    ipv6->SetUp (ifIndex);
+    ipv6->AddAddress (ifIndex, ipv6Addr);
+
+    retval.Add (ipv6, ifIndex);
+  }
+  return retval;
+}
+
+Ipv6InterfaceContainer Ipv6AddressHelper::Assign (const NetDeviceContainer &c, std::vector<bool> withConfiguration)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv6InterfaceContainer retval;
+  for (uint32_t i = 0; i < c.GetN (); ++i) 
+  {
+    Ptr<NetDevice> device = c.Get (i);
+
+    Ptr<Node> node = device->GetNode ();
+    NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node");
+
+    Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+    NS_ASSERT_MSG (ipv6, "Ipv6AddressHelper::Allocate (): Bad ipv6");
+
+    int32_t ifIndex = ipv6->GetInterfaceForDevice (device);
+    if (ifIndex == -1)
+    {
+      ifIndex = ipv6->AddInterface (device);
+    }
+    NS_ASSERT_MSG (ifIndex >= 0, "Ipv6AddressHelper::Allocate (): "
+        "Interface index not found");
+
+    ipv6->SetMetric (ifIndex, 1);
+    ipv6->SetUp (ifIndex);
+
+    if (withConfiguration.at (i))
+    {
+      Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (NewAddress (device->GetAddress ()), m_prefix);
+      ipv6->AddAddress (ifIndex, ipv6Addr);
+    }
+
+    retval.Add (ipv6, ifIndex);
+  }
+  return retval;
+}
+
+Ipv6InterfaceContainer Ipv6AddressHelper::AssignWithoutAddress (const NetDeviceContainer &c)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv6InterfaceContainer retval;
+  for (uint32_t i = 0; i < c.GetN (); ++i) 
+  {
+    Ptr<NetDevice> device = c.Get (i);
+
+    Ptr<Node> node = device->GetNode ();
+    NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node");
+
+    Ptr<Ipv6> ipv6 = node->GetObject<Ipv6> ();
+    NS_ASSERT_MSG (ipv6, "Ipv6AddressHelper::Allocate (): Bad ipv6");
+
+    int32_t ifIndex = ipv6->GetInterfaceForDevice (device);
+    if (ifIndex == -1)
+    {
+      ifIndex = ipv6->AddInterface (device);
+    }
+    NS_ASSERT_MSG (ifIndex >= 0, "Ipv6AddressHelper::Allocate (): "
+        "Interface index not found");
+
+    ipv6->SetMetric (ifIndex, 1);
+    ipv6->SetUp (ifIndex);
+
+    retval.Add (ipv6, ifIndex);
+  }
+  return retval;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-address-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,96 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_ADDRESS_STATIC_HELPER_H
+#define IPV6_ADDRESS_STATIC_HELPER_H
+
+#include <vector>
+
+#include "ns3/ipv6-address.h"
+#include "net-device-container.h"
+#include "ipv6-interface-container.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6AddressHelper
+ * \brief Helper class to assign IPv6 address statically.
+ */
+class Ipv6AddressHelper
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6AddressHelper ();
+
+    /**
+     * \brief Allocate a new network.
+     * \param network The IPv6 network
+     * \param prefix The prefix
+     */
+    void NewNetwork (Ipv6Address network, Ipv6Prefix prefix);
+
+    /**
+     * \brief Allocate a new address.
+     * \param addr L2 address (currenty only ethernet address is supported)
+     * \return newly created Ipv6Address
+     */
+    Ipv6Address NewAddress (Address addr);
+
+    /**
+     * \brief Allocate an Ipv6InterfaceContainer.
+     * \param c netdevice container
+     * \return newly created Ipv6InterfaceContainer
+     */
+    Ipv6InterfaceContainer Assign (const NetDeviceContainer &c);
+
+    /**
+     * \brief Allocate an Ipv6InterfaceContainer.
+     * \param c netdevice container
+     * \param withConfiguration true : interface statically configured, false : no static configuration
+     * \return newly created Ipv6InterfaceContainer
+     */
+    Ipv6InterfaceContainer Assign (const NetDeviceContainer &c, std::vector<bool> withConfiguration);
+
+    /**
+     * \brief Allocate an Ipv6InterfaceContainer without static IPv6 configuration.
+     * \param c netdevice container
+     * \return newly created Ipv6InterfaceContainer
+     */
+    Ipv6InterfaceContainer AssignWithoutAddress (const NetDeviceContainer &c);
+
+  private:
+    /**
+     * \brief The IPv6 network.
+     */
+    Ipv6Address m_network;
+
+    /**
+     * \brief IPv6 The prefix (mask).
+     */
+    Ipv6Prefix m_prefix;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_ADDRESS_STATIC_HELPER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-interface-container.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,109 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+
+#include "ipv6-interface-container.h"
+#include "ipv6-static-routing-helper.h"
+
+namespace ns3 
+{
+
+Ipv6InterfaceContainer::Ipv6InterfaceContainer ()
+{
+}
+
+uint32_t Ipv6InterfaceContainer::GetN () const
+{
+  return m_interfaces.size ();
+}
+
+uint32_t Ipv6InterfaceContainer::GetInterfaceIndex (uint32_t i) const
+{
+  return m_interfaces[i].second;
+}
+
+Ipv6Address Ipv6InterfaceContainer::GetAddress (uint32_t i, uint32_t j) const
+{
+  Ptr<Ipv6> ipv6 = m_interfaces[i].first;
+  uint32_t interface = m_interfaces[i].second;
+  return ipv6->GetAddress (interface, j).GetAddress ();
+}
+
+void Ipv6InterfaceContainer::Add (Ptr<Ipv6> ipv6, uint32_t interface)
+{
+  m_interfaces.push_back (std::make_pair (ipv6, interface));
+}
+
+void Ipv6InterfaceContainer::Add (std::string ipv6Name, uint32_t interface)
+{
+  Ptr<Ipv6> ipv6 = Names::Find<Ipv6> (ipv6Name);
+  m_interfaces.push_back (std::make_pair (ipv6, interface));
+}
+
+void Ipv6InterfaceContainer::Add (Ipv6InterfaceContainer& c)
+{
+  for (InterfaceVector::const_iterator it = c.m_interfaces.begin () ; it != c.m_interfaces.end () ; it++)
+  {
+    m_interfaces.push_back (*it);
+  }
+}
+
+void Ipv6InterfaceContainer::SetRouter (uint32_t i, bool router)
+{
+  Ptr<Ipv6> ipv6 = m_interfaces[i].first;
+  ipv6->SetForwarding (m_interfaces[i].second, router);
+
+  if (router)
+  {
+    uint32_t other;
+    /* assume first global address is index 1 (0 is link-local) */
+    Ipv6Address routerAddress = ipv6->GetAddress (m_interfaces[i].second, 1).GetAddress ();
+
+    for (other = 0 ; other < m_interfaces.size () ; other++)
+    {
+      if (other != i)
+      {
+        Ptr<Ipv6StaticRouting> routing = 0;
+        Ipv6StaticRoutingHelper routingHelper;
+
+        ipv6 = m_interfaces[other].first;
+        routing = routingHelper.GetStaticRouting (ipv6);
+        routing->SetDefaultRoute (routerAddress, m_interfaces[other].second);
+      }
+    }
+  }
+}
+
+void Ipv6InterfaceContainer::SetDefaultRoute (uint32_t i, uint32_t router)
+{
+  Ptr<Ipv6> ipv6 = m_interfaces[i].first;
+  Ptr<Ipv6> ipv6Router = m_interfaces[router].first;
+  Ipv6Address routerAddress = ipv6Router->GetAddress (m_interfaces[router].second, 1).GetAddress ();
+  Ptr<Ipv6StaticRouting> routing = 0;
+  Ipv6StaticRoutingHelper routingHelper;
+
+  routing = routingHelper.GetStaticRouting (ipv6);
+  routing->SetDefaultRoute (routerAddress, m_interfaces[i].second);
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-interface-container.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,111 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_INTERFACE_CONTAINER_H
+#define IPV6_INTERFACE_CONTAINER_H
+
+#include <stdint.h>
+#include <vector>
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-address.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6InterfaceContainer
+ * \brief keep track of a set of IPv6 interfaces.
+ */
+class Ipv6InterfaceContainer
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6InterfaceContainer ();
+
+    /**
+     * \brief Get the number of interfaces.
+     * \return the number of interfaces stored in this Ipv6InterfaceContainer.
+     */
+    uint32_t GetN (void) const;
+
+    /**
+     * \brief Get the interface index for the specified node index.
+     * \param i index of the node
+     * \return interface index
+     */
+    uint32_t GetInterfaceIndex (uint32_t i) const;
+
+    /**
+     * \brief Get the address for the specified index.
+     * \param i interface index
+     * \param j address index, generally index 0 is the link-local address
+     * \return IPv6 address
+     */
+    Ipv6Address GetAddress (uint32_t i, uint32_t j) const;
+
+    /**
+     * \brief Add a couple IPv6/interface.
+     * \param ipv6 IPv6 address
+     * \param interface interface index
+     */
+    void Add (Ptr<Ipv6> ipv6, uint32_t interface);
+
+    /**
+     * \brief Fusion with another Ipv6InterfaceContainer.
+     * \param c container
+     */
+    void Add (Ipv6InterfaceContainer& c);
+
+    /**
+     * \brief Add a couple of name/interface.
+     * \param ipv6Name name of a node
+     * \param interface interface index to add
+     */
+    void Add (std::string ipv6Name, uint32_t interface);
+
+    /**
+     * \brief Set the state of the stack (act as a router or not) for the specified index.
+     * \param i index
+     * \param router true : is a router, false : is an host
+     */
+    void SetRouter (uint32_t i, bool router);
+
+    /**
+     * \brief Set the default route for the specified index.
+     * \param i index
+     * \param router the default router
+     */
+    void SetDefaultRoute (uint32_t i, uint32_t router);
+
+  private:
+    typedef std::vector<std::pair<Ptr<Ipv6>, uint32_t> > InterfaceVector;
+
+    /**
+     * \brief List of IPv6 stack and interfaces index.
+     */
+    InterfaceVector m_interfaces;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_INTERFACE_CONTAINER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-list-routing-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,46 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "ipv6-list-routing-helper.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/node.h"
+
+namespace ns3 {
+
+Ipv6ListRoutingHelper::Ipv6ListRoutingHelper ()
+{}
+void 
+Ipv6ListRoutingHelper::Add (const Ipv6RoutingHelper &routing, int16_t priority)
+{
+  m_list.push_back (std::make_pair (&routing,priority));
+}
+Ptr<Ipv6RoutingProtocol> 
+Ipv6ListRoutingHelper::Create (Ptr<Node> node) const
+{
+  Ptr<Ipv6ListRouting> list = CreateObject<Ipv6ListRouting> ();
+  for (std::list<std::pair<const Ipv6RoutingHelper *,int16_t> >::const_iterator i = m_list.begin ();
+       i != m_list.end (); ++i)
+    {
+      Ptr<Ipv6RoutingProtocol> prot = i->first->Create (node);
+      list->AddRoutingProtocol (prot,i->second);
+    }
+  return list;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-list-routing-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV6_LIST_ROUTING_HELPER_H
+#define IPV6_LIST_ROUTING_HELPER_H
+
+#include "ipv6-routing-helper.h"
+#include <stdint.h>
+#include <list>
+
+namespace ns3 {
+
+/**
+ * \brief Helper class that adds ns3::Ipv6ListRouting objects
+ *
+ * This class is expected to be used in conjunction with 
+ * ns3::InternetStackHelper::SetRoutingHelper
+ */
+class Ipv6ListRoutingHelper : public Ipv6RoutingHelper
+{
+public:
+  Ipv6ListRoutingHelper ();
+  /**
+   * \param routing a routing helper
+   * \param priority the priority of the associated helper
+   *
+   * Store in the internal list a reference to the input routing helper
+   * and associated priority. These helpers will be used later by
+   * the ns3::Ipv6ListRoutingHelper::Create method to create
+   * an ns3::Ipv6ListRouting object and add in it routing protocols
+   * created with the helpers.
+   */
+  void Add (const Ipv6RoutingHelper &routing, int16_t priority);
+  /**
+   * \param node the node on which the routing protocol will run
+   * \returns a newly-created routing protocol
+   *
+   * This method will be called by ns3::InternetStackHelper::Install
+   */
+  virtual Ptr<Ipv6RoutingProtocol> Create (Ptr<Node> node) const;
+private:
+  std::list<std::pair<const Ipv6RoutingHelper *,int16_t> > m_list;
+};
+
+} // namespace ns3
+
+#endif /* IPV6_LIST_ROUTING_HELPER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-routing-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,28 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv6-routing-helper.h"
+
+namespace ns3 {
+
+Ipv6RoutingHelper::~Ipv6RoutingHelper ()
+{}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-routing-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,54 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef IPV6_ROUTING_HELPER_H
+#define IPV6_ROUTING_HELPER_H
+
+#include "ns3/ptr.h"
+
+namespace ns3 {
+
+class Ipv6RoutingProtocol;
+class Node;
+
+/**
+ * \brief a factory to create ns3::Ipv6RoutingProtocol objects
+ *
+ * For each new routing protocol created as a subclass of 
+ * ns3::Ipv6RoutingProtocol, you need to create a subclass of 
+ * ns3::Ipv6RoutingHelper which can be used by 
+ * ns3::InternetStackHelper::SetRoutingHelper and 
+ * ns3::InternetStackHelper::Install.
+ */
+class Ipv6RoutingHelper
+{
+public:
+  virtual ~Ipv6RoutingHelper ();
+  /**
+   * \param node the node within which the new routing protocol will run
+   * \returns a newly-created routing protocol
+   */
+  virtual Ptr<Ipv6RoutingProtocol> Create (Ptr<Node> node) const = 0;
+};
+
+} // namespace ns3
+
+
+#endif /* IPV6_ROUTING_HELPER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-static-routing-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,200 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <vector>
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/names.h"
+#include "ns3/node.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-route.h"
+#include "ns3/ipv6-list-routing.h"
+#include "ns3/assert.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/ipv6-routing-protocol.h"
+#include "ipv6-static-routing-helper.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6StaticRoutingHelper");
+
+namespace ns3 {
+
+Ipv6StaticRoutingHelper::Ipv6StaticRoutingHelper ()
+{}
+Ptr<Ipv6RoutingProtocol> 
+Ipv6StaticRoutingHelper::Create (Ptr<Node> node) const
+{
+  return CreateObject<Ipv6StaticRouting> ();
+}
+
+Ptr<Ipv6StaticRouting>
+Ipv6StaticRoutingHelper::GetStaticRouting (Ptr<Ipv6> ipv6) const
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv6RoutingProtocol> ipv6rp = ipv6->GetRoutingProtocol ();
+  NS_ASSERT_MSG (ipv6rp, "No routing protocol associated with Ipv6");
+  if (DynamicCast<Ipv6StaticRouting> (ipv6rp))
+    {
+      NS_LOG_LOGIC ("Static routing found as the main IPv4 routing protocol.");
+      return DynamicCast<Ipv6StaticRouting> (ipv6rp); 
+    } 
+  if (DynamicCast<Ipv6ListRouting> (ipv6rp))
+    {
+      Ptr<Ipv6ListRouting> lrp = DynamicCast<Ipv6ListRouting> (ipv6rp);
+      int16_t priority;
+      for (uint32_t i = 0; i < lrp->GetNRoutingProtocols ();  i++)
+        {
+          NS_LOG_LOGIC ("Searching for static routing in list");
+          Ptr<Ipv6RoutingProtocol> temp = lrp->GetRoutingProtocol (i, priority);
+          if (DynamicCast<Ipv6StaticRouting> (temp))
+            {
+              NS_LOG_LOGIC ("Found static routing in list");
+              return DynamicCast<Ipv6StaticRouting> (temp);
+            }
+        }
+    }
+  NS_LOG_LOGIC ("Static routing not found");
+  return 0;
+}
+
+void  
+Ipv6StaticRoutingHelper::AddMulticastRoute (
+  Ptr<Node> n,
+  Ipv6Address source, 
+  Ipv6Address group,  
+  Ptr<NetDevice> input, 
+  NetDeviceContainer output)
+{
+  Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+
+  // We need to convert the NetDeviceContainer to an array of interface 
+  // numbers
+  std::vector<uint32_t> outputInterfaces;
+  for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i)
+    {
+      Ptr<NetDevice> nd = *i;
+      int32_t interface = ipv6->GetInterfaceForDevice (nd);
+      NS_ASSERT_MSG (interface >= 0, 
+        "Ipv6StaticRoutingHelper::AddMulticastRoute (): "
+        "Expected an interface associated with the device nd");
+      outputInterfaces.push_back (interface);
+    }
+
+  int32_t inputInterface = ipv6->GetInterfaceForDevice (input);
+  NS_ASSERT_MSG (inputInterface >= 0, 
+    "Ipv6StaticRoutingHelper::AddMulticastRoute (): "
+    "Expected an interface associated with the device input");
+  Ipv6StaticRoutingHelper helper;
+  Ptr<Ipv6StaticRouting> ipv6StaticRouting = helper.GetStaticRouting (ipv6);
+  if (!ipv6StaticRouting)
+    {
+  NS_ASSERT_MSG (ipv6StaticRouting, 
+    "Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (): "
+    "Expected an Ipv6StaticRouting associated with this node");
+    }
+  ipv6StaticRouting->AddMulticastRoute (source, group, inputInterface, outputInterfaces);
+}
+
+void  
+Ipv6StaticRoutingHelper::AddMulticastRoute (
+  Ptr<Node> n,
+  Ipv6Address source, 
+  Ipv6Address group,  
+  std::string inputName, 
+  NetDeviceContainer output)
+{
+  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+void  
+Ipv6StaticRoutingHelper::AddMulticastRoute (
+  std::string nName,
+  Ipv6Address source, 
+  Ipv6Address group,  
+  Ptr<NetDevice> input, 
+  NetDeviceContainer output)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+void  
+Ipv6StaticRoutingHelper::AddMulticastRoute (
+  std::string nName,
+  Ipv6Address source, 
+  Ipv6Address group,  
+  std::string inputName, 
+  NetDeviceContainer output)
+{
+  Ptr<NetDevice> input = Names::Find<NetDevice> (inputName);
+  Ptr<Node> n = Names::Find<Node> (nName);
+  AddMulticastRoute (n, source, group, input, output);
+}
+
+#if 0
+void
+Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (
+  Ptr<Node> n, 
+  Ptr<NetDevice> nd)
+{
+  Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
+  int32_t interfaceSrc = ipv6->GetInterfaceForDevice (nd);
+  NS_ASSERT_MSG (interfaceSrc >= 0, 
+    "Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (): "
+    "Expected an interface associated with the device");
+  Ipv6StaticRoutingHelper helper;
+  Ptr<Ipv6StaticRouting> ipv6StaticRouting = helper.GetStaticRouting (ipv6);
+  if (!ipv6StaticRouting)
+    {
+      NS_ASSERT_MSG (ipv6StaticRouting, 
+        "Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (): "
+        "Expected an Ipv6StaticRouting associated with this node");
+    }
+  ipv6StaticRouting->SetDefaultMulticastRoute (interfaceSrc);
+}
+
+void
+Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (
+  Ptr<Node> n, 
+  std::string ndName)
+{
+  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
+  SetDefaultMulticastRoute (n, nd);
+}
+
+void
+Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (
+  std::string nName, 
+  Ptr<NetDevice> nd)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  SetDefaultMulticastRoute (n, nd);
+}
+
+void
+Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (
+  std::string nName, 
+  std::string ndName)
+{
+  Ptr<Node> n = Names::Find<Node> (nName);
+  Ptr<NetDevice> nd = Names::Find<NetDevice> (ndName);
+  SetDefaultMulticastRoute (n, nd);
+}
+#endif
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv6-static-routing-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,79 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IPV6_STATIC_ROUTING_HELPER_H
+#define IPV6_STATIC_ROUTING_HELPER_H
+
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-static-routing.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ipv6-routing-helper.h"
+#include "node-container.h"
+#include "net-device-container.h"
+
+namespace ns3 {
+
+/**
+ * \brief Helper class that adds ns3::Ipv6StaticRouting objects
+ *
+ * This class is expected to be used in conjunction with 
+ * ns3::InternetStackHelper::SetRoutingHelper
+ */
+class Ipv6StaticRoutingHelper : public Ipv6RoutingHelper
+{
+public:
+  Ipv6StaticRoutingHelper ();
+
+  /**
+   * \param node the node on which the routing protocol will run
+   * \returns a newly-created routing protocol
+   *
+   * This method will be called by ns3::InternetStackHelper::Install
+   */
+  virtual Ptr<Ipv6RoutingProtocol> Create (Ptr<Node> node) const;
+
+  Ptr<Ipv6StaticRouting> GetStaticRouting (Ptr<Ipv6> ipv6) const;
+
+  void AddMulticastRoute (Ptr<Node> n, Ipv6Address source, Ipv6Address group,  
+    Ptr<NetDevice> input, NetDeviceContainer output);
+  void AddMulticastRoute (std::string n, Ipv6Address source, Ipv6Address group,  
+    Ptr<NetDevice> input, NetDeviceContainer output);
+  void AddMulticastRoute (Ptr<Node> n, Ipv6Address source, Ipv6Address group,  
+    std::string inputName, NetDeviceContainer output);
+  void AddMulticastRoute (std::string nName, Ipv6Address source, Ipv6Address group,  
+    std::string inputName, NetDeviceContainer output);
+
+#if 0
+  /**
+   * \brief Add a default route to the static routing protocol to forward
+   *        packets out a particular interface
+   */
+  void SetDefaultMulticastRoute (Ptr<Node> n, Ptr<NetDevice> nd);
+  void SetDefaultMulticastRoute (Ptr<Node> n, std::string ndName);
+  void SetDefaultMulticastRoute (std::string nName, Ptr<NetDevice> nd);
+  void SetDefaultMulticastRoute (std::string nName, std::string ndName);
+#endif
+};
+
+} // namespace ns3
+
+#endif /* IPV6_STATIC_ROUTING_HELPER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ping6-helper.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,72 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/ping6.h"
+#include "ns3/uinteger.h"
+
+#include "ping6-helper.h"
+
+namespace ns3
+{
+
+Ping6Helper::Ping6Helper ()
+  : m_ifIndex (0)
+{
+  m_factory.SetTypeId (Ping6::GetTypeId ());
+}
+
+void Ping6Helper::SetLocal (Ipv6Address ip)
+{
+  m_localIp = ip;
+}
+
+void Ping6Helper::SetRemote (Ipv6Address ip)
+{
+  m_remoteIp = ip;
+}
+
+void Ping6Helper::SetAttribute (std::string name, const AttributeValue& value)
+{
+  m_factory.Set (name, value);
+}
+
+ApplicationContainer Ping6Helper::Install (NodeContainer c)
+{
+  ApplicationContainer apps;
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+  {
+    Ptr<Node> node = *i;
+    Ptr<Ping6> client = m_factory.Create<Ping6> ();
+    client->SetLocal (m_localIp);
+    client->SetRemote (m_remoteIp);
+    client->SetIfIndex (m_ifIndex);
+    node->AddApplication (client);
+    apps.Add (client);
+  }
+  return apps;  
+}
+
+void Ping6Helper::SetIfIndex (uint32_t ifIndex)
+{
+  m_ifIndex = ifIndex;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ping6-helper.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,103 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef PING6_HELPER_H
+#define PING6_HELPER_H
+
+#include <stdint.h>
+#include "application-container.h"
+#include "node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/ipv6-address.h"
+
+namespace ns3 {
+
+/**
+ * \class Ping6Helper
+ * \brief Ping6 application helper.
+ */
+class Ping6Helper
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ping6Helper ();
+
+    /**
+     * \brief Set the local IPv6 address.
+     * \param ip local IPv6 address
+     */
+    void SetLocal (Ipv6Address ip);
+
+    /**
+     * \brief Set the remote IPv6 address.
+     * \param ip remote IPv6 address
+     */
+    void SetRemote (Ipv6Address ip);
+
+    /**
+     * \brief Set some attributes.
+     * \param name attribute name
+     * \param value attribute value
+     */
+    void SetAttribute (std::string name, const AttributeValue& value);
+
+    /**
+     * \brief Install the application in Nodes.
+     * \param c list of Nodes
+     * \return application container
+     */
+    ApplicationContainer Install (NodeContainer c);
+
+    /**
+     * \brief Set the out interface index.
+     * This is to send to link-local (unicast or multicast) address
+     * when a node has multiple interfaces.
+     * \param ifIndex interface index
+     */
+    void SetIfIndex (uint32_t ifIndex);
+
+  private:
+    /**
+     * \brief An object factory.
+     */
+    ObjectFactory m_factory;
+
+    /**
+     * \brief The local IPv6 address.
+     */
+    Ipv6Address m_localIp;
+
+    /**
+     * \brief The remote IPv6 address.
+     */
+    Ipv6Address m_remoteIp;
+
+    /**
+     * \brief Out interface index.                       
+     */
+    uint32_t m_ifIndex;
+};
+
+} /* namespace ns3 */
+
+#endif /* PING6_HELPER_H */
+
--- a/src/helper/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/helper/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -29,6 +29,13 @@
         'ipv4-list-routing-helper.cc',
         'ipv4-routing-helper.cc',
         'mesh-helper.cc',
+        'athstats-helper.cc',
+        'ipv6-address-helper.cc',
+        'ipv6-interface-container.cc',
+        'ipv6-static-routing-helper.cc',
+        'ipv6-list-routing-helper.cc',
+        'ipv6-routing-helper.cc',
+        'ping6-helper.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -60,6 +67,13 @@
         'ipv4-list-routing-helper.h',
         'ipv4-routing-helper.h',
         'mesh-helper.h',
+        'athstats-helper.h',
+        'ipv6-address-helper.h',
+        'ipv6-interface-container.h',
+        'ipv6-static-routing-helper.h',
+        'ipv6-list-routing-helper.h',
+        'ipv6-routing-helper.h',
+        'ping6-helper.h',
         ]
 
     env = bld.env_of_name('default')
--- a/src/internet-stack/arp-cache.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/arp-cache.h	Wed Aug 26 15:29:03 2009 +0400
@@ -32,7 +32,7 @@
 #include "ns3/ptr.h"
 #include "ns3/object.h"
 #include "ns3/traced-callback.h"
-#include "sgi-hashmap.h"
+#include "ns3/sgi-hashmap.h"
 
 namespace ns3 {
 
--- a/src/internet-stack/arp-l3-protocol.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/arp-l3-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -26,14 +26,13 @@
 #include "ns3/ptr.h"
 #include "ns3/traced-callback.h"
 
-#include "ipv4-interface.h"
-
 namespace ns3 {
 
 class ArpCache;
 class NetDevice;
 class Node;
 class Packet;
+class Ipv4Interface;
 
 /**
  * \ingroup internetStack
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv6-header.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1773 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn> 
+ *         David Gross <gdavid.devel@gmail.com>
+ */
+
+#include "ns3/assert.h"
+#include "ns3/address-utils.h"
+#include "icmpv6-header.h"
+#include "ns3/log.h"
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6Header);
+
+NS_LOG_COMPONENT_DEFINE ("Icmpv6Header");
+
+TypeId Icmpv6Header::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6Header")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv6Header> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6Header::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6Header::Icmpv6Header ()
+  : m_calcChecksum (true),
+  m_checksum (0),
+  m_type (0),
+  m_code (0)
+{
+}
+
+Icmpv6Header::~Icmpv6Header ()
+{
+}
+
+uint8_t Icmpv6Header::GetType () const
+{
+  return m_type;
+}
+
+void Icmpv6Header::SetType (uint8_t type)
+{
+  m_type = type;
+}
+
+uint8_t Icmpv6Header::GetCode () const
+{
+  return m_code;
+}
+
+void Icmpv6Header::SetCode (uint8_t code)
+{
+  m_code = code;
+}
+
+uint16_t Icmpv6Header::GetChecksum () const
+{
+  return m_checksum;
+}
+
+void Icmpv6Header::SetChecksum (uint16_t checksum)
+{
+  m_checksum = checksum;
+}
+
+void Icmpv6Header::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)m_type << " code = " << (uint32_t)m_code << " checksum = " << (uint32_t)m_checksum << ")";
+}
+
+uint32_t Icmpv6Header::GetSerializedSize () const
+{
+  return 4;
+}
+
+uint32_t Icmpv6Header::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_type = i.ReadU8 ();
+  m_code = i.ReadU8 ();
+  m_checksum = i.ReadNtohU16 ();
+#if 0
+  i.ReadU32 (); /* padding */
+#endif
+  return GetSerializedSize ();
+}
+
+void Icmpv6Header::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (m_type);
+  i.WriteU8 (m_code);
+  i.WriteU16 (0);
+#if 0
+  i.WriteU32 (0); /* padding */
+#endif
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    uint16_t checksum = i.CalculateIpChecksum (i.GetSize (), m_checksum);
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+void Icmpv6Header::CalculatePseudoHeaderChecksum (Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol)
+{
+  Buffer buf = Buffer (40);
+  uint8_t tmp[16];
+  Buffer::Iterator it;
+
+  buf.AddAtStart (40);
+  it = buf.Begin ();
+
+  src.Serialize (tmp);
+  it.Write (tmp, 16); /* source IPv6 address */
+  dst.Serialize (tmp);
+  it.Write (tmp, 16); /* destination IPv6 address */
+  it.WriteU16 (0); /* length */
+  it.WriteU8 (length >> 8); /* length */
+  it.WriteU8 (length & 0xff); /* length */
+  it.WriteU16 (0); /* zero */
+  it.WriteU8 (0); /* zero */
+  it.WriteU8 (protocol); /* next header */
+
+  it = buf.Begin ();
+  m_checksum = ~(it.CalculateIpChecksum (40));
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6NS);
+
+Icmpv6NS::Icmpv6NS ()
+{
+  SetType (ICMPV6_ND_NEIGHBOR_SOLICITATION);
+  SetCode (0);
+  SetReserved (0);
+  m_checksum = 0;
+}
+
+TypeId Icmpv6NS::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6NS")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6NS> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6NS::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6NS::Icmpv6NS (Ipv6Address target)
+{
+  SetType (ICMPV6_ND_NEIGHBOR_SOLICITATION);
+  SetCode (0);
+  SetReserved (0);
+  SetIpv6Target (target);
+  m_checksum = 0;
+
+  /* test */
+  /*
+     m_reserved = 0xdeadbeef;
+   */
+}
+
+Icmpv6NS::~Icmpv6NS ()
+{
+}
+
+uint32_t Icmpv6NS::GetReserved () const
+{
+  return m_reserved;
+}
+
+void Icmpv6NS::SetReserved (uint32_t reserved)
+{
+  m_reserved = reserved;
+}
+
+Ipv6Address Icmpv6NS::GetIpv6Target () const
+{
+  return m_target;
+}
+
+void Icmpv6NS::SetIpv6Target (Ipv6Address target)
+{
+  m_target = target;
+}
+
+void Icmpv6NS::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " (NS) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << ")";
+}
+
+uint32_t Icmpv6NS::GetSerializedSize () const
+{
+  return 24;
+}
+
+void Icmpv6NS::Serialize (Buffer::Iterator start) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint8_t buff_target[16];
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteU16 (0);
+  i.WriteHtonU32 (m_reserved);
+  m_target.Serialize (buff_target);
+  i.Write (buff_target, 16);
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    checksum = i.CalculateIpChecksum (i.GetSize (), m_checksum);
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+uint32_t Icmpv6NS::Deserialize (Buffer::Iterator start)
+{
+  uint8_t buf[16];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  m_reserved = i.ReadNtohU32 ();
+  i.Read (buf, 16);
+  m_target.Set (buf);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6NA);
+
+TypeId Icmpv6NA::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6NA")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6NA> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6NA::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6NA::Icmpv6NA ()
+{
+  SetType (ICMPV6_ND_NEIGHBOR_ADVERTISEMENT);
+  SetCode (0);
+  SetReserved (0);
+  SetFlagR (0);
+  SetFlagS (0);
+  SetFlagO (0);
+  m_checksum = 0;
+}
+
+Icmpv6NA::~Icmpv6NA ()
+{
+}
+
+uint32_t Icmpv6NA::GetReserved () const
+{
+  return m_reserved;
+}
+
+void Icmpv6NA::SetReserved (uint32_t reserved)
+{
+  m_reserved = reserved;
+}
+
+Ipv6Address Icmpv6NA::GetIpv6Target () const
+{
+  return m_target;
+}
+
+bool Icmpv6NA::GetFlagR () const
+{
+  return m_flagR;
+}
+
+void Icmpv6NA::SetFlagR (bool r)
+{
+  m_flagR = r;
+}
+
+bool Icmpv6NA::GetFlagS () const
+{
+  return m_flagS;
+}
+
+void Icmpv6NA::SetFlagS (bool s)
+{
+  m_flagS = s;
+}
+
+bool Icmpv6NA::GetFlagO () const
+{
+  return m_flagO;
+}
+
+void Icmpv6NA::SetFlagO (bool o)
+{
+  m_flagO = o;
+}
+
+void Icmpv6NA::SetIpv6Target (Ipv6Address target)
+{
+  m_target = target;
+}
+
+void Icmpv6NA::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " (NA) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum () << ")";
+}
+
+uint32_t Icmpv6NA::GetSerializedSize () const
+{
+  return 24;
+}
+
+void Icmpv6NA::Serialize (Buffer::Iterator start) const
+{
+  uint8_t buff_target[16];
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+  uint32_t reserved = m_reserved;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteU16 (0);
+
+  if (m_flagR)
+  {
+    reserved |= (uint32_t)(1 << 31);
+  }
+
+  if (m_flagS)
+  {
+    reserved |= (uint32_t)(1<< 30);
+  }
+
+  if (m_flagO)
+  {
+    reserved |= (uint32_t)(1<< 29);
+  }
+
+  i.WriteHtonU32 (reserved);
+  m_target.Serialize (buff_target);
+  i.Write (buff_target, 16);
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+uint32_t Icmpv6NA::Deserialize (Buffer::Iterator start)
+{
+  uint8_t buf[16];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  m_reserved = i.ReadNtohU32 ();
+
+  m_flagR = false;
+  m_flagS = false;
+  m_flagO = false;
+
+  if (m_reserved & (1 << 31))
+  {
+    m_flagR = true;
+  }
+
+  if (m_reserved & (1 << 30))
+  {
+    m_flagS = true;
+  }
+
+  if (m_reserved & (1 << 29))
+  {
+    m_flagO = true;
+  }
+
+  i.Read (buf, 16);
+  m_target.Set (buf);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6RA);
+
+TypeId Icmpv6RA::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6RA")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6RA> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6RA::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6RA::Icmpv6RA ()
+{
+  SetType (ICMPV6_ND_ROUTER_ADVERTISEMENT);
+  SetCode (0);
+  SetFlags (0);
+  SetFlagM (0);
+  SetFlagO (0);
+  SetFlagH (0);
+  SetCurHopLimit (0);
+  SetLifeTime (0);
+  SetRetransmissionTime (0);
+  SetReachableTime (0);
+}
+
+Icmpv6RA::~Icmpv6RA ()
+{
+}
+
+void Icmpv6RA::SetCurHopLimit (uint8_t m)
+{
+  m_curHopLimit = m;
+}
+
+uint8_t Icmpv6RA::GetCurHopLimit () const
+{
+  return m_curHopLimit;
+}
+
+uint16_t Icmpv6RA::GetLifeTime () const
+{
+  return m_LifeTime;
+}
+
+uint32_t Icmpv6RA::GetReachableTime () const
+{
+  return m_ReachableTime;
+}
+
+uint32_t Icmpv6RA::GetRetransmissionTime () const
+{
+  return m_RetransmissionTimer;
+}
+
+void Icmpv6RA::SetLifeTime (uint16_t l)
+{
+  m_LifeTime = l;
+}
+
+void Icmpv6RA::SetReachableTime (uint32_t r)
+{
+  m_ReachableTime = r;
+}
+
+void Icmpv6RA::SetRetransmissionTime (uint32_t r)
+{
+  m_RetransmissionTimer = r;
+}
+
+bool Icmpv6RA::GetFlagM () const
+{
+  return m_flagM;
+}
+
+void Icmpv6RA::SetFlagM (bool m)
+{
+  m_flagM = m;
+}
+
+bool Icmpv6RA::GetFlagO () const
+{
+  return m_flagO;
+}
+
+void Icmpv6RA::SetFlagO (bool o)
+{
+  m_flagO = o;
+}
+
+bool Icmpv6RA::GetFlagH () const
+{
+  return m_flagH;
+}
+
+void Icmpv6RA::SetFlagH (bool h)
+{
+  m_flagH = h;
+}
+
+uint8_t Icmpv6RA::GetFlags () const
+{
+  return m_flags;
+}
+
+void Icmpv6RA::SetFlags (uint8_t f)
+{
+  m_flags = f;
+}
+
+void Icmpv6RA::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " (RA) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum () << ")";
+}
+
+uint32_t Icmpv6RA::GetSerializedSize () const
+{
+  return 16;
+}
+
+void Icmpv6RA::Serialize (Buffer::Iterator start) const
+{
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+  uint8_t flags = 0;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+  i.WriteU8 (m_curHopLimit);
+
+  if (m_flagM)
+  {
+    flags |= (uint8_t)(1<< 7);
+  }
+
+  if (m_flagO)
+  {
+    flags |= (uint8_t)(1<< 6);
+  }
+
+  if (m_flagH)
+  {
+    flags |= (uint8_t)(1<< 5);
+  }
+  i.WriteU8 (flags);
+  i.WriteHtonU16 (GetLifeTime ());
+  i.WriteHtonU32 (GetReachableTime ());
+  i.WriteHtonU32 (GetRetransmissionTime ());
+
+  i = start;
+  checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+  i = start;
+  i.Next (2);
+  i.WriteU16 (checksum);
+}
+
+uint32_t Icmpv6RA::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  SetCurHopLimit (i.ReadU8 ());
+  m_flags = i.ReadU8 ();
+  m_flagM = false;
+  m_flagO = false;
+  m_flagH = false;
+
+  if (m_flags & (1 << 7))
+  {
+    m_flagM = true;
+  }
+
+  if (m_flags & (1 << 6))
+  {
+    m_flagO = true;
+  }
+
+  if (m_flags & (1 << 5))
+  {
+    m_flagH = true;
+  }
+  SetLifeTime (i.ReadNtohU16 ());
+  SetReachableTime (i.ReadNtohU32 ());
+  SetRetransmissionTime (i.ReadNtohU32 ());
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6RS);
+
+TypeId Icmpv6RS::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6RS")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6RS> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6RS::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6RS::Icmpv6RS ()
+{
+  SetType (ICMPV6_ND_ROUTER_SOLICITATION);
+  SetCode (0);
+  SetReserved (0);
+}
+
+Icmpv6RS::~Icmpv6RS ()
+{
+}
+
+uint32_t Icmpv6RS::GetReserved () const
+{
+  return m_reserved;
+}
+
+void Icmpv6RS::SetReserved (uint32_t reserved)
+{
+  m_reserved = reserved;
+}
+
+void Icmpv6RS::Print (std::ostream& os)
+{
+  os << "( type = " << (uint32_t)GetType () << " (RS) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << ")";
+}
+
+uint32_t Icmpv6RS::GetSerializedSize () const
+{
+  return 8;
+}
+
+void Icmpv6RS::Serialize (Buffer::Iterator start) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteU16 (0);
+  i.WriteHtonU32 (m_reserved);
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+  
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+uint32_t Icmpv6RS::Deserialize (Buffer::Iterator start)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  m_reserved = i.ReadNtohU32 ();
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6Redirection);
+
+TypeId Icmpv6Redirection::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6Redirection")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6Redirection> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6Redirection::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6Redirection::Icmpv6Redirection ()
+  : m_target (Ipv6Address ("")),
+  m_destination (Ipv6Address ("")),
+  m_reserved (0)
+{
+  SetType (ICMPV6_ND_REDIRECTION);
+  SetCode (0);
+  m_checksum = 0;
+}
+
+Icmpv6Redirection::~Icmpv6Redirection ()
+{
+}
+
+void Icmpv6Redirection::SetReserved (uint32_t reserved)
+{
+  m_reserved = reserved;
+}
+
+uint32_t Icmpv6Redirection::GetReserved () const
+{
+  return m_reserved;
+}
+
+Ipv6Address Icmpv6Redirection::GetTarget () const
+{
+  return m_target;
+}
+
+void Icmpv6Redirection::SetTarget (Ipv6Address target)
+{
+  m_target = target;
+}
+
+Ipv6Address Icmpv6Redirection::GetDestination () const
+{
+  return m_destination;
+}
+
+void Icmpv6Redirection::SetDestination (Ipv6Address destination)
+{
+  m_destination = destination;
+}
+
+void Icmpv6Redirection::Print (std::ostream& os)
+{
+  os << "( type = " << (uint32_t)GetType () << " (Redirection) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << " target = " << m_target << " destination = " << m_destination << ")";
+}
+
+uint32_t Icmpv6Redirection::GetSerializedSize () const 
+{
+  return 40;
+}
+
+void Icmpv6Redirection::Serialize (Buffer::Iterator start) const 
+{
+  uint8_t buff[16];
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteU16 (checksum);
+  i.WriteU32 (m_reserved);
+
+  m_target.Serialize (buff);
+  i.Write (buff, 16);
+
+  m_destination.Serialize (buff);
+  i.Write (buff, 16);
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+uint32_t Icmpv6Redirection::Deserialize (Buffer::Iterator start) 
+{
+  uint8_t buff[16];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  SetReserved (i.ReadU32 ());
+
+  i.Read (buff, 16);
+  m_target.Set (buff);
+
+  i.Read (buff, 16);
+  m_destination.Set (buff);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6Echo);
+
+TypeId Icmpv6Echo::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6Echo")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6Echo> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6Echo::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6Echo::Icmpv6Echo ()
+{
+  SetType (Icmpv6Header::ICMPV6_ECHO_REQUEST);
+  SetCode (0);
+  m_checksum = 0;
+  SetId (0);
+  SetSeq (0);
+}
+
+Icmpv6Echo::Icmpv6Echo (bool request)
+{
+  SetType (request ? Icmpv6Header::ICMPV6_ECHO_REQUEST : Icmpv6Header::ICMPV6_ECHO_REPLY);
+  SetCode (0);
+  m_checksum = 0;
+  SetId (0);
+  SetSeq (0);
+}
+
+Icmpv6Echo::~Icmpv6Echo ()
+{
+}
+
+uint16_t Icmpv6Echo::GetId () const
+{
+  return m_id;
+}
+
+void Icmpv6Echo::SetId (uint16_t id)
+{
+  m_id = id;
+}
+
+uint16_t Icmpv6Echo::GetSeq () const
+{
+  return m_seq;
+}
+
+void Icmpv6Echo::SetSeq (uint16_t seq)
+{
+  m_seq = seq;
+}
+
+void Icmpv6Echo::Print (std::ostream& os) const
+{
+  os << "( type = " << (GetType () == 128 ? "128 (Request)" : "129 (Reply)") << 
+    " code = " << (uint32_t)GetCode () << 
+    " checksum = "  << (uint32_t)GetChecksum () << ")";
+}
+
+uint32_t Icmpv6Echo::GetSerializedSize () const
+{
+  return 8; 
+}
+
+void Icmpv6Echo::Serialize (Buffer::Iterator start) const
+{
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+
+  i.WriteHtonU16 (m_id);
+  i.WriteHtonU16 (m_seq);
+
+  if (m_calcChecksum)
+  {
+    i = start;
+    checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+    i = start;
+    i.Next (2);
+    i.WriteU16 (checksum);
+  }
+}
+
+uint32_t Icmpv6Echo::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+
+  m_id = i.ReadNtohU16 ();
+  m_seq = i.ReadNtohU16 ();
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6DestinationUnreachable);
+
+TypeId Icmpv6DestinationUnreachable::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6DestinationUnreachable")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6DestinationUnreachable> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6DestinationUnreachable::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6DestinationUnreachable::Icmpv6DestinationUnreachable ()
+  : m_packet (0)
+{
+  SetType (ICMPV6_ERROR_DESTINATION_UNREACHABLE);
+}
+
+Icmpv6DestinationUnreachable::~Icmpv6DestinationUnreachable ()
+{
+}
+
+Ptr<Packet> Icmpv6DestinationUnreachable::GetPacket () const
+{
+  return m_packet;
+}
+
+void Icmpv6DestinationUnreachable::SetPacket (Ptr<Packet> p)
+{
+  NS_ASSERT (p->GetSize () <= 1280);
+  m_packet = p;
+}
+
+void Icmpv6DestinationUnreachable::Print (std::ostream& os)
+{
+  os << "( type = " << (uint32_t)GetType () << " (Destination Unreachable) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << ")";
+}
+
+uint32_t Icmpv6DestinationUnreachable::GetSerializedSize () const
+{
+  return 8 + m_packet->GetSize ();
+}
+
+void Icmpv6DestinationUnreachable::Serialize (Buffer::Iterator start) const
+{
+  const uint8_t *packet = m_packet->PeekData ();
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+  i.WriteHtonU32 (0);
+
+  i.Write (packet, m_packet->GetSize ());
+
+  i = start;
+  checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+  i = start;
+  i.Next (2);
+  i.WriteU16 (checksum);
+}
+
+uint32_t Icmpv6DestinationUnreachable::Deserialize (Buffer::Iterator start)
+{
+  uint16_t length = start.GetSize () - 8;
+  uint8_t data[length];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  i.ReadNtohU32 ();
+  i.Read (data, length);
+  m_packet = Create<Packet> (data, length);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6TooBig);
+
+TypeId Icmpv6TooBig::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6TooBig")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6TooBig> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6TooBig::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6TooBig::Icmpv6TooBig ()
+  : m_packet (0),
+  m_mtu (0)
+{
+  SetType (ICMPV6_ERROR_PACKET_TOO_BIG);
+}
+
+Icmpv6TooBig::~Icmpv6TooBig ()
+{
+}
+
+Ptr<Packet> Icmpv6TooBig::GetPacket () const
+{
+  return m_packet;
+}
+
+void Icmpv6TooBig::SetPacket (Ptr<Packet> p)
+{
+  NS_ASSERT (p->GetSize () <= 1280);
+  m_packet = p;
+}
+
+uint32_t Icmpv6TooBig::GetMtu () const
+{
+  return m_mtu;
+}
+
+void Icmpv6TooBig::SetMtu (uint32_t mtu) 
+{
+  m_mtu = mtu;
+}
+
+void Icmpv6TooBig::Print (std::ostream& os) 
+{
+  os << "( type = " << (uint32_t)GetType () << " (Too Big) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum () << " mtu = " << (uint32_t)GetMtu () << ")";
+}
+
+uint32_t Icmpv6TooBig::GetSerializedSize () const 
+{
+  return 8 + m_packet->GetSize ();
+}
+
+void Icmpv6TooBig::Serialize (Buffer::Iterator start) const
+{
+  const uint8_t *packet = m_packet->PeekData ();
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+  i.WriteHtonU32 (GetMtu ());
+
+  i.Write (packet, m_packet->GetSize ());
+
+  i = start;
+  checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+  i = start;
+  i.Next (2);
+  i.WriteU16 (checksum);
+}
+
+uint32_t Icmpv6TooBig::Deserialize (Buffer::Iterator start) 
+{
+  uint16_t length = start.GetSize () - 8;
+  uint8_t data[length];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  SetMtu (i.ReadNtohU32 ());
+  i.Read (data, length);
+  m_packet = Create<Packet> (data, length);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6TimeExceeded);
+
+TypeId Icmpv6TimeExceeded::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6TimeExceeded")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6TimeExceeded> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6TimeExceeded::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6TimeExceeded::Icmpv6TimeExceeded ()
+  : m_packet (0)
+{
+  SetType (ICMPV6_ERROR_TIME_EXCEEDED);
+}
+
+Icmpv6TimeExceeded::~Icmpv6TimeExceeded ()
+{
+}
+
+Ptr<Packet> Icmpv6TimeExceeded::GetPacket () const 
+{
+  return m_packet;
+}
+
+void Icmpv6TimeExceeded::SetPacket (Ptr<Packet> p) 
+{
+  NS_ASSERT (p->GetSize () <= 1280);
+  m_packet = p;
+}
+
+void Icmpv6TimeExceeded::Print (std::ostream& os) 
+{
+  os << "( type = " << (uint32_t)GetType () << " (Destination Unreachable) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << ")";
+}
+
+uint32_t Icmpv6TimeExceeded::GetSerializedSize () const
+{
+  return 8 + m_packet->GetSize ();
+}
+
+void Icmpv6TimeExceeded::Serialize (Buffer::Iterator start) const
+{
+  const uint8_t *packet = m_packet->PeekData ();
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+  i.WriteHtonU32 (0);
+
+  i.Write (packet, m_packet->GetSize ());
+
+  i = start;
+  checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+  i = start;
+  i.Next (2);
+  i.WriteU16 (checksum);
+}
+
+uint32_t Icmpv6TimeExceeded::Deserialize (Buffer::Iterator start)
+{
+  uint16_t length = start.GetSize () - 8;
+  uint8_t data[length];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  i.ReadNtohU32 ();
+  i.Read (data, length);
+  m_packet = Create<Packet> (data, length);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6ParameterError);
+
+TypeId Icmpv6ParameterError::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6ParameterError")
+    .SetParent<Icmpv6Header> ()
+    .AddConstructor<Icmpv6ParameterError> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6ParameterError::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6ParameterError::Icmpv6ParameterError ()
+  : m_packet (0),
+    m_ptr (0)
+{
+  SetType (ICMPV6_ERROR_PARAMETER_ERROR);
+}
+
+Icmpv6ParameterError::~Icmpv6ParameterError ()
+{
+}
+
+Ptr<Packet> Icmpv6ParameterError::GetPacket () const
+{
+  return m_packet;
+}
+
+void Icmpv6ParameterError::SetPacket (Ptr<Packet> p)
+{
+  NS_ASSERT (p->GetSize () <= 1280);
+  m_packet = p;
+}
+
+uint32_t Icmpv6ParameterError::GetPtr () const
+{
+  return m_ptr;
+}
+
+void Icmpv6ParameterError::SetPtr (uint32_t ptr) 
+{
+  m_ptr = ptr;
+}
+
+void Icmpv6ParameterError::Print (std::ostream& os)
+{
+  os << "( type = " << (uint32_t)GetType () << " (Destination Unreachable) code = " << (uint32_t)GetCode () << " checksum = " << (uint32_t)GetChecksum ()  << " ptr = " << (uint32_t)GetPtr () << ")";
+}
+
+uint32_t Icmpv6ParameterError::GetSerializedSize () const 
+{
+  return 8 + m_packet->GetSize ();
+}
+
+void Icmpv6ParameterError::Serialize (Buffer::Iterator start) const 
+{
+  const uint8_t *packet = m_packet->PeekData ();
+  uint16_t checksum = 0;
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetCode ());
+  i.WriteHtonU16 (0);
+  i.WriteHtonU32 (GetPtr ());
+
+  i.Write (packet, m_packet->GetSize ());
+
+  i = start;
+  checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ());
+
+  i = start;
+  i.Next (2);
+  i.WriteU16 (checksum);
+}
+
+uint32_t Icmpv6ParameterError::Deserialize (Buffer::Iterator start) 
+{
+  uint16_t length = start.GetSize () - 8;
+  uint8_t data[length];
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetCode (i.ReadU8 ());
+  m_checksum = i.ReadU16 ();
+  SetPtr (i.ReadNtohU32 ());
+  i.Read (data, length);
+  m_packet = Create<Packet> (data, length);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionHeader);
+
+TypeId Icmpv6OptionHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6OptionHeader")
+    .SetParent<Header> ()
+    .AddConstructor<Icmpv6OptionHeader> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6OptionHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+
+Icmpv6OptionHeader::Icmpv6OptionHeader ()
+{
+  /* TODO */
+  m_type = 0;
+  m_len = 0;
+}
+
+Icmpv6OptionHeader::~Icmpv6OptionHeader ()
+{
+}
+
+uint8_t Icmpv6OptionHeader::GetType () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_type;
+}
+
+void Icmpv6OptionHeader::SetType (uint8_t type)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_type = type;
+}
+
+uint8_t Icmpv6OptionHeader::GetLength () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_len;
+}
+
+void Icmpv6OptionHeader::SetLength (uint8_t len)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_len = len;
+}
+
+void Icmpv6OptionHeader::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << ")";
+}
+
+uint32_t Icmpv6OptionHeader::GetSerializedSize () const
+{
+  return m_len*8;
+}
+
+uint32_t Icmpv6OptionHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  return GetSerializedSize ();
+}
+
+void Icmpv6OptionHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionMtu);
+
+TypeId Icmpv6OptionMtu::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6OptionMtu")
+    .SetParent<Icmpv6OptionHeader> ()
+    .AddConstructor<Icmpv6OptionMtu> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6OptionMtu::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6OptionMtu::Icmpv6OptionMtu ()
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_MTU);
+  SetLength (1);
+  SetReserved (0);
+}
+
+Icmpv6OptionMtu::Icmpv6OptionMtu (uint32_t mtu)
+  : m_mtu (mtu)
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_MTU);
+  SetLength (1);
+  SetReserved (0);
+}
+
+Icmpv6OptionMtu::~Icmpv6OptionMtu ()
+{
+}
+
+uint16_t Icmpv6OptionMtu::GetReserved () const
+{
+  return m_reserved;
+}
+
+void Icmpv6OptionMtu::SetReserved (uint16_t reserved)
+{
+  m_reserved = reserved;
+}
+
+uint32_t Icmpv6OptionMtu::GetMtu () const
+{
+  return m_mtu;
+}
+
+void Icmpv6OptionMtu::SetMtu (uint32_t mtu)
+{
+  m_mtu = mtu;
+}
+
+void Icmpv6OptionMtu::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " MTU = " << m_mtu << ")";
+}
+
+uint32_t Icmpv6OptionMtu::GetSerializedSize () const
+{
+  return 8; /* m_len = 1 so the real size is multiple by 8 */
+}
+
+void Icmpv6OptionMtu::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteHtonU16 (GetReserved ());
+  i.WriteHtonU32 (GetMtu ());
+}
+
+uint32_t Icmpv6OptionMtu::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  SetReserved (i.ReadNtohU16 ());
+  SetMtu (i.ReadNtohU32 ());
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionPrefixInformation);
+
+TypeId Icmpv6OptionPrefixInformation::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6OptionPrefixInformation")
+    .SetParent<Icmpv6OptionHeader> ()
+    .AddConstructor<Icmpv6OptionPrefixInformation> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6OptionPrefixInformation::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6OptionPrefixInformation::Icmpv6OptionPrefixInformation ()
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_PREFIX);
+  SetLength (4);
+  SetPrefix (Ipv6Address ("::"));
+  SetPrefixLength (0);
+  SetValidTime (0);
+  SetPreferredTime (0);
+  SetFlags (0);
+  SetReserved (0);
+}
+
+Icmpv6OptionPrefixInformation::Icmpv6OptionPrefixInformation (Ipv6Address prefix, uint8_t prefixlen)
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_PREFIX);
+  SetLength (4);
+  SetPrefix (prefix);
+  SetPrefixLength (prefixlen);
+  SetValidTime (0);
+  SetPreferredTime (0);
+  SetFlags (0);
+  SetReserved (0);
+}
+
+Icmpv6OptionPrefixInformation::~Icmpv6OptionPrefixInformation ()
+{
+}
+
+uint8_t Icmpv6OptionPrefixInformation::GetPrefixLength () const
+{
+  return m_prefixLength;
+}
+
+void Icmpv6OptionPrefixInformation::SetPrefixLength (uint8_t prefixLength)
+{
+  NS_ASSERT (prefixLength <= 128);
+  m_prefixLength = prefixLength;
+}
+
+uint8_t Icmpv6OptionPrefixInformation::GetFlags () const
+{
+  return m_flags;
+}
+
+void Icmpv6OptionPrefixInformation::SetFlags (uint8_t flags)
+{
+  m_flags = flags;
+}
+
+uint32_t Icmpv6OptionPrefixInformation::GetValidTime () const
+{
+  return m_validTime;
+}
+
+void Icmpv6OptionPrefixInformation::SetValidTime (uint32_t validTime)
+{
+  m_validTime = validTime;
+}
+
+uint32_t Icmpv6OptionPrefixInformation::GetPreferredTime () const
+{
+  return m_preferredTime;
+}
+
+void Icmpv6OptionPrefixInformation::SetPreferredTime (uint32_t preferredTime)
+{
+  m_preferredTime = preferredTime;
+}
+
+uint32_t Icmpv6OptionPrefixInformation::GetReserved () const
+{
+  return m_preferredTime;
+}
+
+void Icmpv6OptionPrefixInformation::SetReserved (uint32_t reserved)
+{
+  m_reserved = reserved;
+}
+
+Ipv6Address Icmpv6OptionPrefixInformation::GetPrefix () const
+{
+  return m_prefix;
+}
+
+void Icmpv6OptionPrefixInformation::SetPrefix (Ipv6Address prefix)
+{
+  m_prefix = prefix;
+}
+
+void Icmpv6OptionPrefixInformation::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " prefix " << m_prefix << ")";
+}
+
+uint32_t Icmpv6OptionPrefixInformation::GetSerializedSize () const
+{
+  return 32;
+}
+
+void Icmpv6OptionPrefixInformation::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  uint8_t buf[16];
+
+  memset (buf, 0x00, sizeof (buf));
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (m_prefixLength);
+  i.WriteU8 (m_flags);
+  i.WriteHtonU32 (m_validTime);
+  i.WriteHtonU32 (m_preferredTime);
+  i.WriteHtonU32 (m_reserved);
+  m_prefix.GetBytes (buf);
+  i.Write (buf, 16);
+}
+
+uint32_t Icmpv6OptionPrefixInformation::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t buf[16];
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  SetPrefixLength (i.ReadU8 ());
+  SetFlags (i.ReadU8 ());
+  SetValidTime (i.ReadNtohU32 ());
+  SetPreferredTime (i.ReadNtohU32 ());
+  SetReserved (i.ReadNtohU32 ());
+  i.Read (buf, 16);
+
+  Ipv6Address prefix (buf);
+  SetPrefix (prefix);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionLinkLayerAddress);
+
+TypeId Icmpv6OptionLinkLayerAddress::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6OptionLinkLayerAddress")
+    .SetParent<Icmpv6OptionHeader> ()
+    .AddConstructor<Icmpv6OptionLinkLayerAddress> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6OptionLinkLayerAddress::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6OptionLinkLayerAddress::Icmpv6OptionLinkLayerAddress (bool source)
+{
+  SetType (source ? Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE : Icmpv6Header::ICMPV6_OPT_LINK_LAYER_TARGET);
+}
+
+Icmpv6OptionLinkLayerAddress::Icmpv6OptionLinkLayerAddress ()
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE);
+}
+
+Icmpv6OptionLinkLayerAddress::Icmpv6OptionLinkLayerAddress (bool source, Address addr)
+{
+  SetType (source ? Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE : Icmpv6Header::ICMPV6_OPT_LINK_LAYER_TARGET);
+  SetAddress (addr);
+  SetLength (GetSerializedSize () / 8);
+}
+
+Icmpv6OptionLinkLayerAddress::~Icmpv6OptionLinkLayerAddress ()
+{
+}
+
+Address Icmpv6OptionLinkLayerAddress::GetAddress () const
+{
+  return m_addr;
+}
+
+void Icmpv6OptionLinkLayerAddress::SetAddress (Address addr)
+{
+  m_addr = addr;
+}
+
+void Icmpv6OptionLinkLayerAddress::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " L2 Address = " << m_addr << ")";
+}
+
+uint32_t Icmpv6OptionLinkLayerAddress::GetSerializedSize () const
+{
+  /* TODO add padding */
+  uint8_t nb = 2 + m_addr.GetLength ();
+  return nb;
+}
+
+void Icmpv6OptionLinkLayerAddress::Serialize (Buffer::Iterator start) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Buffer::Iterator i = start;
+  uint8_t mac[32];
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  m_addr.CopyTo (mac);
+  i.Write (mac, m_addr.GetLength ());
+
+  /* XXX if size of the option is not a multiple of 8, add padding */
+}
+
+uint32_t Icmpv6OptionLinkLayerAddress::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t mac[32];
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  i.Read (mac, (GetLength () * 8) - 2);
+
+  m_addr.CopyFrom (mac, (GetLength () * 8)-2);
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionRedirected);
+
+TypeId Icmpv6OptionRedirected::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6OptionRedirected")
+    .SetParent<Icmpv6OptionHeader> ()
+    .AddConstructor<Icmpv6OptionRedirected> ()
+    ;
+  return tid;
+}
+
+TypeId Icmpv6OptionRedirected::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+Icmpv6OptionRedirected::Icmpv6OptionRedirected ()
+  : m_packet (0)
+{
+  SetType (Icmpv6Header::ICMPV6_OPT_REDIRECTED);
+}
+
+Icmpv6OptionRedirected::~Icmpv6OptionRedirected ()
+{
+  m_packet = 0;
+}
+
+Ptr<Packet> Icmpv6OptionRedirected::GetPacket () const
+{
+  return m_packet;
+}
+
+void Icmpv6OptionRedirected::SetPacket (Ptr<Packet> packet)
+{
+  NS_ASSERT (packet->GetSize () <= 1280);
+  m_packet = packet;
+  SetLength (1 + (m_packet->GetSize () / 8));
+}
+
+void Icmpv6OptionRedirected::Print (std::ostream& os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << ")";
+}
+
+uint32_t Icmpv6OptionRedirected::GetSerializedSize () const
+{
+  return 8 + m_packet->GetSize ();
+}
+
+void Icmpv6OptionRedirected::Serialize (Buffer::Iterator start) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  // Reserved
+  i.WriteU16 (0);
+  i.WriteU32 (0);
+
+  i.Write (m_packet->PeekData (), m_packet->GetSize ());
+}
+
+uint32_t Icmpv6OptionRedirected::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  uint8_t length = i.ReadU8 ();
+  SetLength (length);
+  i.ReadU16 ();
+  i.ReadU32 ();
+
+  uint32_t len2 = (GetLength () - 1) * 8;
+  uint8_t buff[len2];
+  i.Read (buff, len2);
+  m_packet = Create<Packet> (buff, len2);
+
+  return GetSerializedSize ();
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv6-header.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1785 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ *         David Gross <gdavid.devel@gmail.com>
+ */
+
+#ifndef ICMPV6_HEADER_H
+#define ICMPV6_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/packet.h"
+
+namespace ns3
+{
+
+/**
+ * \class Icmpv6Header
+ * \brief ICMPv6 header.
+ */
+class Icmpv6Header : public Header
+{
+  public:
+    /**
+     * \enum Type_e
+     * \brief ICMPv6 type code.
+     */
+    enum Type_e
+    {
+      ICMPV6_ERROR_DESTINATION_UNREACHABLE = 1,
+      ICMPV6_ERROR_PACKET_TOO_BIG,
+      ICMPV6_ERROR_TIME_EXCEEDED,
+      ICMPV6_ERROR_PARAMETER_ERROR,
+      ICMPV6_ECHO_REQUEST=128,
+      ICMPV6_ECHO_REPLY,
+      ICMPV6_SUBSCRIBE_REQUEST,
+      ICMPV6_SUBSCRIBE_REPORT,
+      ICMPV6_SUBSCRIVE_END,
+      ICMPV6_ND_ROUTER_SOLICITATION,
+      ICMPV6_ND_ROUTER_ADVERTISEMENT,
+      ICMPV6_ND_NEIGHBOR_SOLICITATION,
+      ICMPV6_ND_NEIGHBOR_ADVERTISEMENT,
+      ICMPV6_ND_REDIRECTION,
+      ICMPV6_ROUTER_RENUMBER,
+      ICMPV6_INFORMATION_REQUEST,
+      ICMPV6_INFORMATION_RESPONSE,
+      ICMPV6_INVERSE_ND_SOLICITATION,
+      ICMPV6_INVERSE_ND_ADVERSTISEMENT,
+      ICMPV6_MLDV2_SUBSCRIBE_REPORT,
+      ICMPV6_MOBILITY_HA_DISCOVER_REQUEST,
+      ICMPV6_MOBILITY_HA_DISCOVER_RESPONSE,
+      ICMPV6_MOBILITY_MOBILE_PREFIX_SOLICITATION,
+      ICMPV6_SECURE_ND_CERTIFICATE_PATH_SOLICITATION,
+      ICMPV6_SECURE_ND_CERTIFICATE_PATH_ADVERTISEMENT,
+      ICMPV6_EXPERIMENTAL_MOBILITY
+    };
+
+    /**
+     * \enum OptionType_e
+     * \brief ICMPv6 Option type code.
+     */
+    enum OptionType_e
+    {
+      ICMPV6_OPT_LINK_LAYER_SOURCE = 1,
+      ICMPV6_OPT_LINK_LAYER_TARGET,
+      ICMPV6_OPT_PREFIX,
+      ICMPV6_OPT_REDIRECTED,
+      ICMPV6_OPT_MTU
+    };
+
+    /**
+     * \enum ErrorDestinationUnreachable_e
+     * \brief ICMPv6 error code : Destination Unreachable
+     */
+    enum ErrorDestinationUnreachable_e
+    {
+      ICMPV6_NO_ROUTE = 0,
+      ICMPV6_ADM_PROHIBITED,
+      ICMPV6_NOT_NEIGHBOUR,
+      ICMPV6_ADDR_UNREACHABLE,
+      ICMPV6_PORT_UNREACHABLE
+    };
+
+    /**
+     * \enum ErrorTimeExceeded_e
+     * \brief ICMPv6 error code : Time Exceeded
+     */
+    enum ErrorTimeExceeded_e
+    {
+      ICMPV6_HOPLIMIT = 0,
+      ICMPV6_FRAGTIME
+    };
+
+    /**
+     * \enum ErrorParameterError_e
+     * \brief ICMPv6 error code : Parameter Error
+     */
+    enum ErrorParameterError_e
+    {
+      ICMPV6_MALFORMED_HEADER = 0,
+      ICMPV6_UNKNOWN_NEXT_HEADER,
+      ICMPV6_UNKNOWN_OPTION
+    };
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6Header ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6Header ();
+
+    /**
+     * \brief Get the type field.
+     * \return type of ICMPv6 message
+     */
+    uint8_t GetType () const;
+
+    /**
+     * \brief Set the type.
+     * \param type type to set
+     */
+    void SetType (uint8_t type);
+
+    /**
+     * \brief Get the code field.
+     * \return code of ICMPv6 message
+     */
+    uint8_t GetCode () const;
+
+    /**
+     * \brief Set the code field.
+     * \param code code to set
+     */
+    void SetCode (uint8_t code);
+
+    /**
+     * \brief Get the checksum.
+     * \return checksum
+     */
+    uint16_t GetChecksum () const;
+
+    /**
+     * \brief Set the checksum.
+     * \param checksum to set
+     */
+    void SetChecksum (uint16_t checksum);
+    
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+    /**
+     * \brief Calculate pseudo header checksum for IPv6.
+     * \param src source address
+     * \param dst destination address
+     * \param length length
+     * \param protocol the protocol number to use in the
+     * underlying IPv6 packet.
+     */
+    void CalculatePseudoHeaderChecksum (Ipv6Address src, Ipv6Address dst, uint16_t length, uint8_t protocol);
+
+  protected:
+    /**
+     * \brief Checksum enable or not.
+     */
+    bool m_calcChecksum;
+
+    /**
+     * \brief The checksum.
+     */
+    uint16_t m_checksum; 
+  
+  private:
+    /**
+     * \brief The type.
+     */
+    uint8_t m_type;
+
+    /**
+     * \brief The code.
+     */
+    uint8_t m_code;
+};
+
+/**
+ * \class Icmpv6OptionHeader
+ * \brief ICMPv6 option header.
+ */
+class Icmpv6OptionHeader : public Header
+{
+  public:
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6OptionHeader ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6OptionHeader ();
+
+    /**
+     * \brief Get the type of the option.
+     * \return type
+     */
+    uint8_t GetType () const;
+
+    /**
+     * \brief Set the type of the option.
+     * \param type the type to set
+     */
+    void SetType (uint8_t type);
+
+    /**
+     * \brief Get the length of the option in 8 bytes unit.
+     * \return length of the option
+     */
+    uint8_t GetLength () const;
+
+    /**
+     * \brief Set the length of the option.
+     * \param len length value to set
+     */
+    void SetLength (uint8_t len);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The type.
+     */
+    uint8_t m_type;
+
+    /**
+     * \brief The length.
+     */
+    uint8_t m_len;
+};
+
+/**
+ * \class Icmpv6NS
+ * \brief ICMPv6 Neighbor Solicitation header.
+ */
+class Icmpv6NS : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param target target IPv6 address
+     */
+    Icmpv6NS (Ipv6Address target);
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6NS ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6NS ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the reserved field.
+     * \return reserved value
+     */
+    uint32_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field.
+     * \param reserved the reserved value
+     */
+    void SetReserved (uint32_t reserved);
+
+    /**
+     * \brief Get the IPv6 target field.
+     * \return IPv6 address
+     */
+    Ipv6Address GetIpv6Target () const;
+
+    /**
+     * \brief Set the IPv6 target field.
+     * \param target IPv6 address
+     */
+    void SetIpv6Target (Ipv6Address target);
+
+    /**
+     * \brief Get the IPv6 target field.
+     * \return IPv6 address
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+
+    /**
+     * \brief The reserved value.
+     */
+    uint32_t m_reserved;
+
+    /**
+     * \brief The IPv6 target address.
+     */
+    Ipv6Address m_target;
+};
+
+/**
+ * \class Icmpv6NA
+ * \brief ICMPv6 Neighbor Advertisement header.
+ */
+class Icmpv6NA : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6NA ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6NA ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the reserved field.
+     * \return reserved value
+     */
+    uint32_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field.
+     * \param reserved the reserved value
+     */
+    void SetReserved (uint32_t reserved);
+
+    /**
+     * \brief Get the IPv6 target field.
+     * \return IPv6 address
+     */
+    Ipv6Address GetIpv6Target () const;
+
+    /**
+     * \brief Set the IPv6 target field.
+     * \param target IPv6 address
+     */
+    void SetIpv6Target (Ipv6Address target);
+
+    /**
+     * \brief Get the R flag.
+     * \return R flag
+     */
+    bool GetFlagR () const;
+
+    /**
+     * \brief Set the R flag.
+     * \param r value
+     */
+    void SetFlagR (bool r);
+
+    /**
+     * \brief Get the S flag.
+     * \return S flag
+     */
+    bool GetFlagS () const;
+
+    /**
+     * \brief Set the S flag.
+     * \param s value
+     */
+    void SetFlagS (bool s);
+
+    /**
+     * \brief Get the O flag.
+     * \return O flag
+     */
+    bool GetFlagO () const;
+
+    /**
+     * \brief Set the O flag.
+     * \param o value
+     */
+    void SetFlagO (bool o);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The R flag.
+     */
+    bool m_flagR;
+
+    /**
+     * \brief The O flag.
+     */
+    bool m_flagS;
+
+    /**
+     * \brief The M flag.
+     */
+    bool m_flagO;
+
+    /**
+     * \brief The reserved value.
+     */
+    uint32_t m_reserved;
+
+    /**
+     * \brief The IPv6 target address.
+     */
+    Ipv6Address m_target;
+};
+
+/**
+ * \class Icmpv6RA
+ * \brief ICMPv6 Router Advertisement header.
+ */
+class Icmpv6RA : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6RA ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6RA ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Set the IPv6 maximum number of jumps.
+     * \param m maximum jumps
+     */
+    void SetCurHopLimit (uint8_t m);
+
+    /**
+     * \brief Get the IPv6 maximum number of jumps.
+     * \return maximum jumps
+     */
+    uint8_t GetCurHopLimit () const;
+
+    /**
+     * \brief Set the node Life time (Neighbor Discovery).
+     * \param l life time
+     */
+    void SetLifeTime (uint16_t l);
+
+    /**
+     * \brief Get the node Life time (Neighbor Discovery).
+     * \return life time
+     */
+    uint16_t GetLifeTime () const;
+
+    /**
+     * \brief Set the node Reachable time (Neighbor Discovery).
+     * \param r Reachable time
+     */
+    void SetReachableTime (uint32_t r);
+
+    /**
+     * \brief Get the node Reachable time (Neighbor Discovery).
+     * \return reachable time
+     */
+    uint32_t GetReachableTime () const;
+
+    /**
+     * \brief Set the node Retransmission time (Neighbor Discovery).
+     * \param r Retransmission time
+     */
+    void SetRetransmissionTime (uint32_t r);
+
+    /**
+     * \brief Get the node Retransmission time (Neighbor Discovery).
+     * \return retransmission time
+     */
+    uint32_t GetRetransmissionTime () const;
+
+    /**
+     * \brief Get the M flag.
+     * \return M flag
+     */
+    bool GetFlagM () const;
+
+    /**
+     * \brief Set the M flag.
+     * \param m value
+     */
+    void SetFlagM (bool m);
+
+    /**
+     * \brief Get the O flag.
+     * \return O flag
+     */
+    bool GetFlagO () const;
+
+    /**
+     * \brief Set the O flag.
+     * \param o value
+     */
+    void SetFlagO (bool o);
+
+    /**
+     * \brief Get the H flag.
+     * \return H flag
+     */
+    bool GetFlagH () const;
+
+    /**
+     * \brief Set the H flag.
+     * \param h value
+     */
+    void SetFlagH (bool h);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Getflags.
+     * \return the flags value
+     */
+    uint8_t GetFlags () const;
+
+    /**
+     * \brief Setflags.
+     * \param f the flags value
+     */
+    void SetFlags (uint8_t f);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The M flag.
+     */
+    bool m_flagM;
+
+    /**
+     * \brief The O flag.
+     */
+    bool m_flagO;
+
+    /**
+     * \brief The H flag.
+     */
+    bool m_flagH;
+
+    /**
+     * \brief The flags field value.
+     */
+    uint8_t m_flags;
+
+    /**
+     * \brief The lifetime value.
+     */
+    uint16_t m_LifeTime;
+
+    /**
+     * \brief The reachable time value.
+     */
+    uint32_t m_ReachableTime;
+
+    /**
+     * \brief The retransmission timer.
+     */
+    uint32_t m_RetransmissionTimer;
+
+    /**
+     * \brief The max jumps.
+     */
+    uint8_t m_curHopLimit;
+};
+
+/**
+ * \class Icmpv6RS
+ * \brief ICMPv6 Router Solicitation header.
+ */
+class Icmpv6RS : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6RS ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6RS ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the reserved field.
+     * \return reserved value
+     */
+    uint32_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field.
+     * \param reserved the reserved value
+     */
+    void SetReserved (uint32_t reserved);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The reserved value.
+     */
+    uint32_t m_reserved;
+};
+
+/**
+ * \class Icmpv6Redirection
+ * \brief ICMPv6 Redirection header.
+ */
+class Icmpv6Redirection : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6Redirection ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6Redirection ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the IPv6 target address.
+     * \return the IPv6 target address
+     */
+    Ipv6Address GetTarget () const;
+
+    /**
+     * \brief Set the IPv6 target address.
+     * \param target IPv6 target address
+     */
+    void SetTarget (Ipv6Address target);
+
+    /**
+     * \brief Get the IPv6 destination address.
+     * \return the IPv6 destination address
+     */
+    Ipv6Address GetDestination () const;
+
+    /**
+     * \brief Set the IPv6 destination address.
+     * \param destination IPv6 destination address
+     */
+    void SetDestination (Ipv6Address destination);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+    /**
+     * \brief Get the reserved field.
+     * \return reserved value
+     */
+    uint32_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field.
+     * \param reserved the reserved value
+     */
+    void SetReserved (uint32_t reserved);
+
+  private:
+    /**
+     * \brief IPv6 target address.
+     */
+    Ipv6Address m_target;
+
+    /**
+     * \brief IPv6 destination address.
+     */
+    Ipv6Address m_destination;
+
+    /**
+     * \brief Reserved value.
+     */
+    uint32_t m_reserved;
+};
+
+/**
+ * \class Icmpv6Echo
+ * \brief ICMPv6 Echo message.
+ */
+class Icmpv6Echo : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Default constructor.
+     */
+    Icmpv6Echo ();
+
+    /**
+     * \brief Constructor.
+     * \param request request or reply message
+     */
+    Icmpv6Echo (bool request);
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6Echo ();
+
+    /**
+     * \brief Get the ID of the packet.
+     * \return id
+     */
+    uint16_t GetId () const;
+
+    /**
+     * \brief Set the ID of the packet.
+     * \param id id to set
+     */
+    void SetId (uint16_t id);
+
+    /**
+     * \brief Get the sequence number.
+     * \return sequence number
+     */
+    uint16_t GetSeq () const;
+
+    /**
+     * \brief Set the sequence number.
+     * \param seq sequence to set
+     */
+    void SetSeq (uint16_t seq);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief ID of the packet (to distinguish response between many ping program).
+     */
+    uint16_t m_id;
+
+    /**
+     * \brief Sequence number (to distinguish response).
+     */
+    uint16_t m_seq;
+};
+
+/**
+ * \class Icmpv6DestinationUnreachable
+ * \brief ICMPv6 Error Destination Unreachable header.
+ */
+class Icmpv6DestinationUnreachable : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6DestinationUnreachable ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6DestinationUnreachable ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the incorrect packet.
+     * \return the incorrect packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the incorrect packet.
+     * \param p the incorrect packet
+     */
+    void SetPacket (Ptr<Packet> p);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The incorrect Packet.
+     */
+    Ptr<Packet> m_packet;
+};
+
+/**
+ * \class Icmpv6TooBig
+ * \brief ICMPv6 Error Too Big header.
+ */
+class Icmpv6TooBig : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6TooBig ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6TooBig ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the incorrect packet.
+     * \return the incorrect packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the incorrect packet.
+     * \param p the incorrect packet
+     */
+    void SetPacket (Ptr<Packet> p);
+
+    /**
+     * \brief Get the MTU field.
+     * \return MTU value
+     */
+    uint32_t GetMtu () const;
+
+    /**
+     * \brief Set the MTU.
+     * \param mtu the MTU
+     */
+    void SetMtu (uint32_t mtu);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+
+    /**
+     * \brief the incorrect packet.
+     */
+    Ptr<Packet> m_packet;
+
+    /**
+     * \brief The MTU value.
+     */
+    uint32_t m_mtu;
+};
+
+/**
+ * \class Icmpv6TimeExceeded
+ * \brief ICMPv6 Error Time Exceeded header.
+ */
+class Icmpv6TimeExceeded : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6TimeExceeded ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6TimeExceeded ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the incorrect packet.
+     * \return the incorrect packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the incorrect packet.
+     * \param p the incorrect packet
+     */
+    void SetPacket (Ptr<Packet> p);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+
+    /**
+     * \brief The incorrect packet.
+     */
+    Ptr<Packet> m_packet;
+};
+
+/**
+ * \class Icmpv6ParameterError
+ * \brief ICMPv6 Error Parameter Error header.
+ */
+class Icmpv6ParameterError : public Icmpv6Header
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6ParameterError ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6ParameterError ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the incorrect packet.
+     * \return the incorrect packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the incorrect packet.
+     * \param p the incorrect packet
+     */
+    void SetPacket (Ptr<Packet> p);
+
+    /**
+     * \brief Get the pointer field.
+     * \return pointer value
+     */
+    uint32_t GetPtr () const;
+
+    /**
+     * \brief Set the pointer field.
+     * \param ptr byte where the error is located in the incorrect packet
+     */
+    void SetPtr (uint32_t ptr);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os);
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+
+    /**
+     * \brief The incorrect packet.
+     */
+    Ptr<Packet> m_packet;
+
+    /**
+     * \brief The pointer field.
+     */
+    uint32_t m_ptr;
+};
+
+/**
+ * \class Icmpv6OptionMtu
+ * \brief ICMPv6 MTU option.
+ */
+class Icmpv6OptionMtu : public Icmpv6OptionHeader
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6OptionMtu ();
+
+    /**
+     * \brief Constructor.
+     * \param mtu MTU used.
+     */
+    Icmpv6OptionMtu (uint32_t mtu);
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6OptionMtu ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the reserved field.
+     * \return the reserved value
+     */
+    uint16_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field.
+     * \param reserved the reserved value
+     */
+    void SetReserved (uint16_t reserved);
+
+    /**
+     * \brief Get the MTU.
+     * \return the MTU value
+     */
+    uint32_t GetMtu () const;
+
+    /**
+     * \brief Set the MTU.
+     * \param mtu the MTU to set
+     */
+    void SetMtu (uint32_t mtu);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The reserved value
+     */
+    uint16_t m_reserved;
+
+    /**
+     * \brief The MTU value.
+     */
+    uint32_t m_mtu;
+};
+
+/**
+ * \class Icmpv6OptionPrefixInformation
+ * \brief ICMPv6 Option Prefix Information.
+ */
+class Icmpv6OptionPrefixInformation : public Icmpv6OptionHeader
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6OptionPrefixInformation ();
+
+    /**
+     * \brief Constructor.
+     * \param network prefix
+     * \param prefixlen prefix length
+     */
+    Icmpv6OptionPrefixInformation (Ipv6Address network, uint8_t prefixlen);
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6OptionPrefixInformation ();
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Get the prefix length.
+     * \return prefix length
+     */
+    uint8_t GetPrefixLength () const;
+
+    /**
+     * \brief Set the prefix length.
+     * \param prefixLength the prefix length
+     */
+    void SetPrefixLength (uint8_t prefixLength);
+
+    /**
+     * \brief Get the flags.
+     * \return the flags.
+     */
+    uint8_t GetFlags () const;
+
+    /**
+     * \brief Set the flags.
+     * \param flags the flags to set
+     */
+    void SetFlags (uint8_t flags);
+
+    /**
+     * \brief Get the valid time of the information.
+     * \return valid time
+     */
+    uint32_t GetValidTime () const;
+
+    /**
+     * \brief Set the valid time of the information.
+     * \param validTime valid time
+     */
+    void SetValidTime (uint32_t validTime);
+
+    /**
+     * \brief Get the preferred time of the information.
+     * \return preferred time
+     */
+    uint32_t GetPreferredTime () const;
+
+    /**
+     * \brief Set the preferred time of the information.
+     * \param preferredTime preferred time
+     */
+    void SetPreferredTime (uint32_t preferredTime);
+
+    /**
+     * \brief Get the reserved field.
+     * \return the reserved field (should be 0x00000000)
+     */
+    uint32_t GetReserved () const;
+
+    /**
+     * \brief Set the reserved field (normally it will be 0x00000000).
+     * \param reserved reserved value
+     */
+    void SetReserved (uint32_t reserved);
+
+    /**
+     * \brief Get the IPv6 prefix.
+     * \return IPv6 prefix
+     */
+    Ipv6Address GetPrefix () const;
+
+    /**
+     * \brief Set the IPv6 prefix.
+     * \param prefix the IPv6 prefix
+     */
+    void SetPrefix (Ipv6Address prefix);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The prefix value.
+     */
+    Ipv6Address m_prefix;
+
+    /**
+     * \brief The length of the prefix.
+     */
+    uint8_t m_prefixLength;
+
+    /**
+     * \brief The flags.
+     */
+    uint8_t m_flags;
+
+    /**
+     * \brief The valid time.
+     */
+    uint32_t m_validTime;
+
+    /**
+     * \brief The preferred time.
+     */
+    uint32_t m_preferredTime;
+
+    /**
+     * \brief The reserved field.
+     */
+    uint32_t m_reserved;
+};
+
+/**
+ * \class Icmpv6OptionLinkLayerAddress
+ * \brief ICMPv6 link-layer address option.
+ */
+class Icmpv6OptionLinkLayerAddress : public Icmpv6OptionHeader
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param source source hardware address or target hardware address for the option
+     */
+    Icmpv6OptionLinkLayerAddress (bool source);
+
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId (void) const;
+
+    /**
+     * \brief Constructor.
+     * \param source source hardware address or target hardware address for the option
+     * \param addr hardware address
+     */
+    Icmpv6OptionLinkLayerAddress (bool source, Address addr);
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6OptionLinkLayerAddress ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6OptionLinkLayerAddress ();
+
+    /**
+     * \brief Get the hardware address.
+     * \return the hardware address
+     */
+    Address GetAddress () const;
+
+    /**
+     * \brief Set the hardware address.
+     * \param addr the address to set
+     */
+    void SetAddress (Address addr);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The hardware address.
+     */
+    Address m_addr;
+};
+
+/**
+ * \class Icmpv6OptionRedirected
+ * \brief ICMPv6 redirected option.
+ */
+class Icmpv6OptionRedirected : public Icmpv6OptionHeader
+{
+  public:
+    /**
+     * \brief Get the UID of this class.
+     * \return UID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Get the instance type ID.
+     * \return instance type ID
+     */
+    virtual TypeId GetInstanceTypeId () const;
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6OptionRedirected ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6OptionRedirected ();
+
+    /**
+     * \brief Get the redirected packet.
+     * \return the redirected packet
+     */
+    Ptr<Packet> GetPacket () const;
+
+    /**
+     * \brief Set the redirected packet.
+     * \param packet the redirected packet
+     */
+    void SetPacket (Ptr<Packet> packet);
+
+    /**
+     * \brief Print informations.
+     * \param os output stream
+     */
+    virtual void Print (std::ostream& os) const;
+
+    /**
+     * \brief Get the serialized size.
+     * \return serialized size
+     */
+    virtual uint32_t GetSerializedSize () const;
+
+    /**
+     * \brief Serialize the packet.
+     * \param start start offset
+     */
+    virtual void Serialize (Buffer::Iterator start) const;
+
+    /**
+     * \brief Deserialize the packet.
+     * \param start start offset
+     * \return length of packet
+     */
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+
+  private:
+    /**
+     * \brief The redirected packet.
+     */
+    Ptr<Packet> m_packet;
+};
+
+} /* namespace ns3 */
+
+#endif /* ICMPV6_HEADER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv6-l4-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,1205 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         David Gross <gdavid.devel@gmail.com>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/ipv6-routing-protocol.h"
+#include "ns3/ipv6-route.h"
+
+#include "ipv6-raw-socket-factory-impl.h"
+#include "icmpv6-l4-protocol.h"
+#include "icmpv6-header.h"
+#include "ipv6-l3-protocol.h"
+#include "ipv6-end-point.h"
+
+#include "ns3/ipv6-static-routing-helper.h"
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Icmpv6L4Protocol);
+
+NS_LOG_COMPONENT_DEFINE ("Icmpv6L4Protocol");
+
+const uint8_t Icmpv6L4Protocol::PROT_NUMBER = 58;
+
+const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERT_INTERVAL = 16;
+const uint8_t Icmpv6L4Protocol::MAX_INITIAL_RTR_ADVERTISEMENTS = 3;
+const uint8_t Icmpv6L4Protocol::MAX_FINAL_RTR_ADVERTISEMENTS = 3;
+const uint8_t Icmpv6L4Protocol::MIN_DELAY_BETWEEN_RAS = 3;
+const uint32_t Icmpv6L4Protocol::MAX_RA_DELAY_TIME = 500; /* millisecond */
+
+const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATION_DELAY = 1;
+const uint8_t Icmpv6L4Protocol::RTR_SOLICITATION_INTERVAL = 4;
+const uint8_t Icmpv6L4Protocol::MAX_RTR_SOLICITATIONS = 3;
+
+const uint8_t Icmpv6L4Protocol::MAX_MULTICAST_SOLICIT = 3;
+const uint8_t Icmpv6L4Protocol::MAX_UNICAST_SOLICIT = 3;
+const uint8_t Icmpv6L4Protocol::MAX_ANYCAST_DELAY_TIME = 1;
+const uint8_t Icmpv6L4Protocol::MAX_NEIGHBOR_ADVERTISEMENT = 3;
+const uint32_t Icmpv6L4Protocol::REACHABLE_TIME = 30000;
+const uint32_t Icmpv6L4Protocol::RETRANS_TIMER = 1000;
+const uint8_t Icmpv6L4Protocol::DELAY_FIRST_PROBE_TIME = 5;
+const double Icmpv6L4Protocol::MIN_RANDOM_FACTOR = 0.5;
+const double Icmpv6L4Protocol::MAX_RANDOM_FACTOR = 1.5;
+
+TypeId Icmpv6L4Protocol::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Icmpv6L4Protocol")
+    .SetParent<Ipv6L4Protocol> ()
+    .AddConstructor<Icmpv6L4Protocol> ()
+    ;
+  return tid;
+}
+
+Icmpv6L4Protocol::Icmpv6L4Protocol ()
+  : m_node (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Icmpv6L4Protocol::~Icmpv6L4Protocol ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void Icmpv6L4Protocol::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (CacheList::const_iterator it = m_cacheList.begin () ; it != m_cacheList.end () ; it++)
+  {
+    Ptr<NdiscCache> cache = *it;
+    cache->Dispose ();
+    cache = 0;
+  }
+  m_cacheList.clear ();
+
+  m_node = 0;
+  Ipv6L4Protocol::DoDispose ();
+}
+
+void Icmpv6L4Protocol::NotifyNewAggregate ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_node == 0)
+  {
+    Ptr<Node> node = this->GetObject<Node> ();
+    if (node != 0)
+    {
+      Ptr<Ipv6L3Protocol> ipv6 = this->GetObject<Ipv6L3Protocol> ();
+      if (ipv6 != 0)
+      {
+        this->SetNode (node);
+        ipv6->Insert (this);
+        Ptr<Ipv6RawSocketFactoryImpl> rawFactory = CreateObject<Ipv6RawSocketFactoryImpl> ();
+        ipv6->AggregateObject (rawFactory);
+      }
+    }
+  }
+  Object::NotifyNewAggregate ();
+}
+
+void Icmpv6L4Protocol::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  m_node = node;
+}  
+
+uint16_t Icmpv6L4Protocol::GetStaticProtocolNumber ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return PROT_NUMBER;
+}
+
+int Icmpv6L4Protocol::GetProtocolNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return PROT_NUMBER;
+}
+
+int Icmpv6L4Protocol::GetVersion () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return 1;
+}
+
+void Icmpv6L4Protocol::DoDAD (Ipv6Address target, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << target << interface);
+  Ipv6Address addr;
+
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  NS_ASSERT (ipv6);
+
+  /* TODO : disable multicast loopback to prevent NS probing to be received by the sender */
+
+  Ptr<Packet> p = ForgeNS ("::" ,Ipv6Address::MakeSolicitedAddress (target), target, interface->GetDevice ()->GetAddress ());
+
+  /* update last packet UID */
+  interface->SetNsDadUid (target, p->GetUid ());
+  interface->Send (p, Ipv6Address::MakeSolicitedAddress (target));
+}
+
+enum Ipv6L4Protocol::RxStatus_e Icmpv6L4Protocol::Receive (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Ptr<Packet> p = packet->Copy ();
+  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
+
+  switch (*p->PeekData ()) /* very ugly! try to find something better in the future */
+  {
+    case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION:
+      if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
+      {
+        HandleRS (p, src, dst, interface);
+      }
+      break;
+    case Icmpv6Header::ICMPV6_ND_ROUTER_ADVERTISEMENT:
+      if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
+      {
+        HandleRA (p, src, dst, interface);
+      }
+      break;
+    case Icmpv6Header::ICMPV6_ND_NEIGHBOR_SOLICITATION:
+      HandleNS (p, src, dst, interface);
+      break;
+    case Icmpv6Header::ICMPV6_ND_NEIGHBOR_ADVERTISEMENT:
+      HandleNA (p, src, dst, interface);
+      break;
+    case Icmpv6Header::ICMPV6_ND_REDIRECTION:
+      HandleRedirection (p, src, dst, interface);
+      break;
+    case Icmpv6Header::ICMPV6_ECHO_REQUEST:
+      HandleEchoRequest (p, src, dst, interface);
+      break;
+    case Icmpv6Header::ICMPV6_ECHO_REPLY:
+      break;
+    case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE:
+      break;
+    case Icmpv6Header::ICMPV6_ERROR_PACKET_TOO_BIG:
+      break;
+    case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED:
+      break;
+    case Icmpv6Header::ICMPV6_ERROR_PARAMETER_ERROR:
+      break;
+    default:
+      NS_LOG_LOGIC ("Unknown ICMPv6 message type=" << (uint8_t)*p->PeekData ());
+      break;
+  }
+
+  return Ipv6L4Protocol::RX_OK;
+}
+
+void Icmpv6L4Protocol::HandleEchoRequest (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Icmpv6Echo request;
+  packet->RemoveHeader (request);
+
+  /* if we send message from ff02::* (link-local multicast), we use our link-local address */
+  SendEchoReply (dst.IsMulticast () ? interface->GetLinkLocalAddress ().GetAddress () : dst, src, request.GetId (), request.GetSeq (), packet);
+}
+
+void Icmpv6L4Protocol::HandleRA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{ 
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Ptr<Packet> p = packet->Copy ();
+  Icmpv6RA raHeader;
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  Icmpv6OptionPrefixInformation prefixHdr;
+  Icmpv6OptionMtu mtuHdr;
+  Icmpv6OptionLinkLayerAddress llaHdr;
+  uint8_t type = 0;
+  bool next = true;
+  bool hasLla = false;
+  bool hasMtu = false;
+
+  p->RemoveHeader (raHeader);
+
+  while (next == true)
+  {
+    type = *p->PeekData ();
+
+    switch (type)
+    {
+      case Icmpv6Header::ICMPV6_OPT_PREFIX:
+        p->RemoveHeader (prefixHdr);
+        ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (interface->GetDevice ()), prefixHdr.GetPrefix (), prefixHdr.GetPrefixLength (), 
+                                        prefixHdr.GetFlags (), prefixHdr.GetValidTime (), prefixHdr.GetPreferredTime (), src);
+        break;
+      case Icmpv6Header::ICMPV6_OPT_MTU:
+        /* take in account the first MTU option */
+        if (!hasMtu)
+        {
+          p->RemoveHeader (mtuHdr);
+          hasMtu = true;
+          /* XXX case of multiple prefix on single interface */
+          /* interface->GetDevice ()->SetMtu (m.GetMtu ()); */
+        }
+        break;
+      case Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE:
+        /* take in account the first LLA option */
+        if (!hasLla)
+        {
+          p->RemoveHeader (llaHdr);                   
+          ReceiveLLA (llaHdr, src, dst, interface);
+          hasLla = true;
+        }
+        break;
+      default:
+        /* unknow option, quit */
+        next = false;
+    }
+  }
+}
+
+void Icmpv6L4Protocol::ReceiveLLA (Icmpv6OptionLinkLayerAddress lla, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << lla << src << dst << interface);
+  Address hardwareAddress;
+  NdiscCache::Entry* entry = NULL;
+  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
+  
+  /* check if we have this address in our cache */ 
+  entry = cache->Lookup (src);
+
+  if (!entry)
+  {
+    entry = cache->Add (src);
+    entry->SetRouter (true);
+    entry->SetMacAddress (lla.GetAddress ());
+    entry->MarkReachable ();  
+    entry->StartReachableTimer ();        
+  }                    
+  else
+  {
+    std::list<Ptr<Packet> > waiting;
+    if (entry->IsIncomplete ())
+    {
+      entry->StopRetransmitTimer ();
+      // mark it to reachable 
+      waiting = entry->MarkReachable (lla.GetAddress ());
+      entry->StopReachableTimer ();
+      entry->StartReachableTimer ();
+      // send out waiting packet 
+      for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
+      {
+        cache->GetInterface ()->Send (*it, src);
+      }
+      entry->ClearWaitingPacket ();
+    }
+    else
+    {
+      if (entry->GetMacAddress ()!=lla.GetAddress ())
+      {
+        entry->SetMacAddress (lla.GetAddress ());
+        entry->MarkStale ();
+        entry->SetRouter (true);
+      }  
+      else
+      {
+        if (!entry->IsReachable ())
+        {
+          entry->StopProbeTimer ();
+          entry->StopDelayTimer ();
+          waiting = entry->MarkReachable (lla.GetAddress ());
+          if (entry->IsProbe ())
+          {
+            for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
+            {
+              cache->GetInterface ()->Send (*it, src);
+            }
+          }
+          entry->StopReachableTimer ();
+          entry->StartReachableTimer ();
+        }    
+      }
+    }
+  }
+}
+
+void Icmpv6L4Protocol::HandleRS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  Icmpv6RS rsHeader;
+  packet->RemoveHeader (rsHeader);
+  Address hardwareAddress;
+  Icmpv6OptionLinkLayerAddress lla (1);
+  NdiscCache::Entry* entry = NULL;
+  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
+
+  if (src != Ipv6Address::GetAny ())
+  {
+    /* XXX search all options following the RS header */
+    /* test if the next option is SourceLinkLayerAddress */
+    if (*packet->PeekData () != Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE)
+    {
+      return;
+    }
+    packet->RemoveHeader (lla);
+    NS_LOG_LOGIC ("Cache updated by RS");
+
+    entry = cache->Lookup (src);
+    if (!entry)
+    {
+      entry = cache->Add (src);
+      entry->SetRouter (false);
+      entry->MarkStale (lla.GetAddress ());
+    }
+    else if (entry->GetMacAddress () != lla.GetAddress ())
+    {
+      entry->MarkStale (lla.GetAddress ());
+    }
+  }
+}
+
+void Icmpv6L4Protocol::HandleNS (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Icmpv6NS nsHeader ("::");
+  Ipv6InterfaceAddress ifaddr;
+  uint32_t nb = interface->GetNAddresses ();
+  uint32_t i = 0;
+  bool found = false;
+
+  packet->RemoveHeader (nsHeader);
+
+  Ipv6Address target = nsHeader.GetIpv6Target ();
+
+  for (i = 0 ; i < nb ; i++)
+  {
+    ifaddr = interface->GetAddress (i);
+
+    if (ifaddr.GetAddress () == target)
+    {
+      found = true;
+      break;
+    }
+  }
+
+  if (!found)
+  {
+    NS_LOG_LOGIC ("Not a NS for us");
+    return;
+  }
+
+  if (packet->GetUid () == ifaddr.GetNsDadUid ())
+  {
+    /* don't process our own DAD probe */
+    NS_LOG_LOGIC ("Hey we receive our DAD probe!");
+    return;
+  }
+
+  Icmpv6OptionLinkLayerAddress lla (1);
+  Address hardwareAddress;
+  NdiscCache::Entry* entry = 0;
+  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
+  uint8_t flags = 0;
+
+  /* XXX search all options following the NS header */
+
+  if (src != Ipv6Address::GetAny ())
+  {
+    if (*packet->PeekData () != Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE)
+    {
+      return;
+    }
+
+    /* Get LLA */
+    packet->RemoveHeader (lla);
+
+    entry = cache->Lookup (src);
+    if (!entry)
+    {
+      entry = cache->Add (src);
+      entry->SetRouter (false);
+      entry->MarkStale (lla.GetAddress ());
+    }
+    else if (entry->GetMacAddress () != lla.GetAddress ())
+    {
+      entry->MarkStale (lla.GetAddress ());
+    }
+
+    flags = 3; /* S + O flags */
+  }
+  else
+  {
+    /* it means someone do a DAD */
+    flags = 1; /* O flag */
+  }
+
+  /* send a NA to src */
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+
+  if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())))
+  {
+    flags += 4; /* R flag */
+  }
+
+  hardwareAddress = interface->GetDevice ()->GetAddress ();
+  Ptr<Packet> p = ForgeNA (target.IsLinkLocal () ? interface->GetLinkLocalAddress ().GetAddress () : ifaddr.GetAddress (), src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src, &hardwareAddress, flags );
+  interface->Send (p,  src.IsAny () ? Ipv6Address::GetAllNodesMulticast () : src); 
+
+  /* not a NS for us discard it */
+}
+
+Ptr<Packet> Icmpv6L4Protocol::ForgeRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress)
+{
+  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
+  Ptr<Packet> p = Create<Packet> ();
+  Ipv6Header ipHeader;
+  Icmpv6RS rs;
+  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);  /* we give our mac address in response */
+
+  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
+  p->AddHeader (llOption);
+
+  rs.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + rs.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (rs);
+
+  ipHeader.SetSourceAddress (src);
+  ipHeader.SetDestinationAddress (dst);
+  ipHeader.SetNextHeader (PROT_NUMBER);
+  ipHeader.SetPayloadLength (p->GetSize ());
+  ipHeader.SetHopLimit (255);
+
+  p->AddHeader (ipHeader);
+
+  return p;
+}
+
+Ptr<Packet> Icmpv6L4Protocol::ForgeEchoRequest (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
+{
+  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
+  Ptr<Packet> p = data->Copy ();
+  Ipv6Header ipHeader;
+  Icmpv6Echo req (1);
+
+  req.SetId (id);
+  req.SetSeq (seq);
+
+  p->AddHeader (req);
+
+  return p;
+}
+
+void Icmpv6L4Protocol::HandleNA (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  Icmpv6NA naHeader;
+  Icmpv6OptionLinkLayerAddress lla (1);
+
+  packet->RemoveHeader (naHeader);
+  Ipv6Address target = naHeader.GetIpv6Target ();
+
+  Address hardwareAddress;
+  NdiscCache::Entry* entry = 0;
+  Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
+  std::list<Ptr<Packet> > waiting;
+
+  /* check if we have something in our cache */
+  entry = cache->Lookup (target);
+
+  if (!entry)
+  {
+    /* ouch!! we are victim of a DAD */
+    Ipv6InterfaceAddress ifaddr;
+    bool found = false;
+    uint32_t i = 0;
+    uint32_t nb = 0;
+
+    for (i = 0 ; i < nb ; i++)
+    {
+      if (ifaddr.GetAddress () == target)
+      {
+        found = true;
+        break;
+      }
+    }
+
+    if (found)
+    {
+      if (ifaddr.GetState () == Ipv6InterfaceAddress::TENTATIVE || ifaddr.GetState () == Ipv6InterfaceAddress::TENTATIVE_OPTIMISTIC)
+      {
+        interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::INVALID);
+      }
+    }
+    /* we have not initiated any communication with the target so... discard the NA */
+    return;
+  }
+
+  /* XXX search all options following the NA header */
+  /* Get LLA */
+  if (*packet->PeekData () != Icmpv6Header::ICMPV6_OPT_LINK_LAYER_TARGET)
+  {
+    return;
+  }
+  packet->RemoveHeader (lla);
+
+  if (entry->IsIncomplete ())
+  {
+    /* we receive a NA so stop the retransmission timer */
+    entry->StopRetransmitTimer ();
+
+    if (naHeader.GetFlagS ())
+    {
+      /* mark it to reachable */
+      waiting = entry->MarkReachable (lla.GetAddress ());
+      entry->StopReachableTimer ();
+      entry->StartReachableTimer ();
+      /* send out waiting packet */
+      for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
+      {
+        cache->GetInterface ()->Send (*it, src);
+      }
+      entry->ClearWaitingPacket ();
+    }
+    else
+    {
+      entry->MarkStale (lla.GetAddress ());
+    }
+
+    if (naHeader.GetFlagR ())
+    {
+      entry->SetRouter (true);
+    }
+  }
+  else
+  {
+    /* we receive a NA so stop the probe timer or delay timer if any */
+    entry->StopProbeTimer ();
+    entry->StopDelayTimer ();
+
+    /* if the Flag O is clear and mac address differs from the cache */
+    if (!naHeader.GetFlagO () && lla.GetAddress ()!=entry->GetMacAddress ())
+    {
+      if (entry->IsReachable ())
+      {
+        entry->MarkStale ();
+      }
+      return;
+    }
+    else
+    {
+      if ((!naHeader.GetFlagO () && lla.GetAddress () == entry->GetMacAddress ()) || naHeader.GetFlagO ()) /* XXX lake "no target link-layer address option supplied" */
+      {
+        entry->SetMacAddress (lla.GetAddress ());
+
+        if (naHeader.GetFlagS ())
+        {
+          if (!entry->IsReachable ())
+          {
+            if (entry->IsProbe ())
+            {
+              waiting = entry->MarkReachable (lla.GetAddress ());
+              for (std::list<Ptr<Packet> >::const_iterator it = waiting.begin (); it != waiting.end (); it++)
+              {
+                cache->GetInterface ()->Send (*it, src); 
+              }
+              entry->ClearWaitingPacket ();
+            }
+            else
+            {
+              entry->MarkReachable (lla.GetAddress ());
+            }
+          }
+          entry->StopReachableTimer ();
+          entry->StartReachableTimer ();
+        }
+        else if (lla.GetAddress ()!=entry->GetMacAddress ())
+        {
+          entry->MarkStale ();
+        }
+        entry->SetRouter (naHeader.GetFlagR ());
+      }
+    }
+  }
+}
+
+void Icmpv6L4Protocol::HandleRedirection (Ptr<Packet> packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << interface);
+  bool hasLla = false;
+  Ptr<Packet> p = packet->Copy ();
+  Icmpv6OptionLinkLayerAddress llOptionHeader (0);
+
+  Icmpv6Redirection redirectionHeader;
+  p->RemoveHeader (redirectionHeader);
+
+  /* little ugly try to find a better way */
+  if (*p->PeekData () == Icmpv6Header::ICMPV6_OPT_LINK_LAYER_TARGET)
+  {
+    hasLla = true;
+    p->RemoveHeader (llOptionHeader);
+  }
+
+  Icmpv6OptionRedirected redirectedOptionHeader;
+  p->RemoveHeader (redirectedOptionHeader);
+
+  Ipv6Address redirTarget = redirectionHeader.GetTarget ();
+  Ipv6Address redirDestination = redirectionHeader.GetDestination ();
+
+  if (hasLla)
+  {
+    /* update the cache if needed */
+    NdiscCache::Entry* entry = NULL;
+    Ptr<NdiscCache> cache = FindCache (interface->GetDevice ());
+
+    entry = cache->Lookup (redirTarget);
+    if (!entry)
+    {
+      entry = cache->Add (redirTarget);
+      /* destination and target different => necessarily a router */
+      entry->SetRouter (!redirTarget.IsEqual (redirDestination) ? true : false);
+      entry->SetMacAddress (llOptionHeader.GetAddress ());
+      entry->MarkStale ();
+    }
+    else
+    {
+      if (entry->IsIncomplete () || entry->GetMacAddress () != llOptionHeader.GetAddress ())
+      {
+        /* update entry to STALE */
+        if (entry->GetMacAddress ()!=llOptionHeader.GetAddress ())
+        {
+          entry->SetMacAddress (llOptionHeader.GetAddress ());
+          entry->MarkStale ();
+        }
+      }
+      else
+      {
+        /* stay unchanged */
+      }
+    }
+  }
+
+  /* add redirection in routing table */
+  Ptr<Ipv6> ipv6 = m_node->GetObject<Ipv6> ();
+
+  if (redirTarget.IsEqual (redirDestination))
+  {
+    ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), Ipv6Address ("::"), ipv6->GetInterfaceForAddress (dst));
+  }
+  else
+  {
+    uint32_t ifIndex = ipv6->GetInterfaceForAddress (dst);
+    ipv6->GetRoutingProtocol ()->NotifyAddRoute (redirDestination, Ipv6Prefix (128), redirTarget, ifIndex);
+  }
+}
+
+void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl)
+{
+  NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  SocketIpTtlTag tag;
+  NS_ASSERT (ipv6 != 0);
+
+  tag.SetTtl (ttl);
+  packet->AddPacketTag (tag);
+  ipv6->Send (packet, src, dst, PROT_NUMBER, 0);
+}
+
+void Icmpv6L4Protocol::SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl)
+{
+  NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0);
+  Ipv6Header header;
+  SocketIpTtlTag tag;
+  Socket::SocketErrno err;
+  Ptr<Ipv6Route> route;
+  uint32_t oif = 0; //specify non-zero if bound to a source address
+  
+  header.SetDestinationAddress (dst);
+  route = ipv6->GetRoutingProtocol ()->RouteOutput (packet, header, oif, err);
+ 
+  if (route != 0)
+  {
+    NS_LOG_LOGIC ("Route exists");
+    tag.SetTtl (ttl);
+    packet->AddPacketTag (tag);
+    Ipv6Address src = route->GetSource ();
+
+    icmpv6Hdr.CalculatePseudoHeaderChecksum (src, dst, packet->GetSize () + icmpv6Hdr.GetSerializedSize (), PROT_NUMBER);
+    packet->AddHeader (icmpv6Hdr);
+    ipv6->Send (packet, src, dst, PROT_NUMBER, route);
+  }
+  else
+  {
+    NS_LOG_WARN ("drop icmp message");
+  }
+}
+
+void Icmpv6L4Protocol::SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
+{
+  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << flags);
+  Ptr<Packet> p = Create<Packet> ();
+  Icmpv6NA na;
+  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress); /* not a source link layer */
+
+  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << " target " << src << ")");
+  na.SetIpv6Target (src);
+
+  if ((flags & 1))
+  {
+    na.SetFlagO (true);
+  }
+  if ((flags & 2) && src != Ipv6Address::GetAny ())
+  {
+    na.SetFlagS (true);
+  }
+  if ((flags & 4))
+  {
+    na.SetFlagR (true);
+  }
+
+  p->AddHeader (llOption);
+  na.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + na.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (na);
+
+  SendMessage (p, src, dst, 255);
+}
+
+void Icmpv6L4Protocol::SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data)
+{
+  NS_LOG_FUNCTION (this << src << dst << id << seq << data);
+  Ptr<Packet> p = data->Copy ();
+  Icmpv6Echo reply (0); /* echo reply */
+
+  reply.SetId (id);
+  reply.SetSeq (seq);
+
+  reply.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + reply.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (reply);
+  SendMessage (p, src, dst, 64);
+}
+
+void Icmpv6L4Protocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
+{
+  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
+  Ptr<Packet> p = Create<Packet> ();
+  /* Ipv6Header ipHeader; */
+  Icmpv6NS ns (target);
+  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);  /* we give our mac address in response */
+
+  /* if the source is unspec, multicast the NA to all-nodes multicast */
+  if (src == Ipv6Address::GetAny ())
+  {
+    dst = Ipv6Address::GetAllNodesMulticast ();
+  }
+
+  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
+
+  p->AddHeader (llOption);
+  ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (ns);
+  SendMessage (p, src, dst, 255);
+}
+
+void Icmpv6L4Protocol::SendRS (Ipv6Address src, Ipv6Address dst,  Address hardwareAddress)
+{
+  NS_LOG_FUNCTION (this << src << dst << hardwareAddress);
+  Ptr<Packet> p = Create<Packet> ();
+  Icmpv6RS rs;
+  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);  /* we give our mac address in response */
+
+  /* if the source is unspec, multicast the NA to all-nodes multicast */
+  if (src != Ipv6Address::GetAny ())
+  {
+    p->AddHeader (llOption);
+  }
+
+  NS_LOG_LOGIC ("Send RS ( from " << src << " to " << dst << ")");
+
+  rs.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + rs.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (rs);
+  SendMessage (p, src, dst, 255);
+}
+
+void Icmpv6L4Protocol::SendErrorDestinationUnreachable (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
+{
+  NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code);
+  Ptr<Packet> p = Create<Packet> ();
+  uint32_t malformedPacketSize = malformedPacket->GetSize ();
+  Icmpv6DestinationUnreachable header;
+
+  NS_LOG_LOGIC ("Send Destination Unreachable ( to " << dst << " code " << (uint32_t)code << " )");
+
+  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
+  if (malformedPacketSize <= 1280 - 48)
+  {
+    header.SetPacket (malformedPacket);
+  }
+  else
+  {
+    Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
+    header.SetPacket (fragment);
+  }
+
+  header.SetCode (code);
+  SendMessage (p, dst, header, 255);
+}
+
+void Icmpv6L4Protocol::SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu)
+{
+  NS_LOG_FUNCTION (this << malformedPacket << dst << mtu);
+  Ptr<Packet> p = Create<Packet> ();
+  uint32_t malformedPacketSize = malformedPacket->GetSize ();
+  Icmpv6TooBig header;
+
+  NS_LOG_LOGIC ("Send Too Big ( to " << dst << " )");
+
+  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
+  if (malformedPacketSize <= 1280 - 48)  
+  {
+    header.SetPacket (malformedPacket);
+  }
+  else
+  {
+    Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
+    header.SetPacket (fragment);
+  }
+
+  header.SetCode (0);
+  header.SetMtu (mtu);
+  SendMessage (p, dst, header, 255);
+}
+
+void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code)
+{
+  NS_LOG_FUNCTION (this<< malformedPacket << dst << code);
+  Ptr<Packet> p = Create<Packet> ();
+  uint32_t malformedPacketSize = malformedPacket->GetSize ();
+  Icmpv6TimeExceeded header;
+
+  NS_LOG_LOGIC ("Send Time Exceeded ( to " << dst << " code " << (uint32_t)code << " )");
+
+  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
+  if (malformedPacketSize <= 1280 - 48) 
+  {
+    header.SetPacket (malformedPacket);
+  }
+  else
+  {
+    Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
+    header.SetPacket (fragment);
+  }
+
+  header.SetCode (code);
+  SendMessage (p, dst, header, 255);
+}
+
+void Icmpv6L4Protocol::SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr)
+{
+  NS_LOG_FUNCTION (this << malformedPacket << dst << code << ptr);
+  Ptr<Packet> p = Create<Packet> ();
+  uint32_t malformedPacketSize = malformedPacket->GetSize ();
+  Icmpv6ParameterError header;
+
+  NS_LOG_LOGIC ("Send Parameter Error ( to " << dst << " code " << (uint32_t)code << " )");
+
+  /* 48 = sizeof IPv6 header + sizeof ICMPv6 error header */
+  if (malformedPacketSize <= 1280 -48 )
+  {
+    header.SetPacket (malformedPacket);
+  }
+  else
+  {
+    Ptr<Packet> fragment = malformedPacket->CreateFragment (0, 1280 - 48);
+    header.SetPacket (fragment);
+  }
+
+  header.SetCode (code);
+  header.SetPtr (ptr);
+  SendMessage (p, dst, header, 255);
+}
+
+void Icmpv6L4Protocol::SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget)
+{
+  NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget);
+  uint32_t llaSize = 0;
+  Ptr<Packet> p = Create<Packet> ();
+  uint32_t redirectedPacketSize = redirectedPacket->GetSize ();
+  Icmpv6OptionLinkLayerAddress llOption (0);
+
+  NS_LOG_LOGIC ("Send Redirection ( to " << dst << " target " << redirTarget << " destination " << redirDestination << " )");
+
+  Icmpv6OptionRedirected redirectedOptionHeader;
+
+  if ((redirectedPacketSize % 8) != 0)
+  {
+    redirectedPacket->AddPaddingAtEnd (8 - (redirectedPacketSize % 8));
+  }
+
+  if (redirHardwareTarget.GetLength ())
+  {
+    llOption.SetAddress (redirHardwareTarget);
+    llaSize = llOption.GetSerializedSize ();
+  }
+
+  /* 56 = sizeof IPv6 header + sizeof ICMPv6 error header + sizeof redirected option */
+  if (redirectedPacketSize <= (1280 - 56 - llaSize))
+  {
+    redirectedOptionHeader.SetPacket (redirectedPacket);
+  }
+  else
+  {
+    Ptr<Packet> fragment = redirectedPacket->CreateFragment (0, 1280 - 56 - llaSize);
+    redirectedOptionHeader.SetPacket (fragment);
+  }
+
+  p->AddHeader (redirectedOptionHeader);
+
+  if (llaSize)
+  {
+    p->AddHeader (llOption);
+  }
+
+  Icmpv6Redirection redirectionHeader;
+  redirectionHeader.SetTarget (redirTarget);
+  redirectionHeader.SetDestination (redirDestination);
+  SendMessage (p, dst, redirectionHeader, 64);
+}
+
+Ptr<Packet> Icmpv6L4Protocol::ForgeNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags)
+{
+  NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags);
+  Ptr<Packet> p = Create<Packet> ();
+  Ipv6Header ipHeader;
+  Icmpv6NA na;
+  Icmpv6OptionLinkLayerAddress llOption (0, *hardwareAddress);  /* we give our mac address in response */
+
+  NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")");
+
+  /* forge the entire NA packet from IPv6 header to ICMPv6 link-layer option, so that the packet does not pass by Icmpv6L4Protocol::Lookup again */
+
+  p->AddHeader (llOption);
+  na.SetIpv6Target (src);
+
+  if ((flags & 1))
+  {
+    na.SetFlagO (true);
+  }
+  if ((flags & 2) && src != Ipv6Address::GetAny ())
+  {
+    na.SetFlagS (true);
+  }
+  if ((flags & 4))
+  {
+    na.SetFlagR (true);
+  }
+
+  na.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + na.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (na);
+
+  ipHeader.SetSourceAddress (src);
+  ipHeader.SetDestinationAddress (dst);
+  ipHeader.SetNextHeader (PROT_NUMBER);
+  ipHeader.SetPayloadLength (p->GetSize ());
+  ipHeader.SetHopLimit (255);
+  
+  p->AddHeader (ipHeader);
+
+  return p;
+}
+
+Ptr<Packet> Icmpv6L4Protocol::ForgeNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress)
+{
+  NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress);
+  Ptr<Packet> p = Create<Packet> ();
+  Ipv6Header ipHeader;
+  Icmpv6NS ns (target);
+  Icmpv6OptionLinkLayerAddress llOption (1, hardwareAddress);  /* we give our mac address in response */
+
+  /* if the source is unspec, multicast the NA to all-nodes multicast */
+  if (src == Ipv6Address::GetAny ())
+  {
+    dst = Ipv6Address::GetAllNodesMulticast ();
+  }
+
+  NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << " target " << target <<")");
+
+  p->AddHeader (llOption);
+  ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER);
+  p->AddHeader (ns);
+
+  ipHeader.SetSourceAddress (src);
+  ipHeader.SetDestinationAddress (dst);
+  ipHeader.SetNextHeader (PROT_NUMBER);
+  ipHeader.SetPayloadLength (p->GetSize ());
+  ipHeader.SetHopLimit (255);
+
+  p->AddHeader (ipHeader);
+
+  return p;
+}
+
+Ptr<NdiscCache> Icmpv6L4Protocol::FindCache (Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << device);
+
+  for (CacheList::const_iterator i = m_cacheList.begin () ; i != m_cacheList.end () ; i++)
+  {
+    if ((*i)->GetDevice () == device)
+    {
+      return *i;
+    }
+  }
+
+  NS_ASSERT (false);
+  /* quiet compiler */
+  return 0;
+}
+
+Ptr<NdiscCache> Icmpv6L4Protocol::CreateCache (Ptr<NetDevice> device, Ptr<Ipv6Interface> interface)
+{
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  Ptr<NdiscCache> cache = CreateObject<NdiscCache> ();
+  cache->SetDevice (device, interface);
+
+  /* XXX : make a list of callback in net-device.cc
+   * else we override IPv4 flushing ARP table...
+   */
+/* device->SetLinkChangeCallback (MakeCallback (&NdiscCache::Flush, cache)); */
+  m_cacheList.push_back (cache);
+  return cache;
+}
+
+bool Icmpv6L4Protocol::Lookup (Ptr<Packet> p, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination)
+{
+  NS_LOG_FUNCTION (this << p << dst << device << hardwareDestination);
+
+  if (!cache)
+  {
+    /* try to find the cache */
+    cache = FindCache (device);
+  }
+
+  NdiscCache::Entry* entry = cache->Lookup (dst);
+  if (entry)
+  {
+    if (entry->IsReachable () || entry->IsDelay ())
+    {
+      /* XXX check reachability time */
+      /* send packet */
+      *hardwareDestination = entry->GetMacAddress ();
+      return true;
+    }
+    else if (entry->IsStale ())
+    {
+      /* *hardwareDestination = entry->GetMacAddress (); */
+      /* start delay timer */
+      entry->StartDelayTimer ();
+      entry->MarkDelay ();
+      *hardwareDestination = entry->GetMacAddress ();
+      return true;
+    }
+    else /* PROBE */
+    {
+      /* queue packet */
+      entry->AddWaitingPacket (p);
+      return false;
+    }
+  }
+  else
+  {
+    /* we contact this node for the first time
+     * add it to the cache and send an NS
+     */
+    Ipv6Address addr;
+    NdiscCache::Entry* entry = cache->Add (dst);
+    entry->MarkIncomplete (p);
+    entry->SetRouter (false);
+
+    if (dst.IsLinkLocal ())
+    {
+      addr = cache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
+    }
+    else if (cache->GetInterface ()->GetNAddresses () == 1) /* an interface have at least one address (link-local) */
+    {
+      /* try to resolve global address without having global address so return! */
+      cache->Remove (entry);
+      return false;
+    }
+    else
+    {
+      /* find source address that match destination */
+      addr = cache->GetInterface ()->GetAddressMatchingDestination (dst).GetAddress (); 
+    }
+
+    SendNS (addr, Ipv6Address::MakeSolicitedAddress (dst), dst, cache->GetDevice ()->GetAddress ());
+
+    /* start retransmit timer */
+    entry->StartRetransmitTimer ();
+    return false;
+  }
+
+  return false;
+}
+
+void Icmpv6L4Protocol::FunctionDadTimeout (Ptr<Icmpv6L4Protocol> icmpv6, Ipv6Interface* interface, Ipv6Address addr)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC (interface << " " << addr);
+  Ipv6InterfaceAddress ifaddr;
+  bool found = false;
+  uint32_t i = 0;
+  uint32_t nb = interface->GetNAddresses ();
+  
+  for (i = 0 ; i < nb ; i++)
+  {
+    ifaddr = interface->GetAddress (i);
+
+    if (ifaddr.GetAddress () == addr)
+    {
+      found = true;
+      break;
+    }
+  }
+
+  /* for the moment, this function is always called, if we was victim of a DAD the address is INVALID 
+   * and we do not set it to PREFERRED
+   */
+  if (found && ifaddr.GetState () != Ipv6InterfaceAddress::INVALID)
+  {
+    interface->SetState (ifaddr.GetAddress (), Ipv6InterfaceAddress::PREFERRED);
+    NS_LOG_LOGIC ("DAD OK, interface in state PREFERRED");
+
+    /* send an RS if our interface is not forwarding (router) and if address is a link-local ones
+     * (because we will send RS with it)
+     */
+    Ptr<Ipv6> ipv6 = icmpv6->m_node->GetObject<Ipv6> ();
+
+    if (!ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ())) && addr.IsLinkLocal ()) 
+    {
+      /* XXX because all nodes start at the same time, there will be many of RS arround 1 second of simulation time 
+       * TODO Add random delays before sending RS
+       */
+      Simulator::Schedule (Seconds (0.0), &Icmpv6L4Protocol::SendRS, PeekPointer (icmpv6), ifaddr.GetAddress (), Ipv6Address::GetAllRoutersMulticast (), interface->GetDevice ()->GetAddress ());
+    }
+  }
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/icmpv6-l4-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,472 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ *         David Gross <gdavid.devel@gmail.com>
+ *         Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#ifndef ICMPV6_L4_PROTOCOL_H
+#define ICMPV6_L4_PROTOCOL_H
+
+#include <list>
+#include "ns3/ipv6-address.h"
+#include "ns3/ptr.h"
+#include "ns3/socket.h"
+#include "ns3/buffer.h"
+#include "icmpv6-header.h"
+#include "ipv6-l4-protocol.h"
+#include "ndisc-cache.h"
+#include "ipv6-l3-protocol.h"
+
+namespace ns3
+{
+ 
+class NetDevice;
+class Node;
+class Packet;
+class TraceContext;
+
+/**
+ * \class Icmpv6L4Protocol
+ * \brief An implementation of the ICMPv6 protocol.
+ */
+class Icmpv6L4Protocol : public Ipv6L4Protocol
+{
+  public:
+    /**
+     * \brief Interface ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief ICMPv6 protocol number (58).
+     */
+    static const uint8_t PROT_NUMBER;
+
+    /**
+     * \brief Neighbor Discovery router constants : max initial RA initial interval.
+     */
+    static const uint8_t MAX_INITIAL_RTR_ADVERT_INTERVAL;
+
+    /**
+     * \brief Neighbor Discovery router constants : max initial RA transmission.
+     */
+    static const uint8_t MAX_INITIAL_RTR_ADVERTISEMENTS;
+
+    /**
+     * \brief Neighbor Discovery router constants : max final RA transmission.
+     */
+    static const uint8_t MAX_FINAL_RTR_ADVERTISEMENTS;
+
+    /**
+     * \brief Neighbor Discovery router constants : min delay between RA.
+     */
+    static const uint8_t MIN_DELAY_BETWEEN_RAS;
+
+    /**
+     * \brief Neighbor Discovery router constants : max delay between RA.
+     */
+    static const uint32_t MAX_RA_DELAY_TIME;
+
+    /**
+     * \brief Neighbor Discovery host constants : max RS delay.
+     */
+    static const uint8_t MAX_RTR_SOLICITATION_DELAY;
+
+    /**
+     * \brief Neighbor Discovery host constants : RS interval.
+     */
+    static const uint8_t RTR_SOLICITATION_INTERVAL;
+
+    /**
+     * \brief Neighbor Discovery host constants : max RS transmission.
+     */
+    static const uint8_t MAX_RTR_SOLICITATIONS;
+
+    /**
+     * \brief Neighbor Discovery node constants : max multicast solicitations.
+     */
+    static const uint8_t MAX_MULTICAST_SOLICIT;
+
+    /**
+     * \brief Neighbor Discovery node constants : max unicast solicitations.
+     */
+    static const uint8_t MAX_UNICAST_SOLICIT;
+
+    /**
+     * \brief Neighbor Discovery node constants : max anycast delay.
+     */
+    static const uint8_t MAX_ANYCAST_DELAY_TIME;
+
+    /**
+     * \brief Neighbor Discovery node constants : max NA transmission.
+     */
+    static const uint8_t MAX_NEIGHBOR_ADVERTISEMENT;
+
+    /**
+     * \brief Neighbor Discovery node constants : reachable time.
+     */
+    static const uint32_t REACHABLE_TIME;
+
+    /**
+     * \brief Neighbor Discovery node constants : retransmission timer.
+     */
+    static const uint32_t RETRANS_TIMER;
+
+    /**
+     * \brief Neighbor Discovery node constants : delay for the first probe.
+     */
+    static const uint8_t DELAY_FIRST_PROBE_TIME;
+
+    /**
+     * \brief Neighbor Discovery node constants : min random factor.
+     */
+    static const double MIN_RANDOM_FACTOR;
+
+    /**
+     * \brief Neighbor Discovery node constants : max random factor.
+     */
+    static const double MAX_RANDOM_FACTOR;
+
+    /**
+     * \brief Get ICMPv6 protocol number.
+     * \return protocol number
+     */
+    static uint16_t GetStaticProtocolNumber ();
+
+    /**
+     * \brief Constructor.
+     */
+    Icmpv6L4Protocol ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Icmpv6L4Protocol ();
+
+    /**
+     * \brief Set the node.
+     * \param node the node to set
+     */
+    void SetNode (Ptr<Node> node);
+
+    /**
+     * \brief This method is called by AddAgregate and completes the aggregation
+     * by setting the node in the ICMPv6 stack and adding ICMPv6 factory to
+     * IPv6 stack connected to the node.
+     */
+    void NotifyNewAggregate ();
+
+    /**
+     * \brief Get the protocol number.
+     * \return protocol number
+     */
+    virtual int GetProtocolNumber () const;
+
+    /**
+     * \brief Get the version of the protocol.
+     * \return version
+     */
+    virtual int GetVersion () const;
+
+    /**
+     * \brief Send a packet via ICMPv6, note that packet already contains ICMPv6 header.
+     * \param packet the packet to send which contains ICMPv6 header
+     * \param src source address
+     * \param dst destination address
+     * \param ttl next hop limit
+     */
+    void SendMessage (Ptr<Packet> packet, Ipv6Address src, Ipv6Address dst, uint8_t ttl);
+
+    /**
+     * \brief Send a packet via ICMPv6.
+     * \param packet the packet to send
+     * \param dst destination address
+     * \param icmpv6Hdr ICMPv6 header (needed to calculate checksum 
+     * after source address is determined by routing stuff
+     * \param ttl next hop limit
+     */
+    void SendMessage (Ptr<Packet> packet, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl);
+    
+    /**
+     * \brief Do the Duplication Address Detection (DAD).
+     * \param target target address
+     * \param interface interface
+     */
+    void DoDAD (Ipv6Address target, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Send a Neighbor Adverstisement.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 address
+     * \param hardwareAddress our MAC address
+     * \param flags to set (4 = flag R, 2 = flag S, 3 = flag O)
+     */
+    void SendNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags);
+
+    /**
+     * \brief Send a Echo Reply.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 address
+     * \param id id of the packet
+     * \param seq sequence number
+     * \param data auxiliary data
+     * \todo Change data to be a char[], change it too in icmpv6-header.
+     */
+    void SendEchoReply (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data);
+
+    /**
+     * \brief Send a Neighbor Solicitation.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 addresss
+     * \param target target IPv6 address
+     * \param hardwareAddress our mac address
+     */
+    void SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress);
+
+    /**
+     * \brief Send an error Destination Unreachable.
+     * \param malformedPacket the malformed packet
+     * \param dst destination IPv6 address
+     * \param code code of the error
+     */
+    void SendErrorDestinationUnreachable (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code);
+
+    /**
+     * \brief Send an error Too Big.
+     * \param malformedPacket the malformed packet
+     * \param dst destination IPv6 address
+     * \param mtu the mtu
+     */
+    void SendErrorTooBig (Ptr<Packet> malformedPacket, Ipv6Address dst, uint32_t mtu);
+
+    /**
+     * \brief Send an error Time Exceeded.
+     * \param malformedPacket the malformed packet
+     * \param dst destination IPv6 address
+     * \param code code of the error
+     */
+    void SendErrorTimeExceeded (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code);
+
+    /**
+     * \brief Send an error Parameter Error.
+     * \param malformedPacket the malformed packet
+     * \param dst destination IPv6 address
+     * \param code code of the error
+     * \param ptr byte of p where the error is located
+     */
+    void SendErrorParameterError (Ptr<Packet> malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr);
+
+    /**
+     * \brief Send an ICMPv6 Redirection.
+     * \param redirectedPacket the redirected packet
+     * \param dst destination IPv6 address
+     * \param redirTarget IPv6 target address for Icmpv6Redirection
+     * \param redirDestination IPv6 destination address for Icmpv6Redirection
+     * \param redirHardwareTarget L2 target address for Icmpv6OptionRdirected
+     */
+    void SendRedirection (Ptr<Packet> redirectedPacket, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget);
+
+    /**
+     * \brief Forge a Neighbor Solicitation.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 addresss
+     * \param target target IPv6 address
+     * \param hardwareAddress our mac address
+     * \return NS packet (with IPv6 header)
+     */
+    Ptr<Packet> ForgeNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress);
+
+    /**
+     * \brief Forge a Neighbor Advertisement.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 addresss
+     * \param hardwareAddress our mac address
+     * \param flags flags (bitfield => R (4), S (2), O (1))
+     * \return NA packet (with IPv6 header)
+     */
+    Ptr<Packet> ForgeNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags);
+
+    /**
+     * \brief Forge a Router Solicitation.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 addresss
+     * \param hardwareAddress our mac address
+     * \return RS packet (with IPv6 header)
+     */
+    Ptr<Packet> ForgeRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress);
+
+    /**
+     * \brief Forge an Echo Request.
+     * \param src source address
+     * \param dst destination address
+     * \param id ID of the packet
+     * \param seq sequence number
+     * \param data the data
+     * \return Echo Request packet (without IPv6 header)
+     */
+    Ptr<Packet> ForgeEchoRequest (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr<Packet> data);
+
+    /**
+     * \brief Receive method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    virtual enum Ipv6L4Protocol::RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Do the Duplication Address Detection.
+     * It consists in sending a NS with our IPv6 as target. If 
+     * we received a NA with matched target address, we could not use the address, 
+     * else the address pass from TENTATIVE to PERMANENT.
+     * \param addr IPv6 address to test
+     * \param interface interface
+     */
+    void DoDad (Ipv6Address addr, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Function called when DAD timeout.
+     * \param icmpv6 Icmpv6L4Protocol instance
+     * \param interface the interface
+     * \param addr the IPv6 address
+     */
+    static void FunctionDadTimeout (Ptr<Icmpv6L4Protocol> icmpv6, Ipv6Interface* interface, Ipv6Address addr);
+
+    /**
+     * \brief Lookup in the ND cache for the IPv6 address (similar as ARP protocol).
+     * \param p the packet
+     * \param dst destination address
+     * \param device device
+     * \param cache the neighbor cache
+     * \param hardwareDestination hardware address
+     * \return true if the address is in the ND cache, the hardwareDestination is updated.
+     */
+    bool Lookup (Ptr<Packet> p, Ipv6Address dst, Ptr<NetDevice> device, Ptr<NdiscCache> cache, Address* hardwareDestination);
+
+    /**
+     * \brief Send a Router Solicitation.
+     * \param src link-local source address
+     * \param dst destination address (usealy ff02::2 i.e all-routers)
+     * \param hardwareAddress link-layer address (SHOULD be included if src is not ::
+     */
+    void SendRS (Ipv6Address src, Ipv6Address dst,  Address hardwareAddress);
+
+    /**
+     * \brief Create a neighbor cache.
+     * \param device thet NetDevice
+     * \param interface the IPv6 interface
+     * \return a smart pointer of NdCache or 0 if problem
+     */
+    Ptr<NdiscCache> CreateCache (Ptr<NetDevice> device, Ptr<Ipv6Interface> interface);
+
+  protected:
+    /**
+     * \brief Dispose this object.
+     */
+    virtual void DoDispose ();
+
+  private:
+
+    typedef std::list<Ptr<NdiscCache> > CacheList;
+
+    /**
+     * \brief The node.
+     */
+    Ptr<Node> m_node;
+
+    /**
+     * \brief A list of cache by device.
+     */
+    CacheList m_cacheList;
+
+    /**
+     * \brief Receive Neighbor Solicitation method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleNS (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Receive Router Solicitation method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleRS (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Receive Router Advertisement method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleRA (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Receive Echo Request method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleEchoRequest (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Receive Neighbor Advertisement method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleNA (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Receive Redirection method.
+     * \param p the packet
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void HandleRedirection (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Link layer address option processing.
+     * \param lla LLA option
+     * \param src source address
+     * \param dst destination address
+     * \param interface the interface from which the packet is coming
+     */
+    void ReceiveLLA (Icmpv6OptionLinkLayerAddress lla, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Get the cache corresponding to the device.
+     * \param device the device
+     */
+    Ptr<NdiscCache> FindCache (Ptr<NetDevice> device);
+};
+
+} /* namespace ns3 */
+
+#endif /* ICMPV6_L4_PROTOCOL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-autoconfigured-prefix.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,201 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Telecom Bretagne 
+ *
+ * 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: Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#include <stdlib.h>
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+
+#include "ipv6-autoconfigured-prefix.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6AutoconfiguredPrefix");
+
+namespace ns3
+{
+  uint32_t Ipv6AutoconfiguredPrefix::m_prefixId = 0;
+
+  Ipv6AutoconfiguredPrefix::Ipv6AutoconfiguredPrefix (Ptr<Node> node, uint32_t interface, Ipv6Address prefix, Ipv6Prefix mask, uint32_t preferredLifeTime, uint32_t validLifeTime, Ipv6Address router)
+  {
+    m_node = node;
+    m_interface = interface;
+    m_validLifeTime = validLifeTime;
+    m_preferredLifeTime = preferredLifeTime;
+    m_id = m_prefixId;
+    m_prefixId ++;
+    m_preferred = false;
+    m_valid = false;
+    m_prefix = prefix;
+    m_mask = mask;
+    m_defaultGatewayRouter = router;
+  }
+
+  Ipv6AutoconfiguredPrefix::~Ipv6AutoconfiguredPrefix ()
+  {
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetDefaultGatewayRouter (Ipv6Address router)
+  {
+    m_defaultGatewayRouter = router;
+  }
+
+  Ipv6Address Ipv6AutoconfiguredPrefix::GetDefaultGatewayRouter () const
+  {
+    return m_defaultGatewayRouter;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetInterface (uint32_t interface)
+  {
+    m_interface = interface;
+  }
+
+  uint32_t Ipv6AutoconfiguredPrefix::GetInterface () const
+  {
+    return m_interface;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetPreferredLifeTime (uint32_t t)
+  {
+    m_preferredLifeTime = t;
+  }
+
+  uint32_t Ipv6AutoconfiguredPrefix::GetPreferredLifeTime () const
+  {
+    return m_preferredLifeTime;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetValidLifeTime (uint32_t t)
+  {
+    m_validLifeTime = t;
+  }
+
+  uint32_t Ipv6AutoconfiguredPrefix::GetValidLifeTime () const
+  {
+    return m_validLifeTime;
+  }
+
+  void Ipv6AutoconfiguredPrefix::MarkPreferredTime ()
+  {
+    m_preferred = true;
+  }
+
+  void Ipv6AutoconfiguredPrefix::MarkValidTime ()
+  {
+    m_preferred = false;
+    m_valid = true;
+  }
+
+  void Ipv6AutoconfiguredPrefix::FunctionPreferredTimeout ()
+  {
+    NS_LOG_INFO ("Preferred Time expired for " << m_prefix);
+    m_preferred = false;
+    MarkValidTime ();
+    StartValidTimer ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::FunctionValidTimeout ()
+  {
+    NS_LOG_INFO ("Valid Time expired for " << m_prefix);
+    m_valid = false;
+    RemoveMe ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::StartPreferredTimer ()
+  {
+    NS_LOG_INFO ("Start PreferredTimer for " << m_prefix);
+    m_preferredTimer.SetFunction (&Ipv6AutoconfiguredPrefix::FunctionPreferredTimeout, this);
+    m_preferredTimer.SetDelay (Seconds (m_preferredLifeTime));
+    m_preferredTimer.Schedule ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::StartValidTimer ()
+  {
+    NS_LOG_INFO ("Start ValidTimer for " << m_prefix);
+    m_validTimer.SetFunction (&Ipv6AutoconfiguredPrefix::FunctionValidTimeout, this);
+    m_validTimer.SetDelay (Seconds (m_validLifeTime - m_preferredLifeTime));
+    m_validTimer.Schedule ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::StopPreferredTimer ()
+  {
+    NS_LOG_INFO ("Stop PreferredTimer for " << m_prefix);
+    m_preferredTimer.Cancel ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::StopValidTimer ()
+  {
+    NS_LOG_INFO ("Stop ValidTimer for " << m_prefix);
+    m_validTimer.Cancel ();
+  }
+
+  void Ipv6AutoconfiguredPrefix::RemoveMe ()
+  {
+    NS_LOG_INFO ("The prefix " << m_prefix << " will be removed on interface " << m_interface);
+    Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+    ipv6->RemoveAutoconfiguredAddress (m_interface, m_prefix, m_mask, m_defaultGatewayRouter);
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetPreferred ()
+  {
+    m_preferred = true;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetValid ()
+  {
+    m_preferred = false;
+    m_valid = true;
+  }
+
+  uint32_t Ipv6AutoconfiguredPrefix::GetId () const
+  { 
+    return m_id;
+  }
+
+  bool Ipv6AutoconfiguredPrefix::IsPreferred () const
+  {
+    return m_preferred;
+  }
+
+  bool Ipv6AutoconfiguredPrefix::IsValid () const
+  {
+    return m_valid;
+  }
+
+  Ipv6Address Ipv6AutoconfiguredPrefix::GetPrefix () const
+  {
+    return m_prefix;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetPrefix (Ipv6Address prefix)
+  {
+    m_prefix = prefix;
+  }
+
+  Ipv6Prefix Ipv6AutoconfiguredPrefix::GetMask () const
+  {
+    return m_mask;
+  }
+
+  void Ipv6AutoconfiguredPrefix::SetMask (Ipv6Prefix mask)
+  {
+    m_mask = mask;
+  }
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-autoconfigured-prefix.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,279 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008-2009 Telecom Bretagne 
+ *
+ * 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: Mehdi Benamor <benamor.mehdi@ensi.rnu.tn>
+ */
+
+#ifndef IPV6_AUTOCONFIGURED_PREFIX_H
+#define IPV6_AUTOCONFIGURED_PREFIX_H
+
+#include <list>
+#include <vector>
+#include <ostream>
+
+#include "ns3/timer.h"
+#include "ns3/ipv6-address.h"
+#include "ipv6-l3-protocol.h"
+#include "ipv6-interface.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6AutoconfiguredPrefix
+ * \brief Router prefix information.
+ */
+class Ipv6AutoconfiguredPrefix : public Object
+{
+  public:
+    /** 
+     * \brief Constructor.
+     * \param node node
+     * \param interface interface index
+     * \param prefix IPv6 address
+     * \param mask bitmask prefix
+     * \param preferredLifeTime the preferred life time
+     * \param validLifeTime the valid life time
+     * \param router if it the prefix that configure the default gateway
+     */
+    Ipv6AutoconfiguredPrefix (Ptr<Node> node, uint32_t interface, Ipv6Address prefix, Ipv6Prefix mask, uint32_t preferredLifeTime, uint32_t validLifeTime, Ipv6Address router = Ipv6Address ("::"));
+
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6AutoconfiguredPrefix ();
+
+    /**
+     * \brief Set the default gateway router.
+     * \param router IPv6 link-local address of the default router
+     */
+    void SetDefaultGatewayRouter (Ipv6Address router);
+
+    /**
+     * \brief Get the default gateway address.
+     * \return IPv6 link-local address of the default router
+     */
+    Ipv6Address GetDefaultGatewayRouter () const;
+
+    /**
+     * \brief Get the interface index.
+     * \return interface index
+     */
+    uint32_t GetInterface () const;
+
+    /**
+     * \brief Set the interface.
+     * \param interface interface index to set
+     */
+    void SetInterface (uint32_t interface);
+
+    /**
+     * \brief Get the prefix preferred life time.
+     * \return preferred life time
+     */
+    uint32_t GetPreferredLifeTime () const;
+
+    /**
+     * \brief Set the prefix preferred life time.
+     * \param p the prefix preferred life time
+     */
+    void SetPreferredLifeTime (uint32_t p);
+
+    /**
+     * \brief Get the prefix valid life time.
+     * \return valid life time
+     */
+    uint32_t GetValidLifeTime (void) const;
+
+    /**
+     * \brief Set the prefix valid life time
+     * \param v the prefix valid life time
+     */
+    void SetValidLifeTime (uint32_t v);
+
+    /**
+     * \brief Test if the prefix is preferred
+     * \return true if prefix is in preferred state, false otherwise
+     */
+    bool IsPreferred () const;
+
+    /**
+     * \brief Test if the prefix is valid.
+     * \return true if prefix is in valid state, false otherwise
+     */  
+    bool IsValid () const;
+
+    /**
+     * \brief Set the prefix as preferred
+     */
+    void SetPreferred ();
+
+    /**
+     * \brief Set the prefix as valid
+     */
+    void SetValid ();
+
+    /**
+     * \brief Start the preferred timer
+     */
+    void StartPreferredTimer ();
+
+    /**
+     * \brief Start the valid timer
+     */
+    void StartValidTimer ();
+
+    /**
+     * \brief Stop the preferred timer
+     */
+    void StopPreferredTimer ();
+
+    /**
+     * \brief Stop the valid timer
+     */
+    void StopValidTimer ();
+
+    /**
+     * \brief Set the prefix as preferred
+     */
+    void MarkPreferredTime ();
+
+    /**
+     * \brief Set the prefix as valid
+     */
+    void MarkValidTime ();
+
+    /**
+     * \brief Signal that the preferred time expired and start the valid timer
+     */
+    void FunctionPreferredTimeout ();
+
+    /**
+     * \brief Signal that the valid time expired
+     */
+    void FunctionValidTimeout ();
+
+    /**
+     * \brief Remove this prefix from the prefix list
+     */
+    void RemoveMe ();
+
+    /**
+     * \brief Get the prefix identificator
+     * \return id of the prefix.
+     */
+    uint32_t GetId () const;
+
+    /**
+     * \brief Get the prefix address
+     * \return prefix address
+     */
+    Ipv6Address GetPrefix () const;
+
+    /**
+     * \brief Set the prefix address
+     * \param prefix prefix address to set
+     */
+    void SetPrefix (Ipv6Address prefix);
+
+    /**
+     * \brief Get the bitmask prefix.
+     * \return bitmask prefix
+     */
+    Ipv6Prefix GetMask () const;
+
+    /**
+     * \brief Set the bitmask prefix.
+     * \param mask prefix
+     */
+    void SetMask (Ipv6Prefix mask);
+
+  private:
+    /**
+     * \brief a static identifier.
+     */
+    static uint32_t m_prefixId;
+
+    /**
+     * \brief the identifier of this prefix.
+     */
+    uint32_t m_id;
+
+    /**
+     * \brief The node.
+     */
+    Ptr<Node> m_node;
+
+    /**
+     * \brief The prefix IP6 address.
+     */
+    Ipv6Address m_prefix;
+
+    /**
+     * \brief The prefix bitmask (length).
+     */
+    Ipv6Prefix m_mask;
+
+    /**
+     * \brief Default gateway router
+     * If the RA received also configured the default gateway, 
+     * this variable has the link-local address. Otherwise this
+     * is "::"
+     */
+    Ipv6Address m_defaultGatewayRouter;
+
+    /**
+     * \brief The interface index (which is stored the address
+     * corresponding of the prefix).
+     */
+    uint32_t m_interface;
+
+    /**
+     * \brief the valid life time.
+     */
+    uint32_t m_validLifeTime;
+
+    /**
+     * \brief the preferred life time.
+     */
+    uint32_t m_preferredLifeTime;
+
+    /**
+     * \brief true if the prefix is preferred.
+     */
+    bool m_preferred;
+
+    /**
+     * \brief true if the prefix is valid.
+     */
+    bool m_valid;
+
+    /**
+     * \brief the timer for preferred life time.
+     */
+    Timer m_preferredTimer;
+
+    /**
+     * \brief the timer for valid life time.
+     */
+    Timer m_validTimer;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_AUTOCONFIGURED_PREFIX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-end-point-demux.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,318 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ipv6-end-point-demux.h"
+#include "ipv6-end-point.h"
+#include "ns3/log.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6EndPointDemux");
+
+Ipv6EndPointDemux::Ipv6EndPointDemux ()
+  : m_ephemeral (49152)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv6EndPointDemux::~Ipv6EndPointDemux ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    Ipv6EndPoint *endPoint = *i;
+    delete endPoint;
+  }
+  m_endPoints.clear ();
+}
+
+bool Ipv6EndPointDemux::LookupPortLocal (uint16_t port)
+{
+  NS_LOG_FUNCTION (this << port);
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    if ((*i)->GetLocalPort  () == port) 
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool Ipv6EndPointDemux::LookupLocal (Ipv6Address addr, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << addr << port);
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    if ((*i)->GetLocalPort () == port &&
+        (*i)->GetLocalAddress () == addr) 
+    {
+      return true;
+    }
+  }
+  return false;
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::Allocate ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint16_t port = AllocateEphemeralPort ();
+  if (port == 0) 
+  {
+    NS_LOG_WARN ("Ephemeral port allocation failed.");
+    return 0;
+  }
+  Ipv6EndPoint *endPoint = new Ipv6EndPoint (Ipv6Address::GetAny (), port);
+  m_endPoints.push_back (endPoint);
+  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+  return endPoint;
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  uint16_t port = AllocateEphemeralPort ();
+  if (port == 0) 
+  {
+    NS_LOG_WARN ("Ephemeral port allocation failed.");
+    return 0;
+  }
+  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
+  m_endPoints.push_back (endPoint);
+  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+  return endPoint;
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::Allocate (uint16_t port)
+{
+  NS_LOG_FUNCTION (this <<  port);
+
+  return Allocate (Ipv6Address::GetAny (), port);
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address address, uint16_t port)
+{
+  NS_LOG_FUNCTION (this << address << port);
+  if (LookupLocal (address, port)) 
+  {
+    NS_LOG_WARN ("Duplicate address/port; failing.");
+    return 0;
+  }
+  Ipv6EndPoint *endPoint = new Ipv6EndPoint (address, port);
+  m_endPoints.push_back (endPoint);
+  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+  return endPoint;
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::Allocate (Ipv6Address localAddress, uint16_t localPort,
+    Ipv6Address peerAddress, uint16_t peerPort)
+{
+  NS_LOG_FUNCTION (this << localAddress << localPort << peerAddress << peerPort);
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    if ((*i)->GetLocalPort () == localPort &&
+        (*i)->GetLocalAddress () == localAddress &&
+        (*i)->GetPeerPort () == peerPort &&
+        (*i)->GetPeerAddress () == peerAddress) 
+    {
+      NS_LOG_WARN ("No way we can allocate this end-point.");
+      /* no way we can allocate this end-point. */
+      return 0;
+    }
+  }
+  Ipv6EndPoint *endPoint = new Ipv6EndPoint (localAddress, localPort);
+  endPoint->SetPeer (peerAddress, peerPort);
+  m_endPoints.push_back (endPoint);
+
+  NS_LOG_DEBUG ("Now have >>" << m_endPoints.size () << "<< endpoints.");
+
+  return endPoint;
+}
+
+void Ipv6EndPointDemux::DeAllocate (Ipv6EndPoint *endPoint)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    if (*i == endPoint)
+    {
+      delete endPoint;
+      m_endPoints.erase (i);
+      break;
+    }
+  }
+}
+
+/*
+ * If we have an exact match, we return it.
+ * Otherwise, if we find a generic match, we return it.
+ * Otherwise, we return 0.
+ */
+Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::Lookup (Ipv6Address daddr, uint16_t dport, 
+                                                        Ipv6Address saddr, uint16_t sport,
+                                                        Ptr<Ipv6Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION (this << daddr << dport << saddr << sport << incomingInterface);
+
+  EndPoints retval1; /* Matches exact on local port, wildcards on others */
+  EndPoints retval2; /* Matches exact on local port/adder, wildcards on others */
+  EndPoints retval3; /* Matches all but local address */
+  EndPoints retval4; /* Exact match on all 4 */
+
+  NS_LOG_DEBUG ("Looking up endpoint for destination address " << daddr);
+  for (EndPointsI i = m_endPoints.begin (); i != m_endPoints.end (); i++) 
+  {
+    Ipv6EndPoint* endP = *i;
+    NS_LOG_DEBUG ("Looking at endpoint dport=" << endP->GetLocalPort ()
+        << " daddr=" << endP->GetLocalAddress ()
+        << " sport=" << endP->GetPeerPort ()
+        << " saddr=" << endP->GetPeerAddress ());
+    if (endP->GetLocalPort () != dport) 
+    {
+      NS_LOG_LOGIC ("Skipping endpoint " << &endP
+          << " because endpoint dport "
+          << endP->GetLocalPort ()
+          << " does not match packet dport " << dport);
+      continue;
+    }
+
+/*    Ipv6Address incomingInterfaceAddr = incomingInterface->GetAddress (); */
+    NS_LOG_DEBUG ("dest addr " << daddr);
+
+    bool localAddressMatchesWildCard = endP->GetLocalAddress () == Ipv6Address::GetAny ();
+    bool localAddressMatchesExact = endP->GetLocalAddress () == daddr;
+    bool localAddressMatchesAllRouters = endP->GetLocalAddress () == Ipv6Address::GetAllRoutersMulticast ();
+
+    /* if no match here, keep looking */
+    if (!(localAddressMatchesExact || localAddressMatchesWildCard))
+      continue; 
+    bool remotePeerMatchesExact = endP->GetPeerPort () == sport;
+    bool remotePeerMatchesWildCard = endP->GetPeerPort () == 0;
+    bool remoteAddressMatchesExact = endP->GetPeerAddress () == saddr;
+    bool remoteAddressMatchesWildCard = endP->GetPeerAddress () == Ipv6Address::GetAny ();
+
+    /* If remote does not match either with exact or wildcard,i
+       skip this one */
+    if (!(remotePeerMatchesExact || remotePeerMatchesWildCard))
+      continue;
+    if (!(remoteAddressMatchesExact || remoteAddressMatchesWildCard))
+      continue;
+
+    /* Now figure out which return list to add this one to */
+    if (localAddressMatchesWildCard &&
+        remotePeerMatchesWildCard && 
+        remoteAddressMatchesWildCard)
+    { /* Only local port matches exactly */
+      retval1.push_back (endP);
+    }
+    if ((localAddressMatchesExact || (localAddressMatchesAllRouters))&&
+        remotePeerMatchesWildCard &&
+        remoteAddressMatchesWildCard)
+    { /* Only local port and local address matches exactly */
+      retval2.push_back (endP);
+    }
+    if (localAddressMatchesWildCard &&
+        remotePeerMatchesExact &&
+        remoteAddressMatchesExact)
+    { /* All but local address */
+      retval3.push_back (endP);
+    }
+    if (localAddressMatchesExact &&
+        remotePeerMatchesExact &&
+        remoteAddressMatchesExact)
+    { /* All 4 match */
+      retval4.push_back (endP);
+    }
+  }
+
+  /* Here we find the most exact match */
+  if (!retval4.empty ()) return retval4;
+  if (!retval3.empty ()) return retval3;
+  if (!retval2.empty ()) return retval2;
+  return retval1;  /* might be empty if no matches */
+}
+
+Ipv6EndPoint* Ipv6EndPointDemux::SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport)
+{
+  uint32_t genericity = 3;
+  Ipv6EndPoint *generic = 0;
+
+  for (EndPointsI i = m_endPoints.begin () ; i != m_endPoints.end () ; i++)
+  {
+    uint32_t tmp = 0;
+
+    if ((*i)->GetLocalPort () != dport)
+    {
+      continue;
+    }
+
+    if ((*i)->GetLocalAddress () == dst && (*i)->GetPeerPort () == sport &&
+        (*i)->GetPeerAddress () == src)
+    {
+      /* this is an exact match. */
+      return *i;
+    }
+
+    if ((*i)->GetLocalAddress () == Ipv6Address::GetAny ())
+    {
+      tmp ++;
+    }
+
+    if ((*i)->GetPeerAddress () == Ipv6Address::GetAny ())
+    {
+      tmp ++;
+    }
+
+    if (tmp < genericity)
+    {
+      generic = (*i);
+      genericity = tmp;
+    }
+  }
+  return generic;
+}
+
+uint16_t Ipv6EndPointDemux::AllocateEphemeralPort ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint16_t port = m_ephemeral;
+  do 
+  {
+    port++;
+    if (port == 65535) 
+    {
+      port = 49152;
+    }
+    if (!LookupPortLocal (port)) 
+    {
+      return port;
+    }
+  } while (port != m_ephemeral);
+  return 0;
+}
+
+Ipv6EndPointDemux::EndPoints Ipv6EndPointDemux::GetEndPoints () const
+{
+  return m_endPoints;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-end-point-demux.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,160 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_END_POINT_DEMUX_H
+#define IPV6_END_POINT_DEMUX_H
+
+#include <stdint.h>
+#include <list>
+#include "ns3/ipv6-address.h"
+#include "ipv6-interface.h"
+
+namespace ns3
+{
+
+class Ipv6EndPoint;
+
+/**
+ * \class Ipv6EndPointDemux
+ * \brief Demultiplexor for end points.
+ */
+class Ipv6EndPointDemux
+{
+  public:
+    typedef std::list<Ipv6EndPoint *>EndPoints;
+    typedef std::list<Ipv6EndPoint *>::iterator EndPointsI;
+
+    /**
+     * \brief Constructor.
+     */
+    Ipv6EndPointDemux ();
+
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6EndPointDemux ();
+
+    /**
+     * \brief Lookup for port local.
+     * \param port port to test
+     * \return true if a port local is in EndPoints, false otherwise
+     */
+    bool LookupPortLocal (uint16_t port);
+
+    /**
+     * \brief Lookup for address and port.
+     * \param addr address to test
+     * \param port port to test
+     * \return true if there is a match in EndPoints, false otherwise
+     */
+    bool LookupLocal (Ipv6Address addr, uint16_t port);
+
+    /**
+     * \brief lookup for a match with all the parameters.
+     * \param dst destination address to test
+     * \param dport destination port to test
+     * \param src source address to test
+     * \param sport source port to test
+     * \param incomingInterface the incoming interface
+     * \return list en IPv6EndPoints (could be 0 element)
+     */
+    EndPoints Lookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport, Ptr<Ipv6Interface> incomingInterface);
+
+    /**
+     * \brief Simple lookup for a four-tuple match.
+     * \param dst destination address to test
+     * \param dport destination port to test
+     * \param src source address to test
+     * \param sport source port to test
+     * \return match or 0 if not found
+     */
+    Ipv6EndPoint* SimpleLookup (Ipv6Address dst, uint16_t dport, Ipv6Address src, uint16_t sport);
+
+    /**
+     * \brief Allocate a Ipv6EndPoint.
+     * \return an empty Ipv6EndPoint instance
+     */
+    Ipv6EndPoint *Allocate (void);
+
+    /**
+     * \brief Allocate a Ipv6EndPoint.
+     * \return an empty Ipv6EndPoint instance
+     */
+    Ipv6EndPoint *Allocate (Ipv6Address address);
+
+    /**
+     * \brief Allocate a Ipv6EndPoint.
+     * \param port local port
+     * \return an Ipv6EndPoint instance
+     */
+    Ipv6EndPoint *Allocate (uint16_t port);
+
+    /**
+     * \brief Allocate a Ipv6EndPoint.
+     * \param address local address
+     * \param port local port
+     * \return an Ipv6EndPoint instance
+     */
+    Ipv6EndPoint *Allocate (Ipv6Address address, uint16_t port);
+
+    /**
+     * \brief Allocate a Ipv6EndPoint.
+     * \param localAddress local address
+     * \param localPort local port
+     * \param peerAddress peer address
+     * \param peerPort peer port
+     * \return an Ipv6EndPoint instance
+     */
+    Ipv6EndPoint *Allocate (Ipv6Address localAddress, uint16_t localPort, Ipv6Address peerAddress, uint16_t peerPort);
+
+    /**
+     * \brief Remove a end point.
+     * \param endPoint the end point to remove
+     */
+    void DeAllocate (Ipv6EndPoint *endPoint);
+
+    /**
+     * \brief Get the entire list of end points registered.
+     * \return list of Ipv6EndPoint
+     */
+    EndPoints GetEndPoints () const;
+
+  private:
+    /**
+     * \brief Allocate a ephemeral port.
+     * \return a port
+     */
+    uint16_t AllocateEphemeralPort ();
+
+    /**
+     * \brief The ephemeral port.
+     */
+    uint16_t m_ephemeral;
+
+    /**
+     * \brief A list of IPv6 end points.
+     */
+    EndPoints m_endPoints;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_END_POINT_DEMUX_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-end-point.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,128 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ipv6-end-point.h"
+#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6EndPoint");
+
+Ipv6EndPoint::Ipv6EndPoint (Ipv6Address addr, uint16_t port)
+  : m_localAddr (addr),
+  m_localPort (port),
+  m_peerAddr (Ipv6Address::GetAny ()),
+  m_peerPort (0)
+{
+}
+
+Ipv6EndPoint::~Ipv6EndPoint ()
+{
+  if (!m_destroyCallback.IsNull ())
+  {
+    m_destroyCallback ();
+  }
+}
+
+Ipv6Address Ipv6EndPoint::GetLocalAddress ()
+{
+  return m_localAddr;
+}
+
+void Ipv6EndPoint::SetLocalAddress (Ipv6Address addr)
+{
+  m_localAddr = addr;
+}
+
+uint16_t Ipv6EndPoint::GetLocalPort ()
+{
+  return m_localPort;
+}
+
+void Ipv6EndPoint::SetLocalPort (uint16_t port)
+{
+  m_localPort = port;
+}
+
+Ipv6Address Ipv6EndPoint::GetPeerAddress ()
+{
+  return m_peerAddr;
+}
+
+uint16_t Ipv6EndPoint::GetPeerPort ()
+{
+  return m_peerPort;
+}
+
+void Ipv6EndPoint::SetPeer (Ipv6Address addr, uint16_t port)
+{
+  m_peerAddr = addr;
+  m_peerPort = port;
+}
+
+void Ipv6EndPoint::SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback)
+{
+  m_rxCallback = callback;
+}
+
+void Ipv6EndPoint::SetIcmpCallback (Callback<void,Ipv6Address,uint8_t,uint8_t,uint8_t,uint32_t> callback)
+{
+  m_icmpCallback = callback;
+}
+
+void Ipv6EndPoint::SetDestroyCallback (Callback<void> callback)
+{
+  m_destroyCallback = callback;
+}
+
+void Ipv6EndPoint::ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port)
+{
+  if (!m_rxCallback.IsNull ())
+  {
+    m_rxCallback (p, addr, port);
+  }
+}
+
+void Ipv6EndPoint::ForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type, 
+                                uint8_t code, uint32_t info)
+{
+  if (!m_icmpCallback.IsNull ())
+  {
+    Simulator::ScheduleNow (&Ipv6EndPoint::DoForwardIcmp, this,
+                           src, ttl, type, code, info);
+  }
+}
+
+void Ipv6EndPoint::DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport)
+{
+  m_rxCallback (p, saddr, sport);
+}
+
+void Ipv6EndPoint::DoForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type, 
+                                  uint8_t code, uint32_t info)
+{
+  m_icmpCallback (src, ttl, type, code, info);
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-end-point.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,193 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_END_POINT_H
+#define IPV6_END_POINT_H
+
+#include <stdint.h>
+#include "ns3/ipv6-address.h"
+#include "ns3/callback.h"
+
+namespace ns3
+{
+
+class Header;
+class Packet;
+
+/**
+ * \class Ipv6EndPoint
+ * \brief An IPv6 end point, four tuples identification.
+ */
+class Ipv6EndPoint
+{
+  public:
+    /**
+     * \brief Constructor.
+     * \param addr the IPv6 address
+     * \param port the port
+     */
+    Ipv6EndPoint (Ipv6Address addr, uint16_t port);
+
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6EndPoint ();
+
+    /**
+     * \brief Get the local address.
+     * \return the local address
+     */
+    Ipv6Address GetLocalAddress ();
+
+    /**
+     * \brief Set the local address.
+     * \param addr the address to set
+     */
+    void SetLocalAddress (Ipv6Address addr);
+
+    /**
+     * \brief Get the local port.
+     * \return the local port
+     */
+    uint16_t GetLocalPort ();
+
+    /**
+     * \brief Set the local port.
+     * \param port the port to set
+     */
+    void SetLocalPort (uint16_t port);
+
+    /**
+     * \brief Get the peer address.
+     * \return the peer address
+     */
+    Ipv6Address GetPeerAddress ();
+
+    /**
+     * \brief Get the peer port.
+     * \return the peer port
+     */
+    uint16_t GetPeerPort ();
+
+    /**
+     * \brief Set the peer informations (address and port).
+     * \param addr peer address
+     * \param port peer port
+     */
+    void SetPeer (Ipv6Address addr, uint16_t port);
+
+    /**
+     * \brief Set the reception callback.
+     * \param callback callback function
+     */
+    void SetRxCallback (Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> callback);
+    
+    /**
+     * \brief Set the ICMP callback.
+     * \param callback callback function
+     */
+    void SetIcmpCallback (Callback<void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t> callback);
+
+    /**
+     * \brief Set the default destroy callback.
+     * \param callback callback function
+     */
+    void SetDestroyCallback (Callback<void> callback);
+
+    /**
+     * \brief Forward the packet to the upper level.
+     * \param p the packet
+     * \param addr source address
+     * \param port source port
+     */
+    void ForwardUp (Ptr<Packet> p, Ipv6Address addr, uint16_t port);
+
+    /** 
+     * \brief Function called from an L4Protocol implementation 
+     * to notify an endpoint of an icmp message reception.
+     * \param src source IPv6 address
+     * \param ttl time-to-live
+     * \param type ICMPv6 type
+     * \param code ICMPv6 code
+     * \param info ICMPv6 info
+     */
+    void ForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type,
+                      uint8_t code, uint32_t info);
+
+  private:
+    /**
+     * \brief ForwardUp wrapper.
+     * \param p packet
+     * \param saddr source IPv6 address
+     * \param sport source port
+     */ 
+    void DoForwardUp (Ptr<Packet> p, Ipv6Address saddr, uint16_t sport);
+
+    /**
+     * \brief ForwardIcmp wrapper.
+     * \param src source IPv6 address
+     * \param ttl time-to-live
+     * \param type ICMPv6 type
+     * \param code ICMPv6 code
+     * \param info ICMPv6 info
+     */ 
+    void DoForwardIcmp (Ipv6Address src, uint8_t ttl, uint8_t type,
+                        uint8_t code, uint32_t info);
+
+    /**
+     * \brief The local address.
+     */
+    Ipv6Address m_localAddr;
+
+    /**
+     * \brief The local port.
+     */
+    uint16_t m_localPort;
+
+    /**
+     * \brief The peer address.
+     */
+    Ipv6Address m_peerAddr;
+
+    /**
+     * \brief The peer port.
+     */
+    uint16_t m_peerPort;
+
+    /**
+     * \brief The RX callback.
+     */
+    Callback<void, Ptr<Packet>, Ipv6Address, uint16_t> m_rxCallback;
+
+    /**
+     * \brief The ICMPv6 callback.
+     */
+    Callback<void, Ipv6Address, uint8_t, uint8_t, uint8_t, uint32_t> m_icmpCallback;
+
+    /**
+     * \brief The destroy callback.
+     */
+    Callback<void> m_destroyCallback;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_END_POINT_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-interface.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,453 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ipv6-interface.h"
+#include "ns3/net-device.h"
+#include "loopback-net-device.h"
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include <ns3/packet.h>
+
+#include "icmpv6-l4-protocol.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6Interface");
+
+TypeId Ipv6Interface::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6Interface")
+    .SetParent<Object> ()
+    ;
+  return tid;
+}
+
+Ipv6Interface::Ipv6Interface ()
+  : m_ifup (false),
+  m_forwarding (true),
+  m_metric (1),
+  m_node (0),
+  m_device (0),
+  m_curHopLimit (0),
+  m_baseReachableTime (0),
+  m_reachableTime (0),
+  m_retransTimer (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+Ipv6Interface::~Ipv6Interface ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void Ipv6Interface::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Object::DoDispose ();
+}
+
+void Ipv6Interface::DoSetup ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  
+  if (m_node == 0 || m_device == 0)
+  {
+    return;
+  }
+
+  if (!m_device->NeedsArp ())
+  {
+    return;
+  }
+  
+  /* set up link-local address */
+  if (!DynamicCast<LoopbackNetDevice> (m_device)) /* no autoconf for ip6-localhost */
+  {
+    Address addr = GetDevice ()->GetAddress ();
+
+    if (Mac48Address::IsMatchingType (addr))
+    {
+      Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address::ConvertFrom (addr)), Ipv6Prefix (64));
+      AddAddress (ifaddr);
+    }
+    else
+    {
+      NS_ASSERT_MSG (false, "IPv6 autoconf for this kind of address not implemented.");
+    }
+  }
+
+  Ptr<Icmpv6L4Protocol> icmpv6 = m_node->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
+  m_ndCache = icmpv6->CreateCache (m_device, this);
+}
+
+void Ipv6Interface::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  m_node = node;
+  DoSetup ();
+}
+
+void Ipv6Interface::SetDevice (Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << device);
+  m_device = device;
+  DoSetup ();
+}
+
+Ptr<NetDevice> Ipv6Interface::GetDevice () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_device;
+}
+
+void Ipv6Interface::SetMetric (uint16_t metric)
+{
+  NS_LOG_FUNCTION (this << metric);
+  m_metric = metric;
+}
+
+uint16_t Ipv6Interface::GetMetric () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_metric;
+}
+
+bool Ipv6Interface::IsUp () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_ifup;
+}
+
+bool Ipv6Interface::IsDown () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return !m_ifup;
+}
+
+void Ipv6Interface::SetUp ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_ifup)
+  {
+    return;
+  }
+  m_ifup = true;
+}
+
+void Ipv6Interface::SetDown ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_ifup = false;
+  m_addresses.clear ();
+}
+
+bool Ipv6Interface::IsForwarding () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_forwarding;
+}
+
+void Ipv6Interface::SetForwarding (bool forwarding)
+{
+  NS_LOG_FUNCTION (this << forwarding);
+  m_forwarding = forwarding;
+}
+
+bool Ipv6Interface::AddAddress (Ipv6InterfaceAddress iface)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ipv6Address addr = iface.GetAddress ();
+
+  /* DAD handling */
+  if (!addr.IsAny ())
+  {
+    for (Ipv6InterfaceAddressListCI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+    {
+      if ((*it).GetAddress () == addr)
+      {
+        return false;
+      }
+    }
+
+    m_addresses.push_back (iface);
+    
+    if (!addr.IsAny () || !addr.IsLocalhost ())
+    {
+      /* DAD handling */
+      Ptr<Icmpv6L4Protocol> icmpv6 = m_node->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
+
+      if (icmpv6)
+      {
+        Simulator::Schedule (Seconds (0.), &Icmpv6L4Protocol::DoDAD, icmpv6, addr, this);
+        Simulator::Schedule (Seconds (1.), &Icmpv6L4Protocol::FunctionDadTimeout, icmpv6, this, addr);
+      }
+    }
+    return true;
+  }
+
+  /* bad address */
+  return false;
+}
+
+Ipv6InterfaceAddress Ipv6Interface::GetLinkLocalAddress () const
+{
+  /* IPv6 interface has always at least one IPv6 link-local address */
+  NS_LOG_FUNCTION_NOARGS ();
+
+  for (Ipv6InterfaceAddressListCI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    if ((*it).GetAddress ().IsLinkLocal ())
+    {
+      return (*it);
+    }
+  }
+  NS_ASSERT_MSG (false, "No link-local address on interface " << this);
+  Ipv6InterfaceAddress addr;
+  return addr; /* quiet compiler */
+}
+
+Ipv6InterfaceAddress Ipv6Interface::GetAddress (uint32_t index) const
+{
+  NS_LOG_FUNCTION (this << index);
+  uint32_t i = 0;
+
+  if (m_addresses.size () > index)
+  {
+    for (Ipv6InterfaceAddressListCI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+    {
+      if (i == index)
+      {
+        return (*it);
+      }
+     i++;
+    }
+  }
+
+  NS_ASSERT_MSG (false, "Address " << index << " not found");
+  Ipv6InterfaceAddress addr;
+  return addr;  /* quiet compiler */
+}
+
+uint32_t Ipv6Interface::GetNAddresses () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_addresses.size ();
+}
+
+Ipv6InterfaceAddress Ipv6Interface::RemoveAddress (uint32_t index)
+{
+  NS_LOG_FUNCTION (this << index);
+  uint32_t i = 0;
+
+  if (m_addresses.size () < index)
+  {
+    NS_ASSERT_MSG (false, "Try to remove index that don't exist in Ipv6Interface::RemoveAddress");
+  }
+  
+  for (Ipv6InterfaceAddressListI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    if (i == index)
+    {
+      Ipv6InterfaceAddress iface = (*it);
+      m_addresses.erase (it);
+      return iface;
+    }
+
+    i++;
+  }
+  
+  NS_ASSERT_MSG (false, "Address " << index << " not found");
+  Ipv6InterfaceAddress addr;
+  return addr;  /* quiet compiler */
+}
+
+Ipv6InterfaceAddress Ipv6Interface::GetAddressMatchingDestination (Ipv6Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+  
+  for (Ipv6InterfaceAddressList::const_iterator it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    Ipv6InterfaceAddress ifaddr = (*it);
+
+    if (ifaddr.GetPrefix ().IsMatch (ifaddr.GetAddress (), dst))
+    {
+      return ifaddr;
+    }
+  }
+
+/*  NS_ASSERT_MSG (false, "Not matching address."); */
+  Ipv6InterfaceAddress ret;
+  return ret; /* quiet compiler */
+}
+
+void Ipv6Interface::Send (Ptr<Packet> p, Ipv6Address dest)
+{
+  NS_LOG_FUNCTION (this << p << dest);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+
+  if (!IsUp ())
+  {
+    return;
+  }
+  
+  /* check if destination is localhost (::1) */
+  if (DynamicCast<LoopbackNetDevice> (m_device))
+  {
+    /* XXX additional checks needed here (such as whether multicast
+     * goes to loopback)?
+     */
+    m_device->Send (p, m_device->GetBroadcast (), Ipv6L3Protocol::PROT_NUMBER);
+    return;
+  }
+
+  /* check if destination is for one of our interface */
+  for (Ipv6InterfaceAddressListCI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    if (dest == (*it).GetAddress ())
+    {
+      ipv6->Receive (m_device, p, Ipv6L3Protocol::PROT_NUMBER,
+                     m_device->GetBroadcast (),
+                     m_device->GetBroadcast (),
+                     NetDevice::PACKET_HOST // note: linux uses PACKET_LOOPBACK here
+                     );
+      return;
+    }
+  }
+
+  /* other address */
+  if (m_device->NeedsArp ())
+  {
+    NS_LOG_LOGIC ("Needs ARP" << " " << dest);
+    Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
+    Address hardwareDestination;
+    bool found = false;
+
+    NS_ASSERT (icmpv6);
+    
+    if (dest.IsMulticast ())
+    {
+      NS_LOG_LOGIC ("IsMulticast");
+      NS_ASSERT_MSG (m_device->IsMulticast (), "Ipv6Interface::SendTo (): Sending multicast packet over non-multicast device");
+
+      hardwareDestination = m_device->GetMulticast (dest);
+      found = true;
+    }
+    else
+    {
+      NS_LOG_LOGIC ("NDISC Lookup");
+      found = icmpv6->Lookup (p, dest, GetDevice (), m_ndCache, &hardwareDestination);
+    }
+
+    if (found)
+    {
+      NS_LOG_LOGIC ("Address Resolved.  Send.");
+      m_device ->Send (p, hardwareDestination, Ipv6L3Protocol::PROT_NUMBER);
+    }
+  }
+  else
+  {
+    NS_LOG_LOGIC ("Doesn't need ARP");
+    m_device->Send (p, m_device->GetBroadcast (), Ipv6L3Protocol::PROT_NUMBER);
+  }
+}
+
+void Ipv6Interface::SetCurHopLimit (uint8_t curHopLimit)
+{
+  NS_LOG_FUNCTION (this << curHopLimit);
+  m_curHopLimit = curHopLimit;
+}
+
+uint8_t Ipv6Interface::GetCurHopLimit () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_curHopLimit;
+}
+
+void Ipv6Interface::SetBaseReachableTime (uint16_t baseReachableTime)
+{
+  NS_LOG_FUNCTION (this << baseReachableTime);
+  m_baseReachableTime = baseReachableTime;
+}
+
+uint16_t Ipv6Interface::GetBaseReachableTime () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_baseReachableTime;
+}
+
+void Ipv6Interface::SetReachableTime (uint16_t reachableTime)
+{
+  NS_LOG_FUNCTION (this << reachableTime);
+  m_reachableTime = reachableTime;
+}
+
+uint16_t Ipv6Interface::GetReachableTime () const
+{
+  NS_LOG_FUNCTION_NOARGS (); 
+  return m_reachableTime;
+}
+
+void Ipv6Interface::SetRetransTimer (uint16_t retransTimer)
+{
+  NS_LOG_FUNCTION (this << retransTimer); 
+  m_retransTimer = retransTimer;
+}
+
+uint16_t Ipv6Interface::GetRetransTimer () const
+{
+  NS_LOG_FUNCTION_NOARGS (); 
+  return m_retransTimer;
+}
+
+void Ipv6Interface::SetState (Ipv6Address address, Ipv6InterfaceAddress::State_e state)
+{
+  NS_LOG_FUNCTION (this << address << state);
+
+  for (Ipv6InterfaceAddressListI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    if ((*it).GetAddress () == address)
+    {
+      (*it).SetState (state);
+      return;
+    }
+  }
+  /* not found, maybe address has expired */
+}
+
+void Ipv6Interface::SetNsDadUid (Ipv6Address address, uint32_t uid)
+{
+  NS_LOG_FUNCTION (this << address << uid);
+
+  for (Ipv6InterfaceAddressListI it = m_addresses.begin () ; it != m_addresses.end () ; ++it)
+  {
+    if ((*it).GetAddress () == address)
+    {
+      (*it).SetNsDadUid (uid);
+      return;
+    }
+  }
+  /* not found, maybe address has expired */
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-interface.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,322 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_INTERFACE_H
+#define IPV6_INTERFACE_H
+
+#include <list>
+
+#include "ns3/ipv6-address.h"
+#include "ns3/ipv6-interface-address.h"
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "ns3/timer.h"
+
+#include "ndisc-cache.h"
+
+namespace ns3
+{
+
+class NetDevice;
+class Packet;
+class Node;
+
+/**
+ * \class Ipv6Interface
+ * \brief The IPv6 representation of a network interface
+ *
+ * By default IPv6 interfaces are created in the "down" state
+ * with IP "fe80::1" and a /64 prefix. Before becoming useable,
+ * the user must invoke SetUp on them once the final IPv6 address
+ * and mask has been set.
+ */
+class Ipv6Interface : public Object
+{
+  public:
+    /**
+     * \brief Get the type ID
+     * \return type ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Constructs an Ipv6Interface.
+     */
+    Ipv6Interface ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6Interface ();
+
+    /**
+     * \brief Set node associated with interface.
+     * \param node node
+     */
+    void SetNode (Ptr<Node> node);
+
+    /**
+     * \brief Set the NetDevice.
+     * \param device NetDevice
+     */
+    void SetDevice (Ptr<NetDevice> device);
+
+    /**
+     * \brief Get the NetDevice.
+     * \return the NetDevice associated with this interface
+     */
+    virtual Ptr<NetDevice> GetDevice () const;
+
+    /**
+     * \brief Set the metric.
+     * \param metric configured routing metric (cost) of this interface
+     */
+    void SetMetric (uint16_t metric);
+
+    /**
+     * \brief Get the metric
+     * \return the metric
+     */
+    uint16_t GetMetric () const;
+
+    /**
+     * \brief Is the interface UP ?
+     * \return true if interface is enabled, false otherwise.
+     */
+    bool IsUp () const;
+
+    /**
+     * \brief Is the interface DOWN ?
+     * \return true if interface is disabled, false otherwise.
+     */
+    bool IsDown () const;
+
+    /**
+     * \brief Enable this interface.
+     */
+    void SetUp ();
+
+    /**
+     * \brief Disable this interface.
+     */
+    void SetDown ();
+
+    /**
+     * \brief If the interface allows forwarding packets.
+     * \return true if forwarding is enabled, false otherwise
+     */
+    bool IsForwarding () const;
+
+    /**
+     * \brief Set forwarding enabled or not.
+     * \param forward forwarding state
+     */
+    void SetForwarding (bool forward);
+
+    /**
+     * \brief Set the current hop limit.
+     * \param curHopLimit the value to set
+     */
+    void SetCurHopLimit (uint8_t curHopLimit);
+
+    /**
+     * \brief Get the current hop limit value.
+     * \return current hop limit
+     */
+    uint8_t GetCurHopLimit () const;
+
+    /**
+     * \brief Set the base reachable time.
+     * \param baseReachableTime the value to set
+     */
+    void SetBaseReachableTime (uint16_t baseReachableTime);
+
+    /**
+     * \brief Get the base reachable time.
+     * \return base reachable time
+     */
+    uint16_t GetBaseReachableTime () const;
+
+    /**
+     * \brief Set the reachable time.
+     * \param reachableTime value to set
+     */
+    void SetReachableTime (uint16_t reachableTime);
+
+    /**
+     * \brief Get the reachable time.
+     * \return reachable time
+     */
+    uint16_t GetReachableTime () const;
+
+    /**
+     * \brief Set the retransmission timer.
+     * \param retransTimer value to set
+     */
+    void SetRetransTimer (uint16_t retransTimer);
+
+    /**
+     * \brief Get the retransmission timer.
+     * \return retransmission timer
+     */
+    uint16_t GetRetransTimer () const;
+
+    /**
+     * \brief Send a packet through this interface.
+     * \param p packet to send
+     * \param dest next hop address of packet.
+     *
+     * \note This method will eventually call the private SendTo
+     * method which must be implemented by subclasses.
+     */
+    void Send (Ptr<Packet> p, Ipv6Address dest);
+
+    /**
+     * \brief Add an IPv6 address.
+     * \param iface address to add
+     * \return true if address was added, false otherwise
+     */
+    bool AddAddress (Ipv6InterfaceAddress iface);
+    
+    /**
+     * \brief Get link-local address from IPv6 interface.
+     * \return link-local Ipv6InterfaceAddress, assert if not found
+     */
+    Ipv6InterfaceAddress GetLinkLocalAddress () const;
+
+    /**
+     * \brief Get an address from IPv6 interface.
+     * \param index index
+     * \return Ipv6InterfaceAddress address whose index is i
+     */
+    Ipv6InterfaceAddress GetAddress (uint32_t index) const;
+
+    /**
+     * \brief Get an address which is in the same network prefix as destination.
+     * \param dst destination address
+     * \return Corresponding Ipv6InterfaceAddress or assert if not found
+     */
+    Ipv6InterfaceAddress GetAddressMatchingDestination (Ipv6Address dst);
+
+    /**
+     * \brief Get number of addresses on this IPv6 interface.
+     * \return number of address
+     */
+    uint32_t GetNAddresses (void) const;
+  
+    /**
+     * \brief Remove an address from interface.
+     * \param index index to remove
+     * \return Ipv6InterfaceAddress address whose index is index
+     */
+    Ipv6InterfaceAddress RemoveAddress (uint32_t index);
+    
+    /**
+     * \brief Update state of an interface address.
+     * \param address IPv6 address
+     * \param state new state
+     */
+    void SetState (Ipv6Address address, Ipv6InterfaceAddress::State_e state);
+
+    /**
+     * \brief Update NS DAD packet UID of an interface address.
+     * \param address IPv6 address
+     * \param uid packet UID 
+     */
+    void SetNsDadUid (Ipv6Address address, uint32_t uid);
+
+  protected:
+    /**
+     * \brief Dispose this object.
+     */
+    virtual void DoDispose ();
+
+  private:
+    typedef std::list<Ipv6InterfaceAddress> Ipv6InterfaceAddressList;
+    typedef std::list<Ipv6InterfaceAddress>::iterator Ipv6InterfaceAddressListI;
+    typedef std::list<Ipv6InterfaceAddress>::const_iterator Ipv6InterfaceAddressListCI;
+
+    /**
+     * \brief Initialize interface.
+     */
+    void DoSetup ();
+
+    /**
+     * \brief The addresses assigned to this interface.
+     */
+    Ipv6InterfaceAddressList m_addresses;
+
+    /**
+     * \brief The state of this interface.
+     */
+    bool m_ifup;
+
+    /**
+     * \brief Forwarding state.
+     */
+    bool m_forwarding;
+
+    /**
+     * \brief The metric.
+     */
+    uint16_t m_metric;
+
+    /**
+     * \brief Node associated with this interface.
+     */
+    Ptr<Node> m_node;
+
+    /**
+     * \brief NetDevice associated with this interface.
+     */
+    Ptr<NetDevice> m_device;
+
+    /**
+     * \brief Neighbor cache.
+     */
+    Ptr<NdiscCache> m_ndCache;
+
+    /**
+     * \brief Current hop limit.
+     */
+    uint8_t m_curHopLimit;
+
+    /**
+     * \brief Base value used for computing the random reachable time value (in millisecond).
+     */
+    uint16_t m_baseReachableTime;
+
+    /**
+     * \brief Reachable time (in millisecond).
+     * The time a neighbor is considered reachable after receiving a reachability confirmation.
+     */
+    uint16_t m_reachableTime;
+
+    /**
+     * \brief Retransmission timer (in millisecond).
+     * Time between retransmission of NS.
+     */
+    uint16_t m_retransTimer;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_INTERFACE_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-l3-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,911 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/node.h"
+#include "ns3/uinteger.h"
+#include "ns3/vector.h"
+#include "ns3/callback.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/object-vector.h"
+#include "ns3/ipv6-routing-protocol.h"
+#include "ns3/ipv6-route.h"
+
+#include "loopback-net-device.h"
+#include "ipv6-l3-protocol.h"
+#include "ipv6-l4-protocol.h"
+#include "ipv6-interface.h"
+#include "ipv6-raw-socket-impl.h"
+#include "ipv6-autoconfigured-prefix.h"
+#include "icmpv6-l4-protocol.h"
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6L3Protocol);
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6L3Protocol");
+
+const uint16_t Ipv6L3Protocol::PROT_NUMBER = 0x86DD;
+
+TypeId Ipv6L3Protocol::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6L3Protocol")
+    .SetParent<Ipv6> ()
+    .AddConstructor<Ipv6L3Protocol> ()
+    .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTtl),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddTraceSource ("Tx", "Send IPv6 packet to outgoing interface.",
+                   MakeTraceSourceAccessor (&Ipv6L3Protocol::m_txTrace))
+    .AddTraceSource ("Rx", "Receive IPv6 packet from incoming interface.",
+                     MakeTraceSourceAccessor (&Ipv6L3Protocol::m_rxTrace))
+    .AddTraceSource ("Drop", "Drop IPv6 packet",
+                     MakeTraceSourceAccessor (&Ipv6L3Protocol::m_dropTrace))
+    .AddAttribute ("InterfaceList", "The set of IPv6 interfaces associated to this IPv6 stack.",
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&Ipv6L3Protocol::m_interfaces),
+                   MakeObjectVectorChecker<Ipv6Interface> ())
+    ;
+  return tid;
+}
+
+Ipv6L3Protocol::Ipv6L3Protocol ()
+  : m_nInterfaces (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv6L3Protocol::~Ipv6L3Protocol ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void Ipv6L3Protocol::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  
+  /* clear protocol and interface list */
+  for (L4List_t::iterator it = m_protocols.begin () ; it != m_protocols.end () ; ++it)
+  {
+    *it = 0;
+  }
+  m_protocols.clear ();
+
+  /* remove interfaces */
+  for (Ipv6InterfaceList::iterator it = m_interfaces.begin () ; it != m_interfaces.end (); ++it)
+  {
+    *it = 0;
+  }
+  m_interfaces.clear ();
+
+  /* remove raw sockets */
+  for (SocketList::iterator it = m_sockets.begin () ; it != m_sockets.end () ; ++it)
+  {
+    *it = 0;
+  }
+  m_sockets.clear ();
+
+  /* remove list of prefix */
+  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin () ; it != m_prefixes.end () ; ++it)
+  {
+    (*it)->StopValidTimer ();
+    (*it)->StopPreferredTimer ();
+    (*it) = 0;
+  }
+  m_prefixes.clear ();
+
+
+  m_node = 0;
+  m_routingProtocol = 0;
+  Object::DoDispose ();
+}
+
+void Ipv6L3Protocol::SetRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol)
+{
+  NS_LOG_FUNCTION (this << routingProtocol);
+  m_routingProtocol = routingProtocol;
+  m_routingProtocol->SetIpv6 (this);
+}
+
+Ptr<Ipv6RoutingProtocol> Ipv6L3Protocol::GetRoutingProtocol () const 
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_routingProtocol;
+}
+
+uint32_t Ipv6L3Protocol::AddInterface (Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << device);
+  Ptr<Node> node = GetObject<Node> ();
+  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
+  
+  node->RegisterProtocolHandler (MakeCallback (&Ipv6L3Protocol::Receive, this), Ipv6L3Protocol::PROT_NUMBER, device);
+  interface->SetNode (m_node);
+  interface->SetDevice (device);
+  interface->SetForwarding (m_ipForward);
+  return AddIpv6Interface (interface);
+}
+
+uint32_t Ipv6L3Protocol::AddIpv6Interface (Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << interface);
+  uint32_t index = m_nInterfaces;
+
+  m_interfaces.push_back (interface);
+  m_nInterfaces++;
+  return index;
+}
+
+Ptr<Ipv6Interface> Ipv6L3Protocol::GetInterface (uint32_t index) const
+{
+  NS_LOG_FUNCTION (this << index);
+  uint32_t tmp = 0;
+  
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end () ; it++)
+  {
+    if (index == tmp)
+    {
+      return *it;
+    }
+    tmp++;
+  }
+  return 0;
+}
+
+uint32_t Ipv6L3Protocol::GetNInterfaces () const 
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_nInterfaces;
+}
+
+int32_t Ipv6L3Protocol::GetInterfaceForAddress (Ipv6Address address) const
+{
+  NS_LOG_FUNCTION (this << address); 
+  int32_t index = 0;
+
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end () ; it++)
+  {
+    uint32_t j = 0;
+    uint32_t max = (*it)->GetNAddresses ();
+
+    for (j = 0 ; j < max ; j++)
+    {
+      if ((*it)->GetAddress (j).GetAddress () == address) 
+      {
+        return index;
+      }
+    }
+    index++;
+  }
+  return -1;
+}
+
+int32_t Ipv6L3Protocol::GetInterfaceForPrefix (Ipv6Address address, Ipv6Prefix mask) const
+{
+  NS_LOG_FUNCTION (this << address << mask);
+  int32_t index = 0;
+
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end () ; it++)
+  {
+    uint32_t j = 0;
+    for (j = 0 ; j < (*it)->GetNAddresses () ; j++)
+    {
+      if ((*it)->GetAddress (j).GetAddress ().CombinePrefix (mask) == address.CombinePrefix (mask))
+      {
+        return index;
+      }
+    }
+    index++;
+  }
+  return -1;
+}
+
+Ptr<NetDevice> Ipv6L3Protocol::GetNetDevice (uint32_t i)
+{
+  NS_LOG_FUNCTION (this << i);
+  return GetInterface (i)->GetDevice ();
+}
+
+int32_t Ipv6L3Protocol::GetInterfaceForDevice (Ptr<const NetDevice> device) const
+{
+  NS_LOG_FUNCTION (this << device);
+  int32_t index = 0;
+
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end () ; it++)
+  {
+    if ((*it)->GetDevice () == device)
+    {
+      return index;
+    }
+    index++;
+  }
+  return -1;
+}
+
+void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter)
+{
+  NS_LOG_FUNCTION (this << interface << network << mask << (uint32_t)flags << validTime << preferredTime);
+  Ipv6InterfaceAddress address;
+
+  Address addr = GetInterface (interface)->GetDevice ()->GetAddress ();
+
+  if (flags & (1<< 6)) /* auto flag */
+  {
+    /* XXX : add other L2 address case */
+    if (Mac48Address::IsMatchingType (addr))
+    {
+      address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), network));
+    }
+    else
+    {
+      NS_FATAL_ERROR ("Unknown method to make autoconfigured address for this kind of device.");
+      return;
+    }
+
+    /* see if we have already the prefix */
+    for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin () ; it != m_prefixes.end () ; ++it)
+    {
+      if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
+      {
+        (*it)->StopPreferredTimer ();
+        (*it)->StopValidTimer ();
+        (*it)->StartPreferredTimer ();
+
+        /* Suppose a link with two prefixes advertised, 
+         * when first prefix (which is the default route) expires,
+         * the second ones router has to be default router
+         */
+        GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
+        return;
+      }
+    }
+    
+    /* no prefix found, add autoconfigured address and the prefix */
+    NS_LOG_INFO ("Autoconfigured address is :" << address.GetAddress ());
+    AddAddress (interface, address);
+
+    /* add default router
+     * check to know if default route already exists is done 
+     * in Ipv6StaticRouting class
+     *
+     * If default route is already set, this function does nothing.
+     */
+    GetRoutingProtocol ()->NotifyAddRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface, network);
+
+    Ptr<Ipv6AutoconfiguredPrefix> aPrefix = CreateObject<Ipv6AutoconfiguredPrefix> (m_node, interface, network, mask, preferredTime, validTime, defaultRouter);
+    aPrefix->StartPreferredTimer ();
+
+    m_prefixes.push_back (aPrefix);
+  }
+}
+
+void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter)
+{
+  NS_LOG_FUNCTION (this << interface << network << mask);
+  Ptr<Ipv6Interface> iface = GetInterface (interface);
+  Address addr = iface->GetDevice ()->GetAddress ();
+  uint32_t max = iface->GetNAddresses ();
+  uint32_t i = 0;
+  Ipv6Address toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), network);
+
+  for (i = 0 ; i < max ; i++)
+  {
+    if (iface->GetAddress (i).GetAddress () == toFound) 
+    {
+      RemoveAddress (interface, i);
+      break;
+    }
+  }
+
+  /* remove from list of autoconfigured address */
+  for (Ipv6AutoconfiguredPrefixListI it = m_prefixes.begin () ; it != m_prefixes.end () ; ++it)
+  {
+    if ((*it)->GetInterface () == interface && (*it)->GetPrefix () == network && (*it)->GetMask () == mask)
+    {
+      *it = 0;
+      m_prefixes.erase (it);
+      break;
+    }
+  }
+
+  GetRoutingProtocol ()->NotifyRemoveRoute (Ipv6Address::GetAny (), Ipv6Prefix ((uint8_t)0), defaultRouter, interface);
+}
+
+bool Ipv6L3Protocol::AddAddress (uint32_t i, Ipv6InterfaceAddress address)
+{
+  NS_LOG_FUNCTION (this << i << address);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  bool ret = interface->AddAddress (address);
+
+  if (m_routingProtocol != 0)
+  {
+    m_routingProtocol->NotifyAddAddress (i, address);
+  }
+  return ret;
+}
+
+uint32_t Ipv6L3Protocol::GetNAddresses (uint32_t i) const
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  return interface->GetNAddresses ();
+}
+
+Ipv6InterfaceAddress Ipv6L3Protocol::GetAddress (uint32_t i, uint32_t addressIndex) const
+{
+  NS_LOG_FUNCTION (this << i << addressIndex);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  return interface->GetAddress (addressIndex);
+}
+
+bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
+{
+  NS_LOG_FUNCTION (this << i << addressIndex);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  Ipv6InterfaceAddress address = interface->RemoveAddress (addressIndex);
+  
+  if (address != Ipv6InterfaceAddress ())
+  {
+    if (m_routingProtocol != 0)
+    {
+      m_routingProtocol->NotifyRemoveAddress (i, address);
+    }
+    return true;
+  }
+  return false;
+}
+
+void Ipv6L3Protocol::SetMetric (uint32_t i, uint16_t metric) 
+{
+  NS_LOG_FUNCTION (this << i << metric);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  interface->SetMetric (metric);
+}
+
+uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const 
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  return interface->GetMetric ();
+}
+
+uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  return interface->GetDevice ()->GetMtu ();
+}
+
+bool Ipv6L3Protocol::IsUp (uint32_t i) const
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  return interface->IsUp ();
+}
+
+void Ipv6L3Protocol::SetUp (uint32_t i)
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  
+  interface->SetUp ();
+  
+  if (m_routingProtocol != 0)
+  {
+    m_routingProtocol->NotifyInterfaceUp (i);
+  }
+}
+
+void Ipv6L3Protocol::SetDown (uint32_t i)
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  
+  interface->SetDown ();
+  
+  if (m_routingProtocol != 0)
+  {
+    m_routingProtocol->NotifyInterfaceDown (i);
+  }
+}
+
+void Ipv6L3Protocol::SetupLoopback ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
+  Ptr<LoopbackNetDevice> device = 0;
+  uint32_t i = 0;
+
+  /* see if we have already an loopback NetDevice */
+  for (i = 0 ; i < m_node->GetNDevices () ; i++)
+  {
+    if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
+    {
+      break;
+    }
+  }
+
+  if (device == 0)
+  {
+    device = CreateObject<LoopbackNetDevice> ();
+    m_node->AddDevice (device);
+  }
+
+  interface->SetDevice (device);
+  interface->SetNode (m_node);
+  Ipv6InterfaceAddress ifaceAddr = Ipv6InterfaceAddress (Ipv6Address::GetLoopback (), Ipv6Prefix (128));
+  interface->AddAddress (ifaceAddr);
+  uint32_t index = AddIpv6Interface (interface);
+  Ptr<Node> node = GetObject<Node> ();
+  node->RegisterProtocolHandler (MakeCallback (&Ipv6L3Protocol::Receive, this), Ipv6L3Protocol::PROT_NUMBER, device);
+  interface->SetUp ();
+  
+  if (m_routingProtocol != 0)
+  {
+    m_routingProtocol->NotifyInterfaceUp (index);
+  }
+}
+
+bool Ipv6L3Protocol::IsForwarding (uint32_t i) const
+{
+  NS_LOG_FUNCTION (this << i);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+
+  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
+  return interface->IsForwarding ();
+}
+
+void Ipv6L3Protocol::SetForwarding (uint32_t i, bool val)
+{
+  NS_LOG_FUNCTION (this << i << val);
+  Ptr<Ipv6Interface> interface = GetInterface (i);
+  interface->SetForwarding (val);
+}
+
+void Ipv6L3Protocol::SetIpForward (bool forward)
+{
+  NS_LOG_FUNCTION (this << forward);
+  m_ipForward = forward;
+
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end (); it++)
+  {
+    (*it)->SetForwarding (forward);
+  }
+}
+
+bool Ipv6L3Protocol::GetIpForward () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_ipForward;
+}
+
+void Ipv6L3Protocol::NotifyNewAggregate ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  if (m_node == 0)
+  {
+    Ptr<Node> node = this->GetObject<Node> ();
+    // verify that it's a valid node and that
+    // the node has not been set before
+    if (node != 0)
+    {
+      this->SetNode (node);
+    }
+  }
+  Object::NotifyNewAggregate ();
+}
+
+void Ipv6L3Protocol::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  m_node = node;
+  /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */
+  SetupLoopback ();
+}
+
+void Ipv6L3Protocol::Insert (Ptr<Ipv6L4Protocol> protocol)
+{
+  NS_LOG_FUNCTION (this << protocol);
+  m_protocols.push_back (protocol);
+}
+
+void Ipv6L3Protocol::Remove (Ptr<Ipv6L4Protocol> protocol)
+{
+  NS_LOG_FUNCTION (this << protocol);
+  m_protocols.remove (protocol);
+}
+
+Ptr<Ipv6L4Protocol> Ipv6L3Protocol::GetProtocol (int protocolNumber) const
+{
+  NS_LOG_FUNCTION (this << protocolNumber);
+
+  for (L4List_t::const_iterator i = m_protocols.begin () ; i != m_protocols.end () ; ++i)
+  {
+    if ((*i)->GetProtocolNumber () == protocolNumber)
+    {
+      return *i;
+    }
+  }
+  return 0;
+}
+
+Ptr<Socket> Ipv6L3Protocol::CreateRawSocket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6RawSocketImpl> sock = CreateObject<Ipv6RawSocketImpl> ();
+  sock->SetNode (m_node);
+  m_sockets.push_back (sock);
+  return sock;
+}
+
+void Ipv6L3Protocol::DeleteRawSocket (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this << socket);
+  
+  for (SocketList::iterator it = m_sockets.begin () ; it != m_sockets.end () ; ++it)
+  {
+    if ((*it) == socket)
+    {
+      m_sockets.erase (it);
+      return;
+    }
+  }
+}
+
+Ptr<Icmpv6L4Protocol> Ipv6L3Protocol::GetIcmpv6 () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6L4Protocol> protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ());
+  
+  if (protocol)
+  {
+    return protocol->GetObject<Icmpv6L4Protocol> ();
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+void Ipv6L3Protocol::SetDefaultTtl (uint8_t ttl)
+{
+  NS_LOG_FUNCTION (this << ttl);
+  m_defaultTtl = ttl;
+}
+
+void Ipv6L3Protocol::Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
+  Ipv6Header hdr;
+  uint8_t ttl = m_defaultTtl;
+  SocketIpTtlTag tag;
+  bool found = packet->RemovePacketTag (tag);
+  
+  if (found)
+  {
+    ttl = tag.GetTtl ();
+  }
+
+  /* Handle 3 cases:
+   * 1) Packet is passed in with a route entry
+   * 2) Packet is passed in with a route entry but route->GetGateway is not set (e.g., same network)
+   * 3) route is NULL (e.g., a raw socket call or ICMPv6)
+   */
+
+  /* 1) */
+  if (route && route->GetGateway () != Ipv6Address::GetZero ())
+  {
+    NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: passed in with a route");
+    hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
+    SendRealOut (route, packet, hdr);
+    return;
+  }
+  
+  /* 2) */
+  if (route && route->GetGateway () == Ipv6Address::GetZero ())
+  {
+    NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 1: probably sent to machine on same IPv6 network");
+    /* NS_FATAL_ERROR ("This case is not yet implemented"); */
+    hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
+    SendRealOut (route, packet, hdr);
+    return;
+  }
+
+  /* 3) */
+  NS_LOG_LOGIC ("Ipv6L3Protocol::Send case 3: passed in with no route " << destination);
+  Socket::SocketErrno err;
+  uint32_t oif = 0;
+  Ptr<Ipv6Route> newRoute = 0;
+
+  hdr = BuildHeader (source, destination, protocol, packet->GetSize (), ttl);
+
+  if (!source.IsAny ())
+  {
+    int32_t index = GetInterfaceForAddress (source);
+    NS_ASSERT (index >= 0);
+    oif = index;
+  }
+
+  newRoute = m_routingProtocol->RouteOutput (packet, hdr, oif, err);
+
+  if (newRoute)
+  {
+    SendRealOut (newRoute, packet, hdr);
+  }
+  else
+  {
+    NS_LOG_WARN ("No route to host, drop!");
+    m_dropTrace (packet);
+  }
+}
+
+void Ipv6L3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
+{
+  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
+  NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
+  uint32_t interface = 0;
+  Ptr<Packet> packet = p->Copy ();
+  Ptr<Ipv6Interface> ipv6Interface = 0;
+  
+  for (Ipv6InterfaceList::const_iterator it = m_interfaces.begin () ; it != m_interfaces.end () ; it++)
+  {
+    ipv6Interface = *it;
+
+    if (ipv6Interface->GetDevice () == device)
+    {
+      if (ipv6Interface->IsUp ())
+      {
+        m_rxTrace (packet, interface);
+        break;
+      }
+      else
+      {
+        NS_LOG_LOGIC ("Dropping received packet-- interface is down");
+        m_dropTrace (packet);
+        return;
+      }
+    }
+    interface++;
+  }
+
+  Ipv6Header hdr;
+  packet->RemoveHeader (hdr);
+
+  /* forward up to IPv6 raw sockets */
+  for (SocketList::iterator it = m_sockets.begin () ; it != m_sockets.end () ; ++it)
+  {
+    Ptr<Ipv6RawSocketImpl> socket = *it;
+    socket->ForwardUp (packet, hdr, device);
+  }
+
+  m_routingProtocol->RouteInput (packet, hdr, device,
+    MakeCallback (&Ipv6L3Protocol::IpForward, this),
+    MakeCallback (&Ipv6L3Protocol::IpMulticastForward, this),
+    MakeCallback (&Ipv6L3Protocol::LocalDeliver, this),
+    MakeCallback (&Ipv6L3Protocol::RouteInputError, this)
+  );
+}
+
+void Ipv6L3Protocol::SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6Header const& ipHeader)
+{
+  NS_LOG_FUNCTION (this << route << packet << ipHeader);
+
+  packet->AddHeader (ipHeader);
+
+  if (!route)
+  {
+    NS_LOG_LOGIC ("No route to host, drop!.");
+    return;
+  }
+
+  Ptr<NetDevice> dev = route->GetOutputDevice ();
+  int32_t interface = GetInterfaceForDevice (dev);
+  NS_ASSERT (interface >= 0);
+  
+  Ptr<Ipv6Interface> outInterface = GetInterface (interface);
+  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface);
+
+  NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ());
+
+  if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ()))
+  {
+    if (outInterface->IsUp ())
+    {
+      NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
+      m_txTrace (packet, interface);
+      outInterface->Send (packet, route->GetGateway ());
+    }
+    else
+    {
+      NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
+      m_dropTrace (packet);
+    }
+  }
+  else
+  {
+    if (outInterface->IsUp ())
+    {
+       NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestinationAddress ());
+       m_txTrace (packet, interface);
+       outInterface->Send (packet, ipHeader.GetDestinationAddress ());
+    }
+    else
+    {
+      NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestinationAddress ());
+      m_dropTrace (packet);
+    }
+  }
+}
+
+void Ipv6L3Protocol::IpForward (Ptr<Ipv6Route> rtentry, Ptr<const Packet> p, const Ipv6Header& header)
+{
+  NS_LOG_FUNCTION (this << rtentry << p << header);
+  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
+  
+  // Forwarding
+  Ipv6Header ipHeader = header;
+  Ptr<Packet> packet = p->Copy ();
+  ipHeader.SetHopLimit (ipHeader.GetHopLimit () - 1);
+
+  if (ipHeader.GetSourceAddress ().IsLinkLocal ())
+  {
+    /* no forward for link-local address */
+    return;
+  }
+  
+  if (ipHeader.GetHopLimit () == 0)
+  {
+    // Do not reply to ICMPv6 or to multicast IPv6 address
+    if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER &&
+        ipHeader.GetDestinationAddress ().IsMulticast () == false)
+    {
+      packet->AddHeader (ipHeader);
+      GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT);
+    }
+    NS_LOG_WARN ("TTL exceeded.  Drop.");
+    m_dropTrace (packet);
+    return;
+  }
+
+  /* ICMPv6 Redirect */
+
+  /* if we forward to a machine on the same network as the source, 
+   * we send him an ICMPv6 redirect message to notify him that a short route 
+   * exists.
+   */
+  if ((!rtentry->GetGateway ().IsAny () && rtentry->GetGateway ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))) ||
+      (rtentry->GetDestination ().CombinePrefix (Ipv6Prefix (64)) == header.GetSourceAddress ().CombinePrefix (Ipv6Prefix (64))))
+  {
+    NS_LOG_LOGIC ("ICMPv6 redirect!");
+    Ptr<Icmpv6L4Protocol> icmpv6 = GetIcmpv6 ();
+    Address hardwareTarget;
+    Ipv6Address dst = header.GetDestinationAddress ();
+    Ipv6Address src = header.GetSourceAddress ();
+    Ipv6Address target = rtentry->GetGateway ();
+    Ptr<Packet> copy = p->Copy ();
+
+    if (target.IsAny ())
+    {
+      target = dst;
+    }
+
+    copy->AddHeader (header);
+    
+    if (icmpv6->Lookup (copy, target, rtentry->GetOutputDevice (), 0, &hardwareTarget))
+    {
+      icmpv6->SendRedirection (copy, src, target, dst, hardwareTarget);
+    }
+    else
+    {
+      icmpv6->SendRedirection (copy, src, target, dst, Address ());
+    }
+  }
+
+  SendRealOut (rtentry, packet, ipHeader);
+}
+
+void Ipv6L3Protocol::IpMulticastForward (Ptr<Ipv6MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv6Header& header)
+{
+  NS_LOG_FUNCTION (this << mrtentry << p << header);
+  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
+
+  // The output interfaces we could forward this onto are encoded
+  // in the OutputTtl of the Ipv6MulticastRoute
+  for (uint32_t i = 0 ; i < Ipv6MulticastRoute::MAX_INTERFACES ; i++)
+  {
+    if (mrtentry->GetOutputTtl (i) < Ipv6MulticastRoute::MAX_TTL)
+    {
+      Ptr<Packet> packet = p->Copy ();
+      Ipv6Header h = header;
+      h.SetHopLimit (header.GetHopLimit () - 1);
+      if (h.GetHopLimit () == 0)
+      {
+        NS_LOG_WARN ("TTL exceeded.  Drop.");
+        m_dropTrace (packet);
+        return;
+      }
+
+      NS_LOG_LOGIC ("Forward multicast via interface " << i);
+      Ptr<Ipv6Route> rtentry = Create<Ipv6Route> ();
+      rtentry->SetSource (h.GetSourceAddress ());
+      rtentry->SetDestination (h.GetDestinationAddress ());
+      rtentry->SetGateway (Ipv6Address::GetAny ());
+      rtentry->SetOutputDevice (GetNetDevice (i));
+      SendRealOut (rtentry, packet, h);
+      return;
+    }
+  }
+}
+
+void Ipv6L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv6Header const& ip, uint32_t iif)
+{
+  NS_LOG_FUNCTION (this << packet << ip << iif);
+  Ptr<Packet> p = packet->Copy ();
+  Ptr<Ipv6L4Protocol> protocol = GetProtocol (ip.GetNextHeader ());
+
+  if (protocol)
+  {
+    Ptr<Packet> copy = p->Copy ();
+    enum Ipv6L4Protocol::RxStatus_e status = protocol->Receive (p, ip.GetSourceAddress (), ip.GetDestinationAddress (), GetInterface (iif));
+
+    switch (status)
+    {
+    case Ipv6L4Protocol::RX_OK:
+      break;
+    case Ipv6L4Protocol::RX_CSUM_FAILED:
+      break;
+    case Ipv6L4Protocol::RX_ENDPOINT_UNREACH:
+      if (ip.GetDestinationAddress ().IsMulticast ())
+      {
+        /* do not rely on multicast address */
+        break;
+      }
+
+      copy->AddHeader (ip);
+      GetIcmpv6 ()->SendErrorDestinationUnreachable (copy, ip.GetSourceAddress (), Icmpv6Header::ICMPV6_PORT_UNREACHABLE);
+    }
+  }
+}
+
+void Ipv6L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno)
+{
+  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
+  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
+  m_dropTrace (p);
+}
+
+Ipv6Header Ipv6L3Protocol::BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t ttl)
+{
+  NS_LOG_FUNCTION (this << src << dst << (uint32_t)protocol << (uint32_t)payloadSize << (uint32_t)ttl);
+  Ipv6Header hdr;
+
+  hdr.SetSourceAddress (src);
+  hdr.SetDestinationAddress (dst);
+  hdr.SetNextHeader (protocol);
+  hdr.SetPayloadLength (payloadSize);
+  hdr.SetHopLimit (ttl);
+  return hdr;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-l3-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,486 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_L3_PROTOCOL_H
+#define IPV6_L3_PROTOCOL_H
+
+#include <list>
+
+#include "ns3/traced-callback.h"
+
+#include "ns3/net-device.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/ipv6-header.h"
+
+namespace ns3
+{
+
+class Node;
+class Ipv6Interface;
+class Ipv6L4Protocol;
+class Ipv6Route;
+class Ipv6MulticastRoute;
+class Ipv6RawSocketImpl;
+class Icmpv6L4Protocol;
+class Ipv6AutoconfiguredPrefix;
+
+/**
+ * \class Ipv6L3Protocol
+ * \brief IPv6 layer implementation.
+ */
+class Ipv6L3Protocol : public Ipv6
+{
+  public:
+    /** 
+     * \brief Get the type ID of this class.
+     * \return type ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief The protocol number for IPv6 (0x86DD).
+     */
+    static const uint16_t PROT_NUMBER;
+    
+    /**
+     * \brief Constructor.
+     */
+    Ipv6L3Protocol ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6L3Protocol ();
+    
+    /**
+     * \brief Set node for this stack.
+     * \param node node to set
+     */
+    void SetNode (Ptr<Node> node);
+
+    /**
+     * \brief Add an L4 protocol.
+     * \param protocol L4 protocol
+     */
+    void Insert (Ptr<Ipv6L4Protocol> protocol);
+
+    /**
+     * \brief Remove an L4 protocol.
+     * \param protocol L4 protocol to remove
+     */
+    void Remove (Ptr<Ipv6L4Protocol> protocol);
+
+    /**
+     * \brief Get L4 protocol by protocol number.
+     * \param protocolNumber protocol number
+     * \return corresponding Ipv6L4Protocol or 0 if not found
+     */
+    Ptr<Ipv6L4Protocol> GetProtocol (int protocolNumber) const;
+
+    /**
+     * \brief Create raw IPv6 socket.
+     * \return newly raw socket
+     */
+    Ptr<Socket> CreateRawSocket ();
+
+    /**
+     * \brief Remove raw IPv6 socket.
+     * \param socket socket to remove
+     */
+    void DeleteRawSocket (Ptr<Socket> socket);
+
+    /**
+     * \brief Set the default TTL.
+     * \param ttl TTL to set
+     */
+    void SetDefaultTtl (uint8_t ttl);
+
+    /**
+     * \brief Receive method when a packet arrive in the stack.
+     * This method removes IPv6 header and forward up to L4 protocol.
+     *
+     * \param device network device
+     * \param p the packet
+     * \param protocol next header value
+     * \param from address of the correspondant
+     * \param to address of the destination
+     * \param packetType type of the packet
+     */
+    void Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType);
+
+    /**
+     * \brief Higher-level layers call this method to send a packet
+     * down the stack to the MAC and PHY layers.
+     *
+     * \param packet packet to send
+     * \param source source address of packet
+     * \param destination address of packet
+     * \param protocol number of packet
+     * \param route route to take
+     */
+    void Send (Ptr<Packet> packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr<Ipv6Route> route);
+   
+    /**
+     * \brief Set routing protocol for this stack.
+     * \param routingProtocol IPv6 routing protocol to set
+     */
+    void SetRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol);
+
+    /**
+     * \brief Get current routing protocol used.
+     * \return routing protocol
+     */
+    Ptr<Ipv6RoutingProtocol> GetRoutingProtocol () const;
+
+    /**
+     * \brief Add IPv6 interface for a device.
+     * \param device net device
+     * \return interface index
+     */
+    uint32_t AddInterface (Ptr<NetDevice> device);
+
+    /**
+     * \brief Get an interface.
+     * \param i interface index
+     * \return IPv6 interface pointer
+     */
+    Ptr<Ipv6Interface> GetInterface (uint32_t i) const;
+    
+    /**
+     * \brief Get current number of interface on this stack.
+     * \return number of interface registered
+     */
+    uint32_t GetNInterfaces () const;
+
+    /**
+     * \brief Get interface index which has specified IPv6 address
+     * \param addr IPv6 address
+     * \return interface index or -1 if not found
+     */
+    int32_t GetInterfaceForAddress (Ipv6Address addr) const;
+
+    /**
+     * \brief Get interface index which match specified address/prefix.
+     * \param addr IPv6 address
+     * \param mask IPv6 prefix (mask)
+     * \return interface index or -1 if not found
+     */
+    int32_t GetInterfaceForPrefix (Ipv6Address addr, Ipv6Prefix mask) const;
+
+    /**
+     * \brief Get interface index which is on a specified net device.
+     * \param device net device
+     */
+    int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
+
+    /**
+     * \brief Add an address on interface.
+     * \param i interface index
+     * \param address to add
+     */
+    bool AddAddress (uint32_t i, Ipv6InterfaceAddress address);
+
+    /**
+     * \brief Get an address.
+     * \param interfaceIndex interface index
+     * \param addressIndex address index on the interface
+     * \return Ipv6InterfaceAddress or assert if not found
+     */
+    Ipv6InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const;
+
+    /**
+     * \brief Get number of address for an interface.
+     * \return number of address
+     */
+    uint32_t GetNAddresses (uint32_t interface) const;
+
+    /**
+     * \brief Remove an address from an interface.
+     * \param interfaceIndex interface index
+     * \param addressIndex address index on the interface
+     */
+    bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex);
+    
+    /**
+     * \brief Set metric for an interface.
+     * \param i index
+     * \param metric
+     */
+    void SetMetric (uint32_t i, uint16_t metric);
+
+    /**
+     * \brief Get metric for an interface.
+     * \param i index
+     * \return metric
+     */
+    uint16_t GetMetric (uint32_t i) const;
+
+    /**
+     * \brief Get MTU for an interface.
+     * \param i index
+     * \return MTU
+     */
+    uint16_t GetMtu (uint32_t i) const;
+
+    /**
+     * \brief Is specified interface up ?
+     * \param i interface index
+     */
+    bool IsUp (uint32_t i) const;
+
+    /**
+     * \brief Set an interface up.
+     * \param i interface index
+     */
+    void SetUp (uint32_t i);
+
+    /**
+     * \brief set an interface down.
+     * \param i interface index
+     */
+    void SetDown (uint32_t i);
+
+    /**
+     * \brief Is interface allows forwarding ?
+     * \param i interface index
+     */
+    bool IsForwarding (uint32_t i) const;
+
+    /**
+     * \brief Enable or disable forwarding on interface
+     * \param i interface index
+     * \param val true = enable forwarding, false = disable
+     */
+    void SetForwarding (uint32_t i, bool val);
+
+    /**
+     * \brief Get device by index.
+     * \param i device index on this stack
+     * \return NetDevice pointer
+     */
+    Ptr<NetDevice> GetNetDevice (uint32_t i);
+    
+    /**
+     * \brief Get ICMPv6 protocol.
+     * \return Icmpv6L4Protocol pointer
+     */
+    Ptr<Icmpv6L4Protocol> GetIcmpv6 () const;
+
+    /**
+     * \brief Add an autoconfigured address with RA information.
+     * \param interface interface index
+     * \param network network prefix
+     * \param mask network mask
+     * \param flags flags of the prefix information option (home agent, ...)
+     * \param validTime valid time of the prefix
+     * \param preferredTime preferred time of the prefix
+     * \param defaultRouter default router address
+     */
+    void AddAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, uint8_t flags, uint32_t validTime, uint32_t preferredTime, Ipv6Address defaultRouter = Ipv6Address::GetZero ());
+
+    /**
+     * \brief Remove an autoconfigured address.
+     *
+     * Typically it is used when an autoconfigured address expires.
+     * \param interface interface index
+     * \param network network prefix
+     * \param mask network mask
+     * \param defaultRouter gateway
+     */
+    void RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Address network, Ipv6Prefix mask, Ipv6Address defaultRouter);
+
+  protected:
+    /**
+     * \brief Dispose object.
+     */
+    virtual void DoDispose ();
+
+    /**
+     * \brief Notify other components connected to the node that a new stack member is now connected.
+     *
+     * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+     */
+    virtual void NotifyNewAggregate ();
+
+  private:
+    /* for unit-tests */
+    friend class Ipv6L3ProtocolTest;
+
+    typedef std::list<Ptr<Ipv6Interface> > Ipv6InterfaceList;
+    typedef std::list<Ptr<Ipv6RawSocketImpl> > SocketList;
+    typedef std::list<Ptr<Ipv6L4Protocol> > L4List_t;
+
+    typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> > Ipv6AutoconfiguredPrefixList;
+    typedef std::list< Ptr<Ipv6AutoconfiguredPrefix> >::iterator Ipv6AutoconfiguredPrefixListI;
+
+    /**
+     * \brief Callback to trace TX (transmission) packets.
+     */ 
+    TracedCallback<Ptr<const Packet>, uint32_t> m_txTrace;
+    
+    /**
+     * \brief Callback to trace RX (reception) packets.
+     */ 
+    TracedCallback<Ptr<const Packet>, uint32_t> m_rxTrace;
+    
+    /**
+     * \brief Callback to trace drop packets.
+     */ 
+    TracedCallback<Ptr<const Packet> > m_dropTrace;
+
+    /**
+     * \brief Copy constructor.
+     * \param o object to copy
+     */
+    Ipv6L3Protocol (const Ipv6L3Protocol& o);
+    
+    /**
+     * \brief Copy constructor.
+     * \param o object to copy
+     */
+    Ipv6L3Protocol &operator = (const Ipv6L3Protocol& o);
+
+    /**
+     * \brief Construct an IPv6 header.
+     * \param src source IPv6 address
+     * \param dst destination IPv6 address
+     * \param protocol L4 protocol
+     * \param payloadSize payload size
+     * \param ttl TTL
+     * \return newly created IPv6 header
+     */
+    Ipv6Header BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol,
+                            uint16_t payloadSize, uint8_t ttl);
+
+    /**
+     * \brief Send packet with route.
+     * \param route route 
+     * \param packet packet to send
+     * \param ipHeader IPv6 header to add to the packet
+     */
+    void SendRealOut (Ptr<Ipv6Route> route, Ptr<Packet> packet, Ipv6Header const& ipHeader);
+
+    /**
+     * \brief Forward a packet.
+     * \param rtentry route 
+     * \param p packet to forward
+     * \param header IPv6 header to add to the packet
+     */
+    void IpForward (Ptr<Ipv6Route> rtentry, Ptr<const Packet> p, const Ipv6Header& header);
+
+    /**
+     * \brief Forward a packet in multicast.
+     * \param mrtentry route 
+     * \param p packet to forward
+     * \param header IPv6 header to add to the packet
+     */
+    void IpMulticastForward (Ptr<Ipv6MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv6Header& header);
+
+    /**
+     * \brief Deliver a packet.
+     * \param p packet delivered
+     * \param ip IPv6 header
+     * \param iif input interface packet was received
+     */
+    void LocalDeliver (Ptr<const Packet> p, Ipv6Header const& ip, uint32_t iif);
+    
+    /**
+     * \brief Fallback when no route is found.
+     * \param p packet
+     * \param ipHeader IPv6 header
+     * \param sockErrno error number
+     */
+    void RouteInputError (Ptr<const Packet> p, const Ipv6Header& ipHeader, Socket::SocketErrno sockErrno);
+
+    /**
+     * \brief Add an IPv6 interface to the stack.
+     * \param interface interface to add
+     * \return index of newly added interface
+     */
+    uint32_t AddIpv6Interface (Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Setup loopback interface.
+     */
+    void SetupLoopback ();
+
+    /**
+     * \brief Set IPv6 forwarding state.
+     * \param forward IPv6 forwarding enabled or not
+     */
+    virtual void SetIpForward (bool forward);
+
+    /**
+     * \brief Get IPv6 forwarding state.
+     * \return forwarding state (enabled or not)
+     */
+    virtual bool GetIpForward () const;
+
+    /**
+     * \brief Node attached to stack.
+     */
+    Ptr<Node> m_node;
+
+    /**
+     * \brief Forwarding packets (i.e. router mode) state.
+     */
+    bool m_ipForward;
+
+    /**
+     * \brief List of transport protocol.
+     */
+    L4List_t m_protocols;
+
+    /**
+     * \brief List of IPv6 interfaces.
+     */
+    Ipv6InterfaceList m_interfaces;
+
+    /**
+     * \brief Number of IPv6 interfaces managed by the stack.
+     */
+    uint32_t m_nInterfaces;
+
+    /**
+     * \brief Default TTL for outgoing packets.
+     */
+    uint8_t m_defaultTtl;
+
+    /**
+     * \brief Routing protocol.
+     */
+    Ptr<Ipv6RoutingProtocol> m_routingProtocol;
+
+    /**
+     * \brief List of IPv6 raw sockets.
+     */
+    SocketList m_sockets;
+
+    /**
+     * \brief List of IPv6 prefix received from RA.
+     */
+    Ipv6AutoconfiguredPrefixList m_prefixes;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_L3_PROTOCOL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-l4-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,52 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ipv6-l4-protocol.h"
+#include "ns3/uinteger.h"
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6L4Protocol);
+
+TypeId Ipv6L4Protocol::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6L4Protocol")
+    .SetParent<Object> ()
+    .AddAttribute ("ProtocolNumber", "The IPv6 protocol number.",
+        UintegerValue (0),
+        MakeUintegerAccessor (&Ipv6L4Protocol::GetProtocolNumber),
+        MakeUintegerChecker<int> ())
+    ;
+  return tid;
+}
+
+Ipv6L4Protocol::~Ipv6L4Protocol ()
+{
+}
+
+void Ipv6L4Protocol::ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                                  uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                                  Ipv6Address payloadSource, Ipv6Address payloadDestination,
+                                  const uint8_t* payload)
+{}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-l4-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,106 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_L4_PROTOCOL_H
+#define IPV6_L4_PROTOCOL_H
+
+#include "ns3/object.h"
+#include "ipv6-interface.h"
+
+namespace ns3
+{
+
+class Packet;
+class Ipv6Address;
+class TraceContext;
+
+/**
+ * \class Ipv6L4Protocol
+ * \brief IPv6 L4 protocol abstract class
+ */
+class Ipv6L4Protocol : public Object
+{
+  public:
+   /**
+     * \enum RxStatus_e
+     * \brief Status of receive.
+     */
+    enum RxStatus_e 
+    {
+      RX_OK,
+      RX_CSUM_FAILED,
+      RX_ENDPOINT_UNREACH
+    };
+
+    /**
+     * \brief Get the type identificator.
+     * \return type identificator
+     */
+    static TypeId GetTypeId (void);
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6L4Protocol ();
+
+    /**
+     * \brief Get the protocol number.
+     * \return protocol number
+     */
+    virtual int GetProtocolNumber () const = 0;
+
+    /**
+     * \brief Receive method.
+     *
+     * Called from lower-level layers to send the packet up
+     * in the stack.
+     * \param p packet to forward up
+     * \param src source address of packet received
+     * \param dst address of packet received
+     * \param incomingInterface the Ipv6Interface on which the packet arrived
+     * \return status (OK, destination unreachable or checksum failed)
+     */
+    virtual enum RxStatus_e Receive (Ptr<Packet> p, Ipv6Address const &src, Ipv6Address const &dst, Ptr<Ipv6Interface> incomingInterface) = 0;
+
+    /**
+     * \param icmpSource the source address of the ICMPv6 message
+     * \param icmpTtl the ttl of the ICMPv6 message
+     * \param icmpType the 'type' field of the ICMPv6 message
+     * \param icmpCode the 'code' field of the ICMPv6 message
+     * \param icmpInfo extra information dependent on the ICMPv6 message
+     *        generated by Icmpv6L4Protocol
+     * \param payloadSource the source address of the packet which triggered
+     *        the ICMPv6 message
+     * \param payloadDestination the destination address of the packet which
+     *        triggered the ICMPv6 message.
+     * \param payload the first 8 bytes of the UDP header of the packet
+     *        which triggered the ICMPv6 message.
+     */
+    virtual void ReceiveIcmp (Ipv6Address icmpSource, uint8_t icmpTtl,
+                            uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo,
+                            Ipv6Address payloadSource, Ipv6Address payloadDestination,
+                            const uint8_t* payload);
+
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_L4_PROTOCOL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-raw-socket-factory-impl.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,16 @@
+#include "ipv6-raw-socket-factory-impl.h"
+#include "ipv6-l3-protocol.h"
+#include "ns3/socket.h"
+
+namespace ns3
+{
+
+Ptr<Socket> Ipv6RawSocketFactoryImpl::CreateSocket ()
+{
+  Ptr<Ipv6L3Protocol> ipv6 = GetObject<Ipv6L3Protocol> ();
+  Ptr<Socket> socket = ipv6->CreateRawSocket ();
+  return socket;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-raw-socket-factory-impl.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,25 @@
+#ifndef IPV6_RAW_SOCKET_FACTORY_IMPL_H
+#define IPV6_RAW_SOCKET_FACTORY_IMPL_H
+
+#include "ns3/ipv6-raw-socket-factory.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6RawSocketFactoryImpl
+ * \brief Implementation of IPv6 raw socket factory.
+ */
+class Ipv6RawSocketFactoryImpl : public Ipv6RawSocketFactory
+{
+public:
+  /**
+   * \brief Create a raw IPv6 socket.
+   */
+  virtual Ptr<Socket> CreateSocket ();
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_RAW_SOCKET_FACTORY_IMPL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-raw-socket-impl.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,338 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/inet6-socket-address.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+#include "ns3/ipv6-route.h"
+#include "ns3/ipv6-routing-protocol.h"
+
+#include "ipv6-l3-protocol.h"
+
+#include "icmpv6-header.h"
+#include "icmpv6-l4-protocol.h"
+#include "ipv6-raw-socket-impl.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6RawSocketImpl");
+
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6RawSocketImpl);
+
+TypeId Ipv6RawSocketImpl::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6RawSocketImpl")
+    .SetParent<Socket> ()
+    .AddAttribute ("Protocol", "Protocol number to match.", 
+        UintegerValue (0),
+        MakeUintegerAccessor (&Ipv6RawSocketImpl::m_protocol),
+        MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("IcmpFilter", "Any ICMPv6 header whose type field matches a bit in this filter is dropped.",
+        UintegerValue (0),
+        MakeUintegerAccessor (&Ipv6RawSocketImpl::m_icmpFilter),
+        MakeUintegerChecker<uint32_t> ())
+    ;
+    return tid;
+}
+
+Ipv6RawSocketImpl::Ipv6RawSocketImpl ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_err = Socket::ERROR_NOTERROR;
+  m_node = 0;
+  m_src = Ipv6Address::GetAny ();
+  m_dst = Ipv6Address::GetAny ();
+  m_protocol = 0;
+  m_shutdownSend = false;
+  m_shutdownRecv = false;
+}
+
+Ipv6RawSocketImpl::~Ipv6RawSocketImpl ()
+{
+}
+
+void Ipv6RawSocketImpl::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  Socket::DoDispose ();
+}
+
+void Ipv6RawSocketImpl::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  m_node = node;
+}
+
+Ptr<Node> Ipv6RawSocketImpl::GetNode () const
+{
+  return m_node;
+}
+
+enum Socket::SocketErrno Ipv6RawSocketImpl::GetErrno () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_err;
+}
+
+int Ipv6RawSocketImpl::Bind (const Address& address)
+{
+  NS_LOG_FUNCTION (this << address);
+
+  if (!Inet6SocketAddress::IsMatchingType (address))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+  Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (address);
+  m_src = ad.GetIpv6 ();
+  return 0;
+}
+
+int Ipv6RawSocketImpl::Bind ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_src = Ipv6Address::GetAny ();
+  return 0;
+}
+
+int Ipv6RawSocketImpl::GetSockName (Address& address) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  address = Inet6SocketAddress (m_src, 0);
+  return 0;
+}
+
+int Ipv6RawSocketImpl::Close ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  
+  if (ipv6)
+  {
+    ipv6->DeleteRawSocket (this);
+  }
+  return 0;
+}
+
+int Ipv6RawSocketImpl::ShutdownSend ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownSend = true;
+  return 0;
+}
+
+int Ipv6RawSocketImpl::ShutdownRecv ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_shutdownRecv = true;
+  return 0;
+}
+
+int Ipv6RawSocketImpl::Connect (const Address& address)
+{
+  NS_LOG_FUNCTION (this << address);
+  
+  if (!Inet6SocketAddress::IsMatchingType (address))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+
+  Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (address);
+  m_dst = ad.GetIpv6 ();
+  return 0;
+}
+
+int Ipv6RawSocketImpl::Listen ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_err = Socket::ERROR_OPNOTSUPP;
+  return -1;
+}
+
+int Ipv6RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << p << flags);
+  Inet6SocketAddress to = Inet6SocketAddress (m_dst, m_protocol);
+  return SendTo (p, flags, to);
+}
+
+int Ipv6RawSocketImpl::SendTo (Ptr<Packet> p, uint32_t flags, const Address& toAddress)
+{
+  NS_LOG_FUNCTION (this << p << flags << toAddress);
+
+  if (!Inet6SocketAddress::IsMatchingType (toAddress))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+
+  if (m_shutdownSend)
+  {
+    return 0;
+  }
+
+  Inet6SocketAddress ad = Inet6SocketAddress::ConvertFrom (toAddress);
+  Ptr<Ipv6L3Protocol> ipv6 = m_node->GetObject<Ipv6L3Protocol> ();
+  Ipv6Address dst = ad.GetIpv6 ();
+
+  if (ipv6->GetRoutingProtocol ())
+  {
+    Ipv6Header hdr;
+    hdr.SetDestinationAddress (dst);
+    SocketErrno err = ERROR_NOTERROR;
+    Ptr<Ipv6Route> route = 0;
+    uint32_t oif = 0; /* specify non-zero if bound to a source address */
+
+    if (!m_src.IsAny ())
+    {
+      int32_t index = ipv6->GetInterfaceForAddress (m_src);
+      NS_ASSERT (index >= 0);
+      oif = index;
+    }
+
+    route = ipv6->GetRoutingProtocol ()->RouteOutput (p, hdr, oif, err);
+
+    if (route)
+    {
+      NS_LOG_LOGIC ("Route exists");
+      if (m_protocol == Icmpv6L4Protocol::GetStaticProtocolNumber ())
+      {
+        /* calculate checksum here for ICMPv6 echo request (sent by ping6) 
+         * as we cannot determine source IPv6 address at application level 
+         */
+        if (*p->PeekData () == Icmpv6Header::ICMPV6_ECHO_REQUEST)
+        {
+          Icmpv6Echo hdr (1);
+          p->RemoveHeader (hdr);
+          hdr.CalculatePseudoHeaderChecksum (route->GetSource (), dst, p->GetSize () + hdr.GetSerializedSize (), Icmpv6L4Protocol::GetStaticProtocolNumber ());
+          p->AddHeader (hdr);
+        }
+      }
+
+      ipv6->Send (p, route->GetSource (), dst, m_protocol, route);
+    }
+    else
+    {
+      NS_LOG_DEBUG ("No route, dropped!");
+    }
+  }
+  return 0;
+}
+
+Ptr<Packet> Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags);
+  Address tmp;
+  return RecvFrom (maxSize, flags, tmp);
+}
+
+Ptr<Packet> Ipv6RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
+  
+  if (m_data.empty ())
+  {
+    return 0;
+  }
+
+  /* get packet */
+  struct Data data = m_data.front ();
+  m_data.pop_front ();
+
+  if (data.packet->GetSize () > maxSize)
+  {
+    Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
+    data.packet->RemoveAtStart (maxSize);
+    m_data.push_front (data);
+    return first;
+  }
+  
+  fromAddress = Inet6SocketAddress (data.fromIp, data.fromProtocol);
+  return data.packet;
+}
+
+uint32_t Ipv6RawSocketImpl::GetTxAvailable () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return 0xffffffff;
+}
+
+uint32_t Ipv6RawSocketImpl::GetRxAvailable () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint32_t rx = 0;
+
+  for (std::list<Data>::const_iterator it = m_data.begin () ; it != m_data.end () ; ++it)
+  {
+    rx+= (it->packet)->GetSize ();
+  }
+
+  return rx;
+}
+
+bool Ipv6RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv6Header hdr, Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << *p << hdr << device);
+
+  if (m_shutdownRecv)
+  {
+    return false;
+  }
+
+  if ((m_src == Ipv6Address::GetAny () || hdr.GetDestinationAddress () == m_src) && 
+     (m_dst == Ipv6Address::GetAny () || hdr.GetSourceAddress () == m_dst) &&
+     hdr.GetNextHeader () == m_protocol)
+  {
+    Ptr<Packet> copy = p->Copy ();
+    
+    if (m_protocol == Icmpv6L4Protocol::GetStaticProtocolNumber ())
+    {
+      /* filter */
+      Icmpv6Header icmpHeader;
+      copy->PeekHeader (icmpHeader);
+      uint8_t type = icmpHeader.GetType ();
+
+      if ((1 << type) & m_icmpFilter)
+      {
+        /* packet filtered */
+        return false;
+      }
+    }
+    
+    copy->AddHeader (hdr);
+    struct Data data;
+    data.packet = copy;
+    data.fromIp = hdr.GetSourceAddress ();
+    data.fromProtocol = hdr.GetNextHeader ();
+    m_data.push_back (data);
+    NotifyDataRecv ();
+    return true;
+  }
+  return false;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-raw-socket-impl.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,255 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_RAW_SOCKET_IMPL_H
+#define IPV6_RAW_SOCKET_IMPL_H
+
+#include <list>
+
+#include "ns3/socket.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/ipv6-header.h"
+
+namespace ns3
+{
+
+class NetDevice;
+class Node;
+
+/**
+ * \class Ipv6RawSocketImpl
+ * \brief IPv6 raw socket.
+ */
+class Ipv6RawSocketImpl : public Socket
+{
+  public:
+    /**
+     * \brief Get the type ID of this class.
+     * \return type ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Constructor.
+     */
+    Ipv6RawSocketImpl ();
+    
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6RawSocketImpl ();
+
+    /**
+     * \brief Set the node.
+     * \param node node to set
+     */
+    void SetNode (Ptr<Node> node);
+
+    /**
+     * \brief Get last error number.
+     * \return error number
+     */
+    virtual enum Socket::SocketErrno GetErrno () const;
+
+    /**
+     * \brief Get node.
+     * \return node associated with this raw socket.
+     */
+    virtual Ptr<Node> GetNode () const;
+
+    /**
+     * \brief Bind the socket to address.
+     * \param address bind to this address
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Bind (const Address& address);
+
+    /**
+     * \brief Bind socket.
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Bind ();
+
+    /**
+     * \brief Get socket address.
+     * \param address socket address if method success
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int GetSockName (Address& address) const;
+
+    /**
+     * \brief Close the socket.
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Close ();
+
+    /**
+     * \brief Shutdown send capability.
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int ShutdownSend ();
+
+    /**
+     * \brief Shutdown receive capability.
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int ShutdownRecv ();
+     
+    /**
+     * \brief Connect to address.
+     * \param address address
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Connect (const Address& address);
+
+    /**
+     * \brief Listen.
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Listen ();
+
+    /**
+     * \brief Get TX size available.
+     * \return TX size
+     */
+    virtual uint32_t GetTxAvailable () const;
+
+    /**
+     * \brief Get RX size available.
+     * \return RX size
+     */
+    virtual uint32_t GetRxAvailable () const;
+
+    /**
+     * \brief Send a packet.
+     * \param p packet to send
+     * \param flags additionnal flags
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int Send (Ptr<Packet> p, uint32_t flags);
+    
+    /**
+     * \brief Send a packet.
+     * \param p packet to send
+     * \param flags additionnal flags
+     * \param toAddress destination address
+     * \return 0 if success, -1 otherwise
+     */
+    virtual int SendTo (Ptr<Packet> p, uint32_t flags, const Address& toAddress);
+
+    /**
+     * \brief Receive packet.
+     * \param maxSize maximum size
+     * \param flags additionnal flags
+     * \return packet received
+     */
+    virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+    
+    /**
+     * \brief Receive packet.
+     * \param maxSize maximum size
+     * \param flags additionnal flags
+     * \param fromAddress source address
+     * \return packet received
+     */
+    virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags, Address& fromAddress);
+    
+    /**
+     * \brief Set protocol field.
+     * \param protocol protocol to set
+     */
+    void SetProtocol (uint16_t protocol);
+    
+    /**
+     * \brief Forward up to receive method.
+     * \param p packet
+     * \param hdr IPv6 header
+     * \param device device
+     * \return true if forwarded, false otherwise
+     */
+    bool ForwardUp (Ptr<const Packet> p, Ipv6Header hdr, Ptr<NetDevice> device);
+
+  private:
+    /**
+     * \struct Data
+     * \brief IPv6 raw data and additionnal information.
+     */
+    struct Data
+    {
+      Ptr<Packet> packet; /**< Packet data */
+      Ipv6Address fromIp; /**< Source address */
+      uint16_t fromProtocol; /**< Protocol used */
+    };
+
+    /**
+     * \brief Dispose object.
+     */
+    virtual void DoDispose ();
+
+    /**
+     * \brief Last error number.
+     */
+    enum Socket::SocketErrno m_err;
+    
+    /**
+     * \brief Node.
+     */
+    Ptr<Node> m_node;
+
+    /**
+     * \brief Source address.
+     */
+    Ipv6Address m_src;
+
+    /**
+     * \brief Destination address.
+     */
+    Ipv6Address m_dst;
+
+    /**
+     * \brief Protocol.
+     */
+    uint16_t m_protocol;
+
+    /**
+     * \brief Packet waiting to be processed.
+     */
+    std::list<struct Data> m_data;
+
+    /**
+     * \brief Flag to shutdown send capability.
+     */
+    bool m_shutdownSend;
+    
+    /**
+     * \brief Flag to shutdown receive capability.
+     */
+    bool m_shutdownRecv;
+
+    /**
+     * \brief ICMPv6 filter.
+     */
+    uint32_t m_icmpFilter;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_RAW_SOCKET_IMPL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ipv6-test.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,145 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/simulator.h"
+#include "ns3/test.h"
+#include "ns3/log.h"
+#include "ns3/inet6-socket-address.h"
+#include "ns3/node.h"
+#include "ns3/csma-net-device.h"
+
+#include "icmpv6-l4-protocol.h"
+#include "ipv6-interface.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6L3ProtocolTest
+ * \brief Ipv6L3Protocol unit tests.
+ */
+class Ipv6L3ProtocolTest : public Test
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6L3ProtocolTest ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6L3ProtocolTest ();
+
+    /**
+     * \brief Run unit tests for this class.
+     * \return true if all tests have passed, false otherwise
+     */
+    virtual bool RunTests ();
+};
+
+Ipv6L3ProtocolTest::Ipv6L3ProtocolTest () : Test ("Ipv6L3Protocol")
+{
+}
+
+Ipv6L3ProtocolTest::~Ipv6L3ProtocolTest ()
+{
+}
+
+bool Ipv6L3ProtocolTest::RunTests ()
+{
+  bool result = true;
+  Ptr<Node> node = CreateObject<Node> ();
+  Ptr<Ipv6L3Protocol> ipv6 = CreateObject<Ipv6L3Protocol> ();
+  Ptr<Icmpv6L4Protocol> icmpv6 = CreateObject<Icmpv6L4Protocol> ();
+  Ptr<Ipv6Interface> interface = CreateObject<Ipv6Interface> ();
+  Ptr<Ipv6Interface> interface2 = CreateObject<Ipv6Interface> ();
+  Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> ();
+  Ptr<CsmaNetDevice> device2 = CreateObject<CsmaNetDevice> ();
+  uint32_t index = 0;
+
+  /* init */
+  node->AggregateObject (ipv6);
+  node->AggregateObject (icmpv6);
+  ipv6->Insert (icmpv6);
+
+  /* first real interface (loopback is also installed) */
+  node->AddDevice (device);
+  interface->SetDevice (device);
+  interface->SetNode (node);
+  index = ipv6->AddIpv6Interface (interface);
+  NS_TEST_ASSERT_EQUAL (index, 1);
+
+  /* second interface */
+  node->AddDevice (device2);
+  interface2->SetDevice (device2);
+  interface2->SetNode (node);
+  index = ipv6->AddIpv6Interface (interface2);
+  NS_TEST_ASSERT_EQUAL (index, 2);
+
+  Ipv6InterfaceAddress ifaceAddr = interface->GetLinkLocalAddress ();
+  NS_TEST_ASSERT_EQUAL (ifaceAddr.GetAddress ().IsLinkLocal (), true);
+
+  interface->SetUp ();
+  NS_TEST_ASSERT_EQUAL (interface->GetNAddresses (), 1); /* interface has always a link-local address */
+
+  interface2->SetUp ();
+
+  Ipv6InterfaceAddress ifaceAddr1 = Ipv6InterfaceAddress ("2001:1234:5678:9000::1", Ipv6Prefix (64));
+  interface->AddAddress (ifaceAddr1);
+  Ipv6InterfaceAddress ifaceAddr2 = Ipv6InterfaceAddress ("2001:ffff:5678:9000::1", Ipv6Prefix (64));
+  interface->AddAddress (ifaceAddr2);
+
+  Ipv6InterfaceAddress ifaceAddr3 = Ipv6InterfaceAddress ("2001:ffff:5678:9001::2", Ipv6Prefix (64));
+  interface2->AddAddress (ifaceAddr3);
+
+  uint32_t num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_EQUAL (num, 3); /* 2 global addresses + link-local ones */
+
+  num = interface2->GetNAddresses ();
+  NS_TEST_ASSERT_EQUAL (num, 2); /* 1 global addresses + link-local ones */
+
+  interface->RemoveAddress (2);
+  num = interface->GetNAddresses ();
+  NS_TEST_ASSERT_EQUAL (num, 2);
+
+  Ipv6InterfaceAddress output = interface->GetAddress (1);
+  NS_TEST_ASSERT_EQUAL (ifaceAddr1, output);
+
+  index = ipv6->GetInterfaceForPrefix ("2001:1234:5678:9000::0", Ipv6Prefix (64));
+  NS_TEST_ASSERT_EQUAL (index, 1); /* link-local address is always index 0 */
+
+  index = ipv6->GetInterfaceForAddress ("2001:ffff:5678:9001::2");
+  NS_TEST_ASSERT_EQUAL (index, 2);
+
+  index = ipv6->GetInterfaceForAddress ("2001:ffff:5678:9000::1"); /* address we just remove */
+  NS_TEST_ASSERT_EQUAL (index, (uint32_t)-1);
+
+  return result;
+}
+
+static Ipv6L3ProtocolTest gIpv6L3ProtocolTest;
+
+} /* namespace ns3 */
+
+#endif /* RUN_SELF_TESTS */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ndisc-cache.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,513 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/uinteger.h"
+#include "ns3/node.h"
+
+#include "ipv6-l3-protocol.h" 
+#include "icmpv6-l4-protocol.h"
+#include "ndisc-cache.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("NdiscCache");
+
+TypeId NdiscCache::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::NdiscCache")
+    .SetParent<Object> ()
+    .AddAttribute ("UnresolvedQueueSize",
+        "Size of the queue for packets pending an NA reply.",
+        UintegerValue (DEFAULT_UNRES_QLEN),
+        MakeUintegerAccessor (&NdiscCache::m_unresQlen),
+        MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+} 
+
+NdiscCache::NdiscCache ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+NdiscCache::~NdiscCache ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Flush ();
+}
+
+void NdiscCache::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Flush ();
+  m_device = 0;
+  m_interface = 0;
+  Object::DoDispose ();
+}
+
+void NdiscCache::SetDevice (Ptr<NetDevice> device, Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << device << interface);
+  m_device = device;
+  m_interface = interface;
+}
+
+Ptr<Ipv6Interface> NdiscCache::GetInterface () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_interface;
+}
+
+Ptr<NetDevice> NdiscCache::GetDevice () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_device;
+}
+
+NdiscCache::Entry* NdiscCache::Lookup (Ipv6Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+
+  if (m_ndCache.find (dst) != m_ndCache.end ())
+  {
+    NdiscCache::Entry* entry = m_ndCache[dst];
+    return entry;
+  }
+  return 0;
+}
+
+NdiscCache::Entry* NdiscCache::Add (Ipv6Address to)
+{
+  NS_LOG_FUNCTION (this << to);
+  NS_ASSERT (m_ndCache.find (to) == m_ndCache.end ());
+
+  NdiscCache::Entry* entry = new NdiscCache::Entry (this);
+  entry->SetIpv6Address (to);
+  m_ndCache[to] = entry;
+  return entry;
+}
+
+void NdiscCache::Remove (NdiscCache::Entry* entry)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  
+  for (CacheI i = m_ndCache.begin () ; i != m_ndCache.end () ; i++)
+  {
+    if ((*i).second == entry)
+    {
+      m_ndCache.erase (i);
+      entry->ClearWaitingPacket ();
+      delete entry;
+      return;
+    }
+  }
+}
+
+void NdiscCache::Flush ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  
+  for (CacheI i = m_ndCache.begin () ; i != m_ndCache.end () ; i++)
+  {
+    delete (*i).second; /* delete the pointer NdiscCache::Entry */
+  }
+
+  m_ndCache.erase (m_ndCache.begin (), m_ndCache.end ());
+}
+
+void NdiscCache::SetUnresQlen (uint32_t unresQlen)
+{
+  NS_LOG_FUNCTION (this << unresQlen);
+  m_unresQlen = unresQlen;
+}
+
+uint32_t NdiscCache::GetUnresQlen ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_unresQlen;
+}
+
+NdiscCache::Entry::Entry (NdiscCache* nd)
+  : m_ndCache (nd),
+  m_waiting (),
+  m_router (false),
+  m_nsRetransmit (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void NdiscCache::Entry::SetRouter (bool router)
+{
+  NS_LOG_FUNCTION (this << router);
+  m_router = router;
+}
+
+bool NdiscCache::Entry::IsRouter () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_router;
+}
+
+void NdiscCache::Entry::AddWaitingPacket (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+
+  if (m_waiting.size () >= m_ndCache->GetUnresQlen ())
+  {
+    /* we store only m_unresQlen packet => first packet in first packet remove */
+    /* XXX report packet as 'dropped' */
+    m_waiting.remove (0);
+  }
+  m_waiting.push_back (p);
+}
+
+void NdiscCache::Entry::ClearWaitingPacket ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  /* XXX report packets as 'dropped' */
+  m_waiting.clear ();
+}
+
+void NdiscCache::Entry::FunctionReachableTimeout ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  this->MarkStale ();
+}
+
+void NdiscCache::Entry::FunctionRetransmitTimeout ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Icmpv6L4Protocol> icmpv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
+  Ipv6Address addr;
+
+  /* determine source address */
+  if (m_ipv6Address.IsLinkLocal ())
+  {
+    addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();;
+  }
+  else if (!m_ipv6Address.IsAny ())
+  {
+    addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
+
+    if (addr.IsAny ()) /* maybe address has expired */
+    {
+      /* delete the entry */
+      m_ndCache->Remove (this);
+      return;
+    }
+  }
+
+  if (GetNSRetransmit () < icmpv6->MAX_MULTICAST_SOLICIT)
+  {
+    IncNSRetransmit ();
+
+    icmpv6->SendNS (addr, Ipv6Address::MakeSolicitedAddress (m_ipv6Address), m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
+    /* arm the timer again */
+    StartRetransmitTimer ();
+  }
+  else
+  {
+    Ptr<Packet> malformedPacket = m_waiting.front ();
+    if (malformedPacket == 0)
+    {
+      malformedPacket = Create<Packet> ();
+    }
+
+    icmpv6->SendErrorDestinationUnreachable (malformedPacket, addr, Icmpv6Header::ICMPV6_ADDR_UNREACHABLE);
+    
+    /* delete the entry */
+    m_ndCache->Remove (this);
+  }
+}
+
+void NdiscCache::Entry::FunctionDelayTimeout ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
+  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
+  Ipv6Address addr;
+
+  this->MarkProbe ();
+
+  if (m_ipv6Address.IsLinkLocal ())
+  {
+    addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
+  }
+  else if (!m_ipv6Address.IsAny ())
+  {
+    addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
+    if (addr.IsAny ()) /* maybe address has expired */
+    {
+      /* delete the entry */
+      m_ndCache->Remove (this);
+      return;
+    }
+  }
+  else
+  {
+    /* should not happen */
+    return;
+  }
+
+  Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
+  m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
+
+  ResetNSRetransmit ();
+  IncNSRetransmit ();
+  StartProbeTimer ();
+}
+
+void NdiscCache::Entry::FunctionProbeTimeout ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  Ptr<Ipv6L3Protocol> ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject<Ipv6L3Protocol> ();
+  Ptr<Icmpv6L4Protocol> icmpv6 = ipv6->GetIcmpv6 ();
+
+  if (GetNSRetransmit () < icmpv6->MAX_UNICAST_SOLICIT)
+  {
+    Ipv6Address addr;
+
+    if (m_ipv6Address.IsLinkLocal ())
+    {
+      addr = m_ndCache->GetInterface ()->GetLinkLocalAddress ().GetAddress ();
+    }
+    else if (!m_ipv6Address.IsAny ())
+    {
+      addr = m_ndCache->GetInterface ()->GetAddressMatchingDestination (m_ipv6Address).GetAddress ();
+      if (addr.IsAny ()) /* maybe address has expired */
+      {
+        /* delete the entry */
+        m_ndCache->Remove (this);
+        return;
+      }
+    }
+    else
+    {
+      /* should not happen */
+      return;
+    }
+
+    IncNSRetransmit ();
+    /* icmpv6->SendNS (m_ndCache->GetInterface ()->GetLinkLocalAddress (), m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ()); */
+    Ptr<Packet> p = icmpv6->ForgeNS (addr, m_ipv6Address, m_ipv6Address, m_ndCache->GetDevice ()->GetAddress ());
+    m_ndCache->GetDevice ()->Send (p, this->GetMacAddress (), Ipv6L3Protocol::PROT_NUMBER);
+
+    /* arm the timer again */
+    StartProbeTimer ();
+  }
+  else
+  {
+    /* delete the entry */
+    m_ndCache->Remove (this);
+  }
+}
+
+void NdiscCache::Entry::SetIpv6Address (Ipv6Address ipv6Address)
+{
+  NS_LOG_FUNCTION (this << ipv6Address);
+  m_ipv6Address = ipv6Address;
+}
+
+uint8_t NdiscCache::Entry::GetNSRetransmit () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_nsRetransmit;
+}
+
+void NdiscCache::Entry::IncNSRetransmit ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_nsRetransmit++;
+}
+
+void NdiscCache::Entry::ResetNSRetransmit ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_nsRetransmit = 0;
+}
+
+Time NdiscCache::Entry::GetLastReachabilityConfirmation () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_lastReachabilityConfirmation;
+}
+
+void NdiscCache::Entry::UpdateLastReachabilityconfirmation ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void NdiscCache::Entry::StartReachableTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_reachableTimer.SetFunction (&NdiscCache::Entry::FunctionReachableTimeout, this);
+  m_reachableTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::REACHABLE_TIME));
+  m_reachableTimer.Schedule ();
+}
+
+void NdiscCache::Entry::StopReachableTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_reachableTimer.Cancel ();
+}
+
+void NdiscCache::Entry::StartProbeTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_probeTimer.SetFunction (&NdiscCache::Entry::FunctionProbeTimeout, this);
+  m_probeTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
+  m_probeTimer.Schedule ();
+}
+
+void NdiscCache::Entry::StopProbeTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_probeTimer.Cancel ();
+  ResetNSRetransmit ();
+}
+
+
+void NdiscCache::Entry::StartDelayTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_delayTimer.SetFunction (&NdiscCache::Entry::FunctionDelayTimeout, this);
+  m_delayTimer.SetDelay (Seconds (Icmpv6L4Protocol::DELAY_FIRST_PROBE_TIME));
+  m_delayTimer.Schedule ();
+}
+
+void NdiscCache::Entry::StopDelayTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_delayTimer.Cancel ();
+  ResetNSRetransmit ();
+}
+
+void NdiscCache::Entry::StartRetransmitTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_retransTimer.SetFunction (&NdiscCache::Entry::FunctionRetransmitTimeout, this);
+  m_retransTimer.SetDelay (MilliSeconds (Icmpv6L4Protocol::RETRANS_TIMER));
+  m_retransTimer.Schedule ();
+}
+
+void NdiscCache::Entry::StopRetransmitTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_retransTimer.Cancel ();
+  ResetNSRetransmit ();
+}
+
+void NdiscCache::Entry::MarkIncomplete (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+  m_state = INCOMPLETE;
+
+  if (p)
+  {
+    m_waiting.push_back (p);
+  }
+}
+
+std::list<Ptr<Packet> > NdiscCache::Entry::MarkReachable (Address mac)
+{
+  NS_LOG_FUNCTION (this << mac);
+  m_state = REACHABLE;
+  m_macAddress = mac;
+  return m_waiting;
+}
+
+void NdiscCache::Entry::MarkProbe ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_state = PROBE;
+}
+
+void NdiscCache::Entry::MarkStale ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_state = STALE;
+}
+
+void NdiscCache::Entry::MarkReachable ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_state = REACHABLE;
+}
+
+std::list<Ptr<Packet> > NdiscCache::Entry::MarkStale (Address mac)
+{
+  NS_LOG_FUNCTION (this << mac);
+  m_state = STALE;
+  m_macAddress = mac;
+  return m_waiting;
+}
+
+void NdiscCache::Entry::MarkDelay ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_state = DELAY;
+}
+
+bool NdiscCache::Entry::IsStale () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return (m_state == STALE);
+}
+
+bool NdiscCache::Entry::IsReachable () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return (m_state == REACHABLE);
+}
+
+bool NdiscCache::Entry::IsDelay () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return (m_state == DELAY);
+}
+
+bool NdiscCache::Entry::IsIncomplete () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return (m_state == INCOMPLETE);
+}
+
+bool NdiscCache::Entry::IsProbe () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return (m_state == PROBE);
+}
+
+Address NdiscCache::Entry::GetMacAddress () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_macAddress;
+}
+
+void NdiscCache::Entry::SetMacAddress (Address mac)
+{
+  NS_LOG_FUNCTION (this << mac);
+  m_macAddress = mac;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/ndisc-cache.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,449 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef NDISC_CACHE_H
+#define NDISC_CACHE_H
+
+#include <stdint.h>
+
+#include <list>
+
+#include "ns3/packet.h"
+#include "ns3/nstime.h"
+#include "ns3/net-device.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/ptr.h"
+#include "ns3/timer.h"
+#include "ns3/sgi-hashmap.h"
+
+#include "ipv6-interface.h"
+
+namespace ns3
+{
+
+class NetDevice;
+class Ipv6Interface;
+
+/**
+ * \class NdiscCache
+ * \brief IPv6 Neighbor Discovery cache.
+ */
+class NdiscCache : public Object
+{
+  public:
+    class Entry;
+
+    /**
+     * \brief Get the type ID
+     * \return type ID
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Default value for unres qlen.
+     */
+    static const uint32_t DEFAULT_UNRES_QLEN = 3;
+
+    /**
+     * \brief Constructor.
+     */
+    NdiscCache ();
+
+    /**
+     * \brief Destructor.
+     */
+    ~NdiscCache ();
+
+    /**
+     * \brief Get the NetDevice associated with this cache.
+     * \return NetDevice
+     */
+    Ptr<NetDevice> GetDevice () const;
+
+    /**
+     * \brief Get the Ipv6Interface associated with this cache.
+     */
+    Ptr<Ipv6Interface> GetInterface () const;
+
+    /**
+     * \brief Lookup in the cache.
+     * \param dst destination address
+     * \return the entry if found, 0 otherwise
+     */
+    NdiscCache::Entry* Lookup (Ipv6Address dst);
+
+    /**
+     * \brief Add an entry.
+     * \param to address to add
+     * \return an new Entry
+     */
+    NdiscCache::Entry* Add (Ipv6Address to);
+
+    /**
+     * \brief Delete an entry.
+     * \param entry pointer to delete from the list.
+     */
+    void Remove (NdiscCache::Entry* entry);
+
+    /**
+     * \brief Flush the cache.
+     */
+    void Flush ();
+
+    /**
+     * \brief Set the max number of waiting packet.
+     * \param unresQlen value to set
+     */
+    void SetUnresQlen (uint32_t unresQlen);
+
+    /**
+     * \brief Get the max number of waiting packet.
+     * \return max number
+     */
+    uint32_t GetUnresQlen ();
+
+    /**
+     * \brief Set the device and interface.
+     * \param device the device
+     * \param interface the IPv6 interface
+     */
+    void SetDevice (Ptr<NetDevice> device, Ptr<Ipv6Interface> interface);
+
+    /**
+     * \class Entry
+     * \brief A record that holds information about an NdiscCache entry.
+     */
+    class Entry
+    {
+      public:
+        /**
+         * \brief Constructor.
+         * \param nd The NdiscCache this entry belongs to.
+         */
+        Entry (NdiscCache* nd);
+
+        /**
+         * \brief Changes the state to this entry to INCOMPLETE.
+         * \param p packet that wait to be sent
+         */
+        void MarkIncomplete (Ptr<Packet> p);
+
+        /**
+         * \brief Changes the state to this entry to REACHABLE.
+         * \param mac MAC address
+         * \return the list of packet waiting
+         */
+        std::list<Ptr<Packet> > MarkReachable (Address mac);
+
+        /**
+         * \brief Changes the state to this entry to PROBE.
+         */
+        void MarkProbe ();
+
+        /**
+         * \brief Changes the state to this entry to STALE.
+         * \param mac L2 address
+         * \return the list of packet waiting
+         */
+        std::list<Ptr<Packet> > MarkStale (Address mac);
+
+        /**
+         * \brief Changes the state to this entry to STALE.
+         */
+        void MarkStale ();
+
+        /**
+         * \brief Changes the state to this entry to REACHABLE.
+         */
+        void MarkReachable ();
+
+        /**
+         * \brief Change the state to this entry to DELAY.
+         */
+        void MarkDelay ();
+
+        /**
+         * \brief Add a packet (or replace old value) in the queue.
+         * \param p packet to add
+         */
+        void AddWaitingPacket (Ptr<Packet> p);
+
+        /**
+         * \brief Clear the waiting packet list.
+         */
+        void ClearWaitingPacket ();
+
+        /**
+         * \brief Is the entry STALE
+         * \return true if the entry is in STALE state, false otherwise
+         */
+        bool IsStale () const;
+
+        /**
+         * \brief Is the entry REACHABLE
+         * \return true if the entry is in REACHABLE state, false otherwise
+         */
+        bool IsReachable () const;
+
+        /**
+         * \brief Is the entry DELAY
+         * \return true if the entry is in DELAY state, false otherwise
+         */
+        bool IsDelay () const;
+
+        /**
+         * \brief Is the entry INCOMPLETE
+         * \return true if the entry is in INCOMPLETE state, false otherwise
+         */
+        bool IsIncomplete () const;
+
+        /**
+         * \brief Is the entry PROBE
+         * \return true if the entry is in PROBE state, false otherwise
+         */
+        bool IsProbe () const;
+
+        /**
+         * \brief Get the MAC address of this entry.
+         * \return the L2 address
+         */
+        Address GetMacAddress () const;
+
+        /**
+         * \brief Set the MAC address of this entry.
+         * \param mac the MAC address to set
+         */
+        void SetMacAddress (Address mac);
+
+        /**
+         * \brief If the entry is a host or a router.
+         * \return true if the node is a router, 0 if it is a host
+         */
+        bool IsRouter () const;
+
+        /**
+         * \brief Set the node type.
+         * \param router true is a router, false means a host
+         */
+        void SetRouter (bool router);
+
+        /**
+         * \brief Get the number of NS retransmit.
+         * \return number of NS that have been retransmit
+         */
+        uint8_t GetNSRetransmit () const;
+
+        /**
+         * \brief Increment NS retransmit.
+         */
+        void IncNSRetransmit ();
+
+        /**
+         * \brief Reset NS retransmit (=0).
+         */
+        void ResetNSRetransmit ();
+
+        /**
+         * \brief Get the time of last reachability confirmation.
+         * \return time
+         */
+        Time GetLastReachabilityConfirmation () const;
+
+        /**
+         * \brief Update the time of last reachability confirmation.
+         */
+        void UpdateLastReachabilityconfirmation ();
+
+        /**
+         * \brief Start the reachable timer.
+         */
+        void StartReachableTimer ();
+
+        /**
+         * \brief Stop the reachable timer.
+         */
+        void StopReachableTimer ();
+
+        /**
+         * \brief Start retransmit timer.
+         */
+        void StartRetransmitTimer ();
+
+        /**
+         * \brief Stop retransmit timer.
+         */
+        void StopRetransmitTimer ();
+
+        /**
+         * \brief Start probe timer.
+         */
+        void StartProbeTimer ();
+
+        /**
+         * \brief Stop probe timer.
+         */
+        void StopProbeTimer ();
+
+        /**
+         * \brief Start delay timer.
+         */
+        void StartDelayTimer ();
+
+        /**
+         * \brief Stop delay timer.
+         */
+        void StopDelayTimer ();
+
+        /**
+         * \brief Function called when reachable timer timeout.
+         */
+        void FunctionReachableTimeout ();
+
+        /**
+         * \brief Function called when retransmit timer timeout.
+         * It verify that the NS retransmit has reached the max so discard the entry
+         * otherwise it retransmit a NS.
+         */
+        void FunctionRetransmitTimeout ();
+
+        /**
+         * \brief Function called when probe timer timeout.
+         */
+        void FunctionProbeTimeout ();
+
+        /**
+         * \brief Function called when delay timer timeout.
+         */
+        void FunctionDelayTimeout ();
+
+        /**
+         * \brief Set the IPv6 address.
+         * \param ipv6Address IPv6 address
+         */
+        void SetIpv6Address (Ipv6Address ipv6Address);
+
+      private:
+        /**
+         * \brief The IPv6 address.
+         */
+        Ipv6Address m_ipv6Address;
+
+        /**
+         * \brief The Entry state enumeration.
+         */
+        enum NdiscCacheEntryState_e
+        {
+          INCOMPLETE, /**< No mapping between IPv6 and L2 addresses */
+          REACHABLE, /**< Mapping exists between IPv6 and L2 addresses */
+          STALE, /**< Mapping is stale */
+          DELAY, /**< Try to wait contact from remote host */
+          PROBE /**< Try to contact IPv6 address to know again its L2 address */
+        };
+
+        /**
+         * \brief The state of the entry.
+         */
+        NdiscCacheEntryState_e m_state;
+
+        /**
+         * \brief the NdiscCache associated.
+         */
+        NdiscCache* m_ndCache;
+
+        /**
+         * \brief The MAC address.
+         */
+        Address m_macAddress;
+
+        /**
+         * \brief The list of packet waiting.
+         */
+        std::list<Ptr<Packet> > m_waiting;
+
+        /**
+         * \brief Type of node (router or host).
+         */
+        bool m_router;
+
+        /**
+         * \brief Reachable timer (used for NUD in REACHABLE state).
+         */
+        Timer m_reachableTimer;
+
+        /**
+         * \brief Retransmission timer (used for NUD in INCOMPLETE state).
+         */
+        Timer m_retransTimer;
+
+        /**
+         * \brief Probe timer (used for NUD in PROBE state).
+         */
+        Timer m_probeTimer;
+
+        /**
+         * \brief Delay timer (used for NUD when in DELAY state).
+         */
+        Timer m_delayTimer;
+
+        /**
+         * \brief Last time we see a reachability confirmation.
+         */
+        Time m_lastReachabilityConfirmation;
+
+        /**
+         * \brief Number of NS retransmission.
+         */
+        uint8_t m_nsRetransmit;
+    };
+
+  private:
+    typedef sgi::hash_map<Ipv6Address, NdiscCache::Entry *, Ipv6AddressHash> Cache;
+    typedef sgi::hash_map<Ipv6Address, NdiscCache::Entry *, Ipv6AddressHash>::iterator CacheI;
+
+    /**
+     * \brief Dispose this object.
+     */
+    void DoDispose ();
+
+    /**
+     * \brief The NetDevice.
+     */
+    Ptr<NetDevice> m_device;
+
+    /**
+     * \brief the interface.
+     */
+    Ptr<Ipv6Interface> m_interface;
+
+    /**
+     * A list of Entry.
+     */
+    Cache m_ndCache;
+
+    /**
+     * \brief Max number of packet stored in m_waiting.
+     */
+    uint32_t m_unresQlen;
+};
+
+} /* namespace ns3 */
+
+#endif /* NDISC_CACHE_H */
+
--- a/src/internet-stack/nsc-tcp-l4-protocol.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/nsc-tcp-l4-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -32,8 +32,10 @@
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
 #include "nsc-tcp-l4-protocol.h"
+#include "nsc-tcp-socket-impl.h"
 #include "nsc-sysctl.h"
 #include "nsc-tcp-socket-factory-impl.h"
+#include "sim_interface.h"
 
 #include "tcp-typedefs.h"
 
@@ -54,13 +56,39 @@
 /* see http://www.iana.org/assignments/protocol-numbers */
 const uint8_t NscTcpL4Protocol::PROT_NUMBER = 6;
 
-ObjectFactory
-NscTcpL4Protocol::GetDefaultRttEstimatorFactory (void)
+class NscInterfaceImpl : public ISendCallback, public IInterruptCallback 
 {
-  ObjectFactory factory;
-  factory.SetTypeId (RttMeanDeviation::GetTypeId ());
-  return factory;
+public:
+  NscInterfaceImpl (Ptr<NscTcpL4Protocol> prot);
+private:
+  virtual void send_callback(const void *data, int datalen);
+  virtual void wakeup();
+  virtual void gettime(unsigned int *, unsigned int *);
+private:
+  Ptr<NscTcpL4Protocol> m_prot;
+};
+
+NscInterfaceImpl::NscInterfaceImpl (Ptr<NscTcpL4Protocol> prot)
+  : m_prot (prot)
+{}
+
+void 
+NscInterfaceImpl::send_callback(const void *data, int datalen)
+{
+  m_prot->send_callback (data, datalen);
 }
+void 
+NscInterfaceImpl::wakeup()
+{
+  m_prot->wakeup ();
+}
+void 
+NscInterfaceImpl::gettime(unsigned int *sec, unsigned int *usec)
+{
+  m_prot->gettime (sec,usec);
+}
+
+
 
 TypeId 
 NscTcpL4Protocol::GetTypeId (void)
@@ -68,11 +96,6 @@
   static TypeId tid = TypeId ("ns3::NscTcpL4Protocol")
     .SetParent<Ipv4L4Protocol> ()
     .AddConstructor<NscTcpL4Protocol>()
-    .AddAttribute ("RttEstimatorFactory",
-                   "How RttEstimator objects are created.",
-                   ObjectFactoryValue (GetDefaultRttEstimatorFactory ()),
-                   MakeObjectFactoryAccessor (&NscTcpL4Protocol::m_rttFactory),
-                   MakeObjectFactoryChecker ())
     .AddAttribute ("SocketList", "The list of sockets associated to this protocol.",
                    ObjectVectorValue (),
                    MakeObjectVectorAccessor (&NscTcpL4Protocol::m_sockets),
@@ -95,6 +118,7 @@
 NscTcpL4Protocol::NscTcpL4Protocol ()
   : m_endPoints (new Ipv4EndPointDemux ()),
     m_nscStack (0),
+    m_nscInterface (new NscInterfaceImpl (this)),
     m_softTimer (Timer::CANCEL_ON_DESTROY)
 {
   m_dlopenHandle = NULL;
@@ -139,7 +163,7 @@
 
   FCreateStack create = (FCreateStack)dlsym(m_dlopenHandle, "nsc_create_stack");
   NS_ASSERT(create);
-  m_nscStack = create(this, this, external_rand);
+  m_nscStack = create(m_nscInterface, m_nscInterface, external_rand);
   int hzval = m_nscStack->get_hz();
 
   NS_ASSERT(hzval > 0);
@@ -212,6 +236,8 @@
       m_endPoints = 0;
     }
   m_node = 0;
+  delete m_nscInterface;
+  m_nscInterface = 0;
   Ipv4L4Protocol::DoDispose ();
 }
 
@@ -220,11 +246,9 @@
 {
   NS_LOG_FUNCTION (this);
 
-  Ptr<RttEstimator> rtt = m_rttFactory.Create<RttEstimator> ();
   Ptr<NscTcpSocketImpl> socket = CreateObject<NscTcpSocketImpl> ();
   socket->SetNode (m_node);
   socket->SetTcp (this);
-  socket->SetRtt (rtt);
   m_sockets.push_back (socket);
   return socket;
 }
--- a/src/internet-stack/nsc-tcp-l4-protocol.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/nsc-tcp-l4-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -23,27 +23,27 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/ptr.h"
 #include "ns3/object-factory.h"
-#include "ipv4-end-point-demux.h"
+#include "ns3/timer.h"
 #include "ipv4-l4-protocol.h"
-#include "ipv4-interface.h"
 
-#include "tcp-header.h"
-
-#include "ns3/timer.h"
-#include "sim_interface.h"
-#include "nsc-tcp-socket-impl.h"
+struct INetStack;
 
 namespace ns3 {
 
 class Node;
 class Socket;
-class TcpHeader;
+class Ipv4EndPointDemux;
+class Ipv4Interface;
+class NscTcpSocketImpl;
+class Ipv4EndPoint;
+class NscInterfaceImpl;
+
 /**
  * \ingroup nsctcp
  * 
  * \brief Nsc wrapper glue, to interface with the Ipv4 protocol underneath.
  */
-class NscTcpL4Protocol : public Ipv4L4Protocol, ISendCallback, IInterruptCallback {
+class NscTcpL4Protocol : public Ipv4L4Protocol {
 public:
   static const uint8_t PROT_NUMBER;
   static TypeId GetTypeId (void);
@@ -86,6 +86,10 @@
                                             Ipv4Address const &destination,
                                             Ptr<Ipv4Interface> incomingInterface);
 
+protected:
+  virtual void DoDispose (void);
+  virtual void NotifyNewAggregate ();
+private:
   // NSC callbacks.
   // NSC invokes these hooks to interact with the simulator.
   // In any case, these methods are only to be called by NSC.
@@ -93,29 +97,23 @@
   // send_callback is invoked by NSCs 'ethernet driver' to re-inject
   // a packet (i.e. an octet soup consisting of an IP Header, TCP Header
   // and user payload, if any), into ns-3.
-  virtual void send_callback(const void *data, int datalen);
+  void send_callback(const void *data, int datalen);
   // This is called by the NSC stack whenever something of interest
   // has happened, e.g. when data arrives on a socket, a listen socket
   // has a new connection pending, etc.
-  virtual void wakeup();
+  void wakeup();
   // This is called by the Linux stack RNG initialization.
   // Its also used by the cradle code to add a timestamp to
   // printk/printf/debug output.
-  virtual void gettime(unsigned int *, unsigned int *);
-
-protected:
-  virtual void DoDispose (void);
-  virtual void NotifyNewAggregate ();
-private:
+  void gettime(unsigned int *sec, unsigned int *usec);
+  void AddInterface (void);
+  void SoftInterrupt (void);
+  friend class NscInterfaceImpl;
+  friend class NscTcpSocketImpl;
   Ptr<Node> m_node;
   Ipv4EndPointDemux *m_endPoints;
-  ObjectFactory m_rttFactory;
-private:
-  void AddInterface (void);
-  void SoftInterrupt (void);
-  static ObjectFactory GetDefaultRttEstimatorFactory (void);
-  friend class NscTcpSocketImpl;
   INetStack* m_nscStack;
+  NscInterfaceImpl *m_nscInterface;
   void *m_dlopenHandle;
   std::string m_nscLibrary;
   Timer m_softTimer;
--- a/src/internet-stack/nsc-tcp-socket-impl.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/nsc-tcp-socket-impl.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -74,7 +74,6 @@
     m_state (CLOSED),
     m_closeOnEmpty (false),
     m_txBufferSize (0),
-    m_rtt (0),
     m_lastMeasuredRtt (Seconds(0.0))
 {
   NS_LOG_FUNCTION (this);
@@ -104,7 +103,6 @@
     m_cWnd (sock.m_cWnd),
     m_ssThresh (sock.m_ssThresh),
     m_initialCWnd (sock.m_initialCWnd),
-    m_rtt (0),
     m_lastMeasuredRtt (Seconds(0.0)),
     m_cnTimeout (sock.m_cnTimeout),
     m_cnCount (sock.m_cnCount),
@@ -119,11 +117,6 @@
     {
       m_txBuffer = sock.m_txBuffer;
     }
-  //copy the rtt if necessary
-  if (sock.m_rtt)
-    {
-      m_rtt = sock.m_rtt->Copy();
-    }
   //can't "copy" the endpoint just yes, must do this when we know the peer info
   //too; this is in SYN_ACK_TX
 }
@@ -165,11 +158,6 @@
   m_nscTcpSocket = tcp->m_nscStack->new_tcp_socket();
   m_tcp = tcp;
 }
-void 
-NscTcpSocketImpl::SetRtt (Ptr<RttEstimator> rtt)
-{
-  m_rtt = rtt;
-}
 
 
 enum Socket::SocketErrno
--- a/src/internet-stack/nsc-tcp-socket-impl.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/nsc-tcp-socket-impl.h	Wed Aug 26 15:29:03 2009 +0400
@@ -30,7 +30,8 @@
 #include "tcp-typedefs.h"
 #include "pending-data.h"
 #include "sequence-number.h"
-#include "rtt-estimator.h"
+
+struct INetStreamSocket;
 
 namespace ns3 {
 
@@ -63,7 +64,6 @@
 
   void SetNode (Ptr<Node> node);
   void SetTcp (Ptr<NscTcpL4Protocol> tcp);
-  void SetRtt (Ptr<RttEstimator> rtt);
 
   virtual enum SocketErrno GetErrno (void) const;
   virtual Ptr<Node> GetNode (void) const;
@@ -158,7 +158,6 @@
   uint32_t                       m_initialCWnd;          //Initial cWnd value
 
   // Round trip time estimation
-  Ptr<RttEstimator> m_rtt;
   Time m_lastMeasuredRtt;
 
   // Timer-related members
--- a/src/internet-stack/sgi-hashmap.h	Tue Aug 25 20:12:53 2009 +0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/* This code snippet was ripped out of the gcc 
- * documentation and slightly modified to work
- * with gcc 4.x
- */
-#ifndef SGI_HASHMAP_H
-#define SGI_HASHMAP_H
-
-/* To use gcc extensions.
- */
-#ifdef __GNUC__
-  #if __GNUC__ < 3
-     #include <hash_map.h>
-namespace sgi { using ::hash_map; }; // inherit globals
-  #else 
-     #if __GNUC__ < 4
-       #include <ext/hash_map>
-       #if __GNUC_MINOR__ == 0
-namespace sgi = std;         // GCC 3.0
-       #else
-namespace sgi = ::__gnu_cxx;       // GCC 3.1 and later
-       #endif
-     #else  // gcc 4.x and later
-       #if __GNUC_MINOR__ < 3
-       #include <ext/hash_map>
-namespace sgi = ::__gnu_cxx;
-       #else
-#undef __DEPRECATED
-       #include <backward/hash_map>
-namespace sgi = ::__gnu_cxx;
-       #endif
-     #endif
-  #endif
-#else      // ...  there are other compilers, right?
-namespace sgi = std;
-#endif
-
-
-#endif /* SGI_HASHMAP_H */
--- a/src/internet-stack/tcp-l4-protocol.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/tcp-l4-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -34,7 +34,8 @@
 #include "ipv4-end-point.h"
 #include "ipv4-l3-protocol.h"
 #include "tcp-socket-factory-impl.h"
-
+#include "tcp-socket-impl.h"
+#include "rtt-estimator.h"
 #include "tcp-typedefs.h"
 
 #include <vector>
@@ -558,17 +559,18 @@
 }
 
 void
-TcpL4Protocol::SendPacket (Ptr<Packet> packet, TcpHeader outgoingHeader,
+TcpL4Protocol::SendPacket (Ptr<Packet> packet, const TcpHeader &outgoing,
                                Ipv4Address saddr, Ipv4Address daddr)
 {
   NS_LOG_LOGIC("TcpL4Protocol " << this
-              << " sending seq " << outgoingHeader.GetSequenceNumber()
-              << " ack " << outgoingHeader.GetAckNumber()
-              << " flags " << std::hex << (int)outgoingHeader.GetFlags() << std::dec
+              << " sending seq " << outgoing.GetSequenceNumber()
+              << " ack " << outgoing.GetAckNumber()
+              << " flags " << std::hex << (int)outgoing.GetFlags() << std::dec
               << " data size " << packet->GetSize());
   NS_LOG_FUNCTION (this << packet << saddr << daddr);
   // XXX outgoingHeader cannot be logged
 
+  TcpHeader outgoingHeader = outgoing;
   outgoingHeader.SetLength (5); //header length in units of 32bit words
   /* outgoingHeader.SetUrgentPointer (0); //XXX */
   if(Node::ChecksumEnabled ())
--- a/src/internet-stack/tcp-l4-protocol.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/tcp-l4-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -27,19 +27,17 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/ptr.h"
 #include "ns3/object-factory.h"
-#include "ipv4-end-point-demux.h"
 #include "ipv4-l4-protocol.h"
-#include "ipv4-interface.h"
-
-#include "tcp-socket-impl.h"
-#include "tcp-header.h"
-#include "tcp-typedefs.h"
 
 namespace ns3 {
 
 class Node;
 class Socket;
 class TcpHeader;
+class Ipv4EndPointDemux;
+class Ipv4Interface;
+class TcpSocketImpl;
+class Ipv4EndPoint;
 
 /**
  * \ingroup tcp
@@ -120,7 +118,7 @@
   ObjectFactory m_rttFactory;
 private:
   friend class TcpSocketImpl;
-  void SendPacket (Ptr<Packet>, TcpHeader,
+  void SendPacket (Ptr<Packet>, const TcpHeader &,
                   Ipv4Address, Ipv4Address);
   static ObjectFactory GetDefaultRttEstimatorFactory (void);
 
--- a/src/internet-stack/tcp-socket-impl.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/tcp-socket-impl.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -36,6 +36,8 @@
 #include "tcp-socket-impl.h"
 #include "tcp-l4-protocol.h"
 #include "ipv4-end-point.h"
+#include "tcp-header.h"
+#include "rtt-estimator.h"
 
 #include <algorithm>
 
--- a/src/internet-stack/tcp-test.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/tcp-test.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -31,17 +31,18 @@
 #include "ns3/simple-net-device.h"
 #include "ns3/drop-tail-queue.h"
 #include "ns3/config.h"
+#include "ns3/ipv4-static-routing.h"
+#include "ns3/ipv4-list-routing.h"
+#include "ns3/node.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
+
 #include "ipv4-end-point.h"
 #include "arp-l3-protocol.h"
 #include "ipv4-l3-protocol.h"
 #include "icmpv4-l4-protocol.h"
 #include "udp-l4-protocol.h"
 #include "tcp-l4-protocol.h"
-#include "ns3/ipv4-static-routing.h"
-#include "ns3/ipv4-list-routing.h"
-
-#include "ns3/node.h"
-#include "ns3/inet-socket-address.h"
 
 #include <string>
 
--- a/src/internet-stack/udp-l4-protocol.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/udp-l4-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -26,7 +26,6 @@
 #include "ns3/packet.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/ptr.h"
-#include "ipv4-end-point-demux.h"
 #include "ipv4-l4-protocol.h"
 
 namespace ns3 {
@@ -34,6 +33,8 @@
 class Node;
 class Socket;
 class Ipv4Route;
+class Ipv4EndPointDemux;
+class Ipv4EndPoint;
 /**
  * \ingroup udp
  * \brief Implementation of the UDP protocol
--- a/src/internet-stack/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/internet-stack/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -99,6 +99,18 @@
         'icmpv4.cc',
         'icmpv4-l4-protocol.cc',
         'loopback-net-device.cc',
+        'ipv6-interface.cc',
+        'ndisc-cache.cc',
+        'icmpv6-header.cc',
+        'ipv6-l3-protocol.cc',
+        'ipv6-end-point.cc',
+        'ipv6-end-point-demux.cc',
+        'ipv6-l4-protocol.cc',
+        'ipv6-raw-socket-factory-impl.cc',
+        'ipv6-raw-socket-impl.cc',
+        'ipv6-autoconfigured-prefix.cc',
+        'icmpv6-l4-protocol.cc',
+        'ipv6-test.cc'
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -108,11 +120,20 @@
         'tcp-header.h',
         'sequence-number.h',
         'icmpv4.h',
-        ]
+        'icmpv6-header.h',
+        'ipv4-l3-protocol.h',
+        'arp-l3-protocol.h',
+        'udp-l4-protocol.h',
+        'tcp-l4-protocol.h',
+        'icmpv4-l4-protocol.h',
+        'ipv4-l4-protocol.h',
+        'arp-cache.h',
+       ]
 
     if bld.env['NSC_ENABLED']:
         obj.source.append ('nsc-tcp-socket-impl.cc')
         obj.source.append ('nsc-tcp-l4-protocol.cc')
         obj.source.append ('nsc-tcp-socket-factory-impl.cc')
         obj.source.append ('nsc-sysctl.cc')
+        headers.source.append('nsc-tcp-l4-protocol.h')
         obj.uselib = 'DL'
--- a/src/node/inet6-socket-address.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/inet6-socket-address.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -24,31 +24,31 @@
 namespace ns3 {
 
 Inet6SocketAddress::Inet6SocketAddress (Ipv6Address ipv6, uint16_t port)
-: m_ipv6(ipv6),
+  : m_ipv6(ipv6),
   m_port(port)
 {
 }
 
 Inet6SocketAddress::Inet6SocketAddress (Ipv6Address ipv6)
-: m_ipv6(ipv6),
+  : m_ipv6(ipv6),
   m_port(0)
 {
 }
 
-  Inet6SocketAddress::Inet6SocketAddress (const char* ipv6, uint16_t port)
-: m_ipv6(Ipv6Address(ipv6)),
+Inet6SocketAddress::Inet6SocketAddress (const char* ipv6, uint16_t port)
+  : m_ipv6(Ipv6Address(ipv6)),
   m_port(port)
 {
 }
 
-  Inet6SocketAddress::Inet6SocketAddress (const char* ipv6)
-: m_ipv6(Ipv6Address(ipv6)),
+Inet6SocketAddress::Inet6SocketAddress (const char* ipv6)
+  : m_ipv6(Ipv6Address(ipv6)),
   m_port(0)
 {
 }
 
-  Inet6SocketAddress::Inet6SocketAddress (uint16_t port)
-: m_ipv6(Ipv6Address::GetAny()),
+Inet6SocketAddress::Inet6SocketAddress (uint16_t port)
+  : m_ipv6(Ipv6Address::GetAny()),
   m_port(port)
 {
 }
--- a/src/node/ipv4-address.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv4-address.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -18,6 +18,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
+#include <stdlib.h>
 #include "ns3/log.h"
 #include "ipv4-address.h"
 #include "ns3/assert.h"
@@ -28,26 +29,29 @@
 
 #define ASCII_DOT (0x2e)
 #define ASCII_ZERO (0x30)
+#define ASCII_SLASH (0x2f)
 
 static uint32_t 
 AsciiToIpv4Host (char const *address)
 {
   uint32_t host = 0;
-  while (true) {
-    uint8_t byte = 0;
-    while (*address != ASCII_DOT &&
-           *address != 0) {
-      byte *= 10;
-      byte += *address - ASCII_ZERO;
+  while (true) 
+    {
+      uint8_t byte = 0;
+      while (*address != ASCII_DOT && *address != 0) 
+        {
+          byte *= 10;
+          byte += *address - ASCII_ZERO;
+          address++;
+        }
+      host <<= 8;
+      host |= byte;
+      if (*address == 0) 
+        {
+          break;
+        }
       address++;
     }
-    host <<= 8;
-    host |= byte;
-    if (*address == 0) {
-      break;
-    }
-    address++;
-  }
   return host;
 }
 
@@ -63,9 +67,18 @@
 Ipv4Mask::Ipv4Mask (uint32_t mask)
   : m_mask (mask)
 {}
+
 Ipv4Mask::Ipv4Mask (char const *mask)
 {
-  m_mask = AsciiToIpv4Host (mask);
+  if (*mask == ASCII_SLASH)
+    {
+      m_mask = static_cast<uint32_t> (atoi (++mask));
+      NS_ASSERT (m_mask <= 32);
+    }
+  else
+    {
+      m_mask = AsciiToIpv4Host (mask);
+    }
 }
 
 bool 
@@ -133,6 +146,20 @@
   return ones;
 }
 
+uint16_t
+Ipv4Mask::GetPrefixLength (void) const
+{
+  uint16_t tmp = 0;
+  uint32_t mask = m_mask;
+  while (mask != 0 ) 
+  {
+    mask = mask << 1;
+    tmp++;
+  }
+  return tmp; 
+}
+
+
 Ipv4Address::Ipv4Address ()
   : m_address (0x66666666)
 {}
--- a/src/node/ipv4-address.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv4-address.h	Wed Aug 26 15:29:03 2009 +0400
@@ -198,11 +198,26 @@
  * \ingroup address
  *
  * \brief a class to represent an Ipv4 address mask
+ * 
+ * The constructor takes arguments according to a few formats. 
+ * Ipv4Mask ("255.255.255.255"), Ipv4Mask ("/32"), and Ipv4Mask (0xffffffff)
+ * are all equivalent.
  */
 class Ipv4Mask {
 public:
+  /**
+   * Will initialize to a garbage value (0x66666666)
+   */
   Ipv4Mask ();
+  /**
+   * param mask bitwise integer representation of the mask
+   * 
+   * For example, the integer input 0xffffff00 yields a 24-bit mask
+   */
   Ipv4Mask (uint32_t mask);
+  /**
+   * \param mask String constant either in "255.255.255.0" or "/24" format
+   */
   Ipv4Mask (char const *mask);
   /**
    * \param a first address to compare
@@ -238,6 +253,10 @@
    */
   void Print (std::ostream &os) const;
   /**
+   * \return the prefix length of mask (the yy in x.x.x.x/yy notation)
+   */
+  uint16_t GetPrefixLength (void) const;
+  /**
    * \return the 255.0.0.0 mask corresponding to a typical loopback address
    */
   static Ipv4Mask GetLoopback (void);
--- a/src/node/ipv6-address.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv6-address.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -74,13 +74,13 @@
       a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
       b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
       c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
-      mix(a,b,c);
+      mix(a, b, c);
       k += 12; len -= 12;
     }
 
     /*------------------------------------- handle the last 11 bytes */
     c += length;
-    switch(len)              /* all the case statements fall through */
+    switch (len)              /* all the case statements fall through */
     {
       case 11: c+=((ub4)k[10]<<24);
       case 10: c+=((ub4)k[9]<<16);
@@ -96,7 +96,7 @@
       case 1 : a+=k[0];
                /* case 0: nothing left to add */
     }
-    mix(a,b,c);
+    mix(a, b, c);
     /*-------------------------------------------- report the result */
     return c;
   }
@@ -119,7 +119,7 @@
   int ch, seen_xdigits;
   unsigned int val;
 
-  memset((tp = tmp), '\0', 16 /* NS_IN6ADDRSZ*/);
+  memset ((tp = tmp), '\0', 16 /* NS_IN6ADDRSZ*/);
   endp = tp + 16 /*NS_IN6ADDRSZ*/;
   colonp = NULL;
   /* Leading :: requires some special handling. */
@@ -133,8 +133,8 @@
   {
     const char *pch;
 
-    if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
-      pch = strchr((xdigits = xdigits_u), ch);
+    if ((pch = strchr ((xdigits = xdigits_l), ch)) == NULL)
+      pch = strchr ((xdigits = xdigits_u), ch);
     if (pch != NULL)
     {
       val <<= 4;
@@ -184,7 +184,7 @@
   if (colonp != NULL)
   {
     /*
-     * Since some memmove()'s erroneously fail to handle
+     * Since some memmove ()'s erroneously fail to handle
      * overlapping regions, we'll do the shift by hand.
      */
     const int n = tp - colonp;
@@ -202,24 +202,24 @@
   if (tp != endp)
     return (0);
 
-  /* memcpy(dst, tmp, NS_IN6ADDRSZ);  */
-  memcpy(addr, tmp, 16);
+  /* memcpy (dst, tmp, NS_IN6ADDRSZ);  */
+  memcpy (addr, tmp, 16);
   return (1);
 }
 
 Ipv6Address::Ipv6Address ()
 {
-  memset(m_address, 0x00, 16);
+  memset (m_address, 0x00, 16);
 }
 
 Ipv6Address::Ipv6Address (Ipv6Address const& addr)
 {
-  memcpy(m_address, addr.m_address, 16);
+  memcpy (m_address, addr.m_address, 16);
 }
 
 Ipv6Address::Ipv6Address (Ipv6Address const* addr)
 {
-  memcpy(m_address, addr->m_address, 16);
+  memcpy (m_address, addr->m_address, 16);
 }
 
 Ipv6Address::Ipv6Address (char const* address)
@@ -230,7 +230,7 @@
 Ipv6Address::Ipv6Address (uint8_t address[16])
 {
   /* 128 bit => 16 bytes */
-  memcpy(m_address, address, 16);
+  memcpy (m_address, address, 16);
 }
 
 Ipv6Address::~Ipv6Address ()
@@ -246,12 +246,12 @@
 void Ipv6Address::Set (uint8_t address[16])
 {
   /* 128 bit => 16 bytes */
-  memcpy(m_address, address, 16);
+  memcpy (m_address, address, 16);
 }
 
 void Ipv6Address::Serialize (uint8_t buf[16]) const
 {
-  memcpy(buf, m_address, 16);
+  memcpy (buf, m_address, 16);
 }
 
 Ipv6Address Ipv6Address::Deserialize (const uint8_t buf[16])
@@ -266,16 +266,16 @@
   uint8_t buf[16];
   uint8_t buf2[16];
 
-  addr.CopyTo(buf);
-  prefix.GetBytes(buf2);
+  addr.CopyTo (buf);
+  prefix.GetBytes (buf2);
 
-  memcpy(buf2 + 8, buf, 3);
+  memcpy (buf2 + 8, buf, 3);
   buf2[11] = 0xff;
   buf2[12] = 0xfe;
-  memcpy(buf2 + 13, buf + 3, 3);
+  memcpy (buf2 + 13, buf + 3, 3);
   buf2[8] |= 0x02;
 
-  ret.Set(buf2);
+  ret.Set (buf2);
   return ret;
 }
 
@@ -285,18 +285,18 @@
   uint8_t buf[16];
   uint8_t buf2[16];
 
-  addr.CopyTo(buf);
+  addr.CopyTo (buf);
 
-  memset(buf2, 0x00, sizeof(buf2));
+  memset (buf2, 0x00, sizeof (buf2));
   buf2[0] = 0xfe;
   buf2[1] = 0x80;
-  memcpy(buf2 + 8, buf, 3);
+  memcpy (buf2 + 8, buf, 3);
   buf2[11] = 0xff;
   buf2[12] = 0xfe;
-  memcpy(buf2 + 13, buf + 3, 3);
+  memcpy (buf2 + 13, buf + 3, 3);
   buf2[8] |= 0x02;
 
-  ret.Set(buf2);
+  ret.Set (buf2);
   return ret;
 }
 
@@ -306,9 +306,9 @@
   uint8_t buf2[16];
   Ipv6Address ret;
 
-  addr.Serialize(buf2);
+  addr.Serialize (buf2);
 
-  memset(buf, 0x00, sizeof(buf));
+  memset (buf, 0x00, sizeof (buf));
   buf[0] = 0xff;
   buf[1] = 0x02;
   buf[11] = 0x01;
@@ -317,40 +317,40 @@
   buf[14] = buf2[14];
   buf[15] = buf2[15];
 
-  ret.Set(buf);
+  ret.Set (buf);
   return ret;
 }
 
 void Ipv6Address::Print (std::ostream& os) const
 {
-  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[0]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[1] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[2] 
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[3] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[4]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[5] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[6]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[7] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[8]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[9] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[10]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[11] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[12]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[13] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[14]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_address[15] 
-    << std::dec << std::setfill(' ');
+  os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[0]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[1] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[2] 
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[3] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[4]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[5] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[6]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[7] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[8]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[9] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[10]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[11] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[12]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[13] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[14]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_address[15] 
+    << std::dec << std::setfill (' ');
 }
 
 bool Ipv6Address::IsLocalhost () const
 {
-  static Ipv6Address localhost("::1");
+  static Ipv6Address localhost ("::1");
   return (*this == localhost);
 }
 
 bool Ipv6Address::IsMulticast () const
 {
-  if(m_address[0] == 0xff)
+  if (m_address[0] == 0xff)
   {
     return true;
   }
@@ -364,15 +364,15 @@
   uint8_t pref[16];
   unsigned int i = 0;
 
-  memcpy(addr, m_address, 16);
-  ((Ipv6Prefix)prefix).GetBytes(pref);
+  memcpy (addr, m_address, 16);
+  ((Ipv6Prefix)prefix).GetBytes (pref);
 
   /* a little bit ugly... */
-  for(i = 0 ; i < 16 ; i++)
+  for (i = 0 ; i < 16 ; i++)
   {
     addr[i] = addr[i] & pref[i];
   }
-  ipv6.Set(addr);
+  ipv6.Set (addr);
   return ipv6;
 }
 
@@ -380,9 +380,9 @@
 {
   uint8_t buf[16];
 
-  Serialize(buf);
+  Serialize (buf);
 
-  if(buf[0] == 0xff && 
+  if (buf[0] == 0xff && 
       buf[1] == 0x02 &&
       buf[11] == 0x01 &&
       buf[12] == 0xff)
@@ -394,31 +394,31 @@
 
 bool Ipv6Address::IsAllNodesMulticast () const
 {
-  static Ipv6Address allnodes("ff02::1");
+  static Ipv6Address allnodes ("ff02::1");
   return (*this == allnodes);
 }
 
 bool Ipv6Address::IsAllRoutersMulticast () const
 {
-  static Ipv6Address allrouters("ff02::2");
+  static Ipv6Address allrouters ("ff02::2");
   return (*this == allrouters);
 }
 
 bool Ipv6Address::IsAllHostsMulticast () const
 {
-  static Ipv6Address allhosts("ff02::3");
+  static Ipv6Address allhosts ("ff02::3");
   return (*this == allhosts);
 }
 
 bool Ipv6Address::IsAny () const
 {
-  static Ipv6Address any("::");
+  static Ipv6Address any ("::");
   return (*this == any);
 }
 
 bool Ipv6Address::IsMatchingType (const Address& address)
 {
-  return address.CheckCompatible(GetType(), 16);
+  return address.CheckCompatible (GetType (), 16);
 }
 
 Ipv6Address::operator Address () const
@@ -430,7 +430,7 @@
 {
   uint8_t buf[16];
   Serialize (buf);
-  return Address(GetType(), buf, 16);
+  return Address (GetType (), buf, 16);
 }
 
 Ipv6Address Ipv6Address::ConvertFrom (const Address &address)
@@ -443,55 +443,55 @@
 
 uint8_t Ipv6Address::GetType (void)
 {
-  static uint8_t type = Address::Register();
+  static uint8_t type = Address::Register ();
   return type;
 }
 
 Ipv6Address Ipv6Address::GetZero ()
 {
-  Ipv6Address zero("::");
+  Ipv6Address zero ("::");
   return zero;
 }
 
 Ipv6Address Ipv6Address::GetAny ()
 {
-  Ipv6Address any("::");
+  Ipv6Address any ("::");
   return any;
 }
 
 Ipv6Address Ipv6Address::GetAllNodesMulticast ()
 {
-  Ipv6Address nmc("ff02::1");
+  Ipv6Address nmc ("ff02::1");
   return nmc;
 }
 
 Ipv6Address Ipv6Address::GetAllRoutersMulticast ()
 {
-  Ipv6Address rmc("ff02::2");
+  Ipv6Address rmc ("ff02::2");
   return rmc;
 }
 
 Ipv6Address Ipv6Address::GetAllHostsMulticast ()
 {
-  Ipv6Address hmc("ff02::3");
+  Ipv6Address hmc ("ff02::3");
   return hmc;
 }
 
 Ipv6Address Ipv6Address::GetLoopback ()
 {
-  static Ipv6Address loopback("::1");
+  static Ipv6Address loopback ("::1");
   return loopback;
 }
 
 void Ipv6Address::GetBytes (uint8_t buf[16]) const
 {
-  memcpy(buf, m_address, 16);
+  memcpy (buf, m_address, 16);
 }
 
 bool Ipv6Address::IsLinkLocal () const
 {
-  Ipv6Address linkLocal("fe80::0");
-  if(!IsMulticast() && ((Ipv6Address*)this)->CombinePrefix(Ipv6Prefix(64))==linkLocal)
+  Ipv6Address linkLocal ("fe80::0");
+  if (!IsMulticast () && ((Ipv6Address*)this)->CombinePrefix (Ipv6Prefix (64))==linkLocal)
   {
     return true;
   }
@@ -500,7 +500,7 @@
 
 bool Ipv6Address::IsEqual (const Ipv6Address& other) const
 {
-  if(!memcmp(m_address, other.m_address, 16))
+  if (!memcmp (m_address, other.m_address, 16))
   {
     return true;
   }
@@ -509,7 +509,7 @@
 
 std::ostream& operator << (std::ostream& os, Ipv6Address const& address)
 {
-  address.Print(os);
+  address.Print (os);
   return os;
 }
 
@@ -523,17 +523,17 @@
 
 Ipv6Prefix::Ipv6Prefix ()
 {
-  memset(m_prefix, 0x00, 16);
+  memset (m_prefix, 0x00, 16);
 }
 
 Ipv6Prefix::Ipv6Prefix (char const* prefix)
 {
-  AsciiToIpv6Host(prefix, m_prefix);
+  AsciiToIpv6Host (prefix, m_prefix);
 }
 
 Ipv6Prefix::Ipv6Prefix (uint8_t prefix[16])
 {
-  memcpy(m_prefix, prefix, 16);
+  memcpy (m_prefix, prefix, 16);
 }
 
 Ipv6Prefix::Ipv6Prefix (uint8_t prefix)
@@ -542,24 +542,24 @@
   unsigned int mod=0;
   unsigned int i=0;
 
-  memset(m_prefix, 0x00, 16);
+  memset (m_prefix, 0x00, 16);
 
-  NS_ASSERT(prefix <= 128);
+  NS_ASSERT (prefix <= 128);
 
   nb = prefix / 8;
   mod = prefix % 8;
 
-  memset(m_prefix, 0xff, nb);
+  memset (m_prefix, 0xff, nb);
 
-  if(mod)
+  if (mod)
   {
     m_prefix[nb] = 0xff << (8-mod);
   }
 
-  if(nb < 16)
+  if (nb < 16)
   {
     nb++;
-    for(i = nb; i < 16 ; i++)
+    for (i = nb; i < 16 ; i++)
     {
       m_prefix[i] = 0x00;
     }
@@ -568,12 +568,12 @@
 
 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const& prefix)
 {
-  memcpy(m_prefix, prefix.m_prefix, 16);
+  memcpy (m_prefix, prefix.m_prefix, 16);
 }
 
 Ipv6Prefix::Ipv6Prefix (Ipv6Prefix const* prefix)
 {
-  memcpy(m_prefix, prefix->m_prefix, 16);
+  memcpy (m_prefix, prefix->m_prefix, 16);
 }
 
 Ipv6Prefix::~Ipv6Prefix ()
@@ -587,13 +587,13 @@
   uint8_t addrB[16];
   unsigned int i = 0;
 
-  a.GetBytes(addrA);
-  b.GetBytes(addrB);
+  a.GetBytes (addrA);
+  b.GetBytes (addrB);
 
   /* a little bit ugly... */
-  for(i = 0 ; i < 16 ; i++)
+  for (i = 0 ; i < 16 ; i++)
   {
-    if((addrA[i] & m_prefix[i]) !=	(addrB[i] & m_prefix[i]))
+    if ((addrA[i] & m_prefix[i]) != (addrB[i] & m_prefix[i]))
     {
       return false;
     }
@@ -603,44 +603,44 @@
 
 void Ipv6Prefix::Print (std::ostream &os) const
 {
-  os << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[0]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[1] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[2]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[3] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[4]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[5] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[6]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[7] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[8]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[9] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[10]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[11] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[12]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[13] << ":"
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[14]
-    << std::hex << std::setw(2) << std::setfill('0') << (unsigned int) m_prefix[15];
+  os << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[0]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[1] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[2]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[3] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[4]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[5] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[6]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[7] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[8]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[9] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[10]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[11] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[12]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[13] << ":"
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[14]
+    << std::hex << std::setw (2) << std::setfill ('0') << (unsigned int) m_prefix[15];
 }
 
 Ipv6Prefix Ipv6Prefix::GetLoopback ()
 {
-  Ipv6Prefix prefix((uint8_t)128);
+  Ipv6Prefix prefix ((uint8_t)128);
   return prefix;
 }
 
 Ipv6Prefix Ipv6Prefix::GetZero ()
 {
-  Ipv6Prefix prefix((uint8_t)0);
+  Ipv6Prefix prefix ((uint8_t)0);
   return prefix;
 }
 
 void Ipv6Prefix::GetBytes (uint8_t buf[16]) const
 {
-  memcpy(buf, m_prefix, 16);
+  memcpy (buf, m_prefix, 16);
 }
 
 bool Ipv6Prefix::IsEqual (const Ipv6Prefix& other) const
 {
-  if(!memcmp(m_prefix, other.m_prefix, 16))
+  if (!memcmp (m_prefix, other.m_prefix, 16))
   {
     return true;
   }
@@ -671,13 +671,13 @@
   return !a.IsEqual (b);
 }
 
-size_t Ipv6AddressHash::operator() (Ipv6Address const &x) const
+size_t Ipv6AddressHash::operator () (Ipv6Address const &x) const
 {
   uint8_t buf[16];
 
-  x.GetBytes(buf);
+  x.GetBytes (buf);
 
-  return lookuphash(buf, sizeof(buf), 0);
+  return lookuphash (buf, sizeof (buf), 0);
 }
 
 ATTRIBUTE_HELPER_CPP (Ipv6Address);
--- a/src/node/ipv6-address.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv6-address.h	Wed Aug 26 15:29:03 2009 +0400
@@ -415,7 +415,7 @@
 class Ipv6AddressHash : public std::unary_function<Ipv6Address, size_t>
 {
   public:
-    size_t operator() (Ipv6Address const &x) const;
+    size_t operator () (Ipv6Address const &x) const;
 };
 
 bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b);
--- a/src/node/ipv6-header.cc	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv6-header.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -31,16 +31,15 @@
 NS_OBJECT_ENSURE_REGISTERED (Ipv6Header);
 
 Ipv6Header::Ipv6Header ()
-: m_version (6),
+  : m_version (6),
   m_trafficClass (0),
   m_flowLabel (1),
   m_payloadLength (0),
   m_nextHeader (0),
   m_hopLimit (0)
 {
-
-  SetSourceAddress (Ipv6Address("::"));
-  SetDestinationAddress(Ipv6Address ("::"));
+  SetSourceAddress (Ipv6Address ("::"));
+  SetDestinationAddress (Ipv6Address ("::"));
 }
 
 void Ipv6Header::SetTrafficClass (uint8_t traffic)
@@ -157,8 +156,8 @@
   i.WriteU8(m_nextHeader);
   i.WriteU8(m_hopLimit);
 
-  WriteTo(i, m_sourceAddress);
-  WriteTo(i, m_destinationAddress);
+  WriteTo (i, m_sourceAddress);
+  WriteTo (i, m_destinationAddress);
 }
 
 uint32_t Ipv6Header::Deserialize (Buffer::Iterator start)
@@ -169,7 +168,7 @@
   vTcFl = i.ReadNtohU32();
   m_version = vTcFl >> 28;
 
-  NS_ASSERT((m_version) == 6);
+  NS_ASSERT ((m_version) == 6);
 
   m_trafficClass = (uint8_t)((vTcFl >> 20) & 0x000000ff);
   m_flowLabel = vTcFl & 0xfff00000;
@@ -177,10 +176,10 @@
   m_nextHeader = i.ReadU8();
   m_hopLimit = i.ReadU8();
 
-  ReadFrom(i, m_sourceAddress);
-  ReadFrom(i, m_destinationAddress);
+  ReadFrom (i, m_sourceAddress);
+  ReadFrom (i, m_destinationAddress);
 
-  return GetSerializedSize();
+  return GetSerializedSize ();
 }
 
 } /* namespace ns3 */
--- a/src/node/ipv6-header.h	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/ipv6-header.h	Wed Aug 26 15:29:03 2009 +0400
@@ -39,21 +39,21 @@
      */
     enum NextHeader_e
     {
-      IPV6_EXT_HOP_BY_HOP=0,
-      IPV6_IPV4=4,
-      IPV6_TCP=6,
-      IPV6_UDP=17,
-      IPV6_IPV6=41,
-      IPV6_EXT_ROUTING=43,
-      IPV6_EXT_FRAGMENTATION=44,
-      IPV6_EXT_CONFIDENTIALITY=50,
-      IPV6_EXT_AUTHENTIFICATION,
-      IPV6_ICMPV6=58,
-      IPV6_EXT_END,
-      IPV6_EXT_DESTINATION,
-      IPV6_SCTP=135,
-      IPV6_EXT_MOBILITY=135,
-      IPV6_UDP_LITE,
+      IPV6_EXT_HOP_BY_HOP = 0,
+      IPV6_IPV4 = 4,
+      IPV6_TCP = 6,
+      IPV6_UDP = 17,
+      IPV6_IPV6 = 41,
+      IPV6_EXT_ROUTING = 43,
+      IPV6_EXT_FRAGMENTATION = 44,
+      IPV6_EXT_CONFIDENTIALITY = 50,
+      IPV6_EXT_AUTHENTIFICATION = 51,
+      IPV6_ICMPV6 = 58,
+      IPV6_EXT_END = 59,
+      IPV6_EXT_DESTINATION = 60,
+      IPV6_SCTP = 135,
+      IPV6_EXT_MOBILITY = 135,
+      IPV6_UDP_LITE = 136,
     };
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-interface-address.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,170 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include <iostream>
+
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ipv6-interface-address.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6InterfaceAddress");
+
+Ipv6InterfaceAddress::Ipv6InterfaceAddress () 
+  : m_address (Ipv6Address ()),
+  m_prefix (Ipv6Prefix ()),
+  m_state (TENTATIVE_OPTIMISTIC),
+  m_scope (HOST),
+  m_nsDadUid (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+Ipv6InterfaceAddress::Ipv6InterfaceAddress (Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  m_prefix = Ipv6Prefix (64);
+  SetAddress (address);
+  SetState (TENTATIVE_OPTIMISTIC);
+  m_nsDadUid = 0;
+}
+
+Ipv6InterfaceAddress::Ipv6InterfaceAddress (Ipv6Address address, Ipv6Prefix prefix)
+{
+  NS_LOG_FUNCTION (this << address << prefix);
+  m_prefix = prefix;
+  SetAddress (address);
+  SetState (TENTATIVE_OPTIMISTIC);
+  m_nsDadUid = 0;
+}
+
+Ipv6InterfaceAddress::Ipv6InterfaceAddress (const Ipv6InterfaceAddress& o) 
+  : m_address (o.m_address),
+  m_prefix (o.m_prefix),
+  m_state (o.m_state),
+  m_scope (o.m_scope),
+  m_nsDadUid (o.m_nsDadUid)
+{}
+
+Ipv6InterfaceAddress::~Ipv6InterfaceAddress ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv6Address Ipv6InterfaceAddress::GetAddress () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_address;
+}
+
+void Ipv6InterfaceAddress::SetAddress (Ipv6Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  m_address = address;
+
+  if (address.IsLocalhost ())
+  {
+    m_scope = HOST;
+    /* localhost address is always /128 prefix */
+    m_prefix = Ipv6Prefix (128);
+  }
+  if (address.IsLinkLocal ())
+  {
+    m_scope = LINKLOCAL;
+    /* link-local address is always /64 prefix */
+    m_prefix = Ipv6Prefix (64);
+  }
+  else
+  {
+    m_scope = GLOBAL;
+  }
+}
+
+Ipv6Prefix Ipv6InterfaceAddress::GetPrefix () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_prefix;
+}
+
+void Ipv6InterfaceAddress::SetState (Ipv6InterfaceAddress::State_e state)
+{
+  NS_LOG_FUNCTION (this << state);
+  m_state = state;
+}
+
+Ipv6InterfaceAddress::State_e Ipv6InterfaceAddress::GetState () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_state;
+}
+
+void Ipv6InterfaceAddress::SetScope (Ipv6InterfaceAddress::Scope_e scope)
+{
+  NS_LOG_FUNCTION (this << scope);
+  m_scope = scope;
+}
+
+Ipv6InterfaceAddress::Scope_e Ipv6InterfaceAddress::GetScope () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_scope;
+}
+
+std::ostream& operator<< (std::ostream& os, const Ipv6InterfaceAddress &addr)
+{
+  os << "address=" << addr.GetAddress () << "; prefix=" <<
+    addr.GetPrefix () << "; scope=" << addr.GetScope ();
+  return os;
+}
+
+uint32_t Ipv6InterfaceAddress::GetNsDadUid () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_nsDadUid;
+}
+
+void Ipv6InterfaceAddress::SetNsDadUid (uint32_t nsDadUid)
+{
+  NS_LOG_FUNCTION (this << nsDadUid);
+  m_nsDadUid = nsDadUid;
+}
+
+#if 0
+void Ipv6InterfaceAddress::StartDadTimer (Ptr<Ipv6Interface> interface)
+{
+  NS_LOG_FUNCTION (this << interface);
+  m_dadTimer.SetFunction (&Icmpv6L4Protocol::FunctionDadTimeout);
+  m_dadTimer.SetArguments (interface, m_address);
+  m_dadTimer.Schedule (Seconds (1));
+  m_dadId = Simulator::Schedule (Seconds (1.), &Icmpv6L4Protocol::FunctionDadTimeout, interface, m_address);
+}
+
+void Ipv6InterfaceAddress::StopDadTimer ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_dadTimer.Cancel ();
+  Simulator::Cancel (m_dadId);
+}
+#endif
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-interface-address.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,209 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_INTERFACE_ADDRESS_H
+#define IPV6_INTERFACE_ADDRESS_H 
+
+#include <stdint.h>
+
+#include "ipv6-address.h"
+
+namespace ns3
+{
+
+/**
+ * \ingroup address
+ * \class Ipv6InterfaceAddress
+ * \brief IPv6 address associated with an interface.
+ */
+class Ipv6InterfaceAddress
+{
+  public:
+    /**
+     * \enum State_e
+     * \brief State of an address associated with an interface.
+     */
+    enum State_e
+    {
+      TENTATIVE, /**< Address is tentative, no packet can be sent unless DAD finished */
+      DEPRECATED, /**< Address is deprecated and should not be used */
+      PREFERRED, /**< Preferred address */
+      PERMANENT, /**< Permanent address */
+      HOMEADDRESS, /**< Address is a HomeAddress */
+      TENTATIVE_OPTIMISTIC, /**< Address is tentative but we are optimistic so we can send packet even if DAD is not yet finished */
+      INVALID, /**< Invalid state (after a DAD failed) */
+    };
+
+    /**
+     * \enum Scope_e
+     * \brief Scope of address.
+     */
+    enum Scope_e
+    {
+      HOST, /**< Localhost (::1/128) */
+      LINKLOCAL, /**< Link-local address (fe80::/64) */
+      GLOBAL, /**< Global address (2000::/3) */
+    };
+
+    /**
+     * \brief Default constructor.
+     */
+    Ipv6InterfaceAddress ();
+
+    /**
+     * \brief Constructor. Prefix is 64 by default.
+     * \param address the IPv6 address to set
+     */
+    Ipv6InterfaceAddress (Ipv6Address address);
+
+    /**
+     * \brief Constructor.
+     * \param address IPv6 address to set
+     * \param prefix IPv6 prefix
+     */
+    Ipv6InterfaceAddress (Ipv6Address address, Ipv6Prefix prefix);
+
+    /**
+     * \brief Copy constructor.
+     * \param o object to copy
+     */
+    Ipv6InterfaceAddress (const Ipv6InterfaceAddress& o);
+    
+    /**
+     * \brief Destructor.
+     */
+    ~Ipv6InterfaceAddress ();
+
+    /**
+     * \brief Set IPv6 address (and scope).
+     * \param address IPv6 address to set
+     */
+    void SetAddress (Ipv6Address address);
+
+    /**
+     * \brief Get the IPv6 address.
+     * \return IPv6 address
+     */
+    Ipv6Address GetAddress () const;
+
+    /**
+     * \brief Get the IPv6 prefix.
+     * \return IPv6 prefix
+     */
+    Ipv6Prefix GetPrefix () const;
+
+    /**
+     * \brief Set the state.
+     * \param state the state
+     */
+    void SetState (Ipv6InterfaceAddress::State_e state);
+
+    /**
+     * \brief Get the address state.
+     * \return address state
+     */
+    Ipv6InterfaceAddress::State_e GetState () const;
+
+    /**
+     * \brief Set the scope.
+     * \param scope the scope of address
+     */
+    void SetScope (Ipv6InterfaceAddress::Scope_e scope);
+    
+    /**
+     * \brief Get address scope.
+     * \return scope
+     */
+    Ipv6InterfaceAddress::Scope_e GetScope () const;
+
+    /**
+     * \brief Set the latest DAD probe packet UID.
+     * \param uid packet uid
+     */
+    void SetNsDadUid (uint32_t uid);
+
+    /**
+     * \brief Get the latest DAD probe packet UID.
+     * \return uid
+     */
+    uint32_t GetNsDadUid () const;
+
+#if 0
+    /**
+     * \brief Start the DAD timer.
+     * \param interface interface
+     */
+    void StartDadTimer (Ptr<Ipv6Interface> interface);
+
+    /**
+     * \brief Stop the DAD timer.
+     */
+    void StopDadTimer ();
+#endif
+
+  private:
+    /**
+     * \brief The IPv6 address.
+     */
+    Ipv6Address m_address;
+
+    /**
+     * \brief The IPv6 prefix.
+     */
+    Ipv6Prefix m_prefix;
+
+    /**
+     * \brief State of the address.
+     */
+    State_e m_state;
+
+    /**
+     * \brief Scope of the address.
+     */
+    Scope_e m_scope;
+
+    friend bool operator == (Ipv6InterfaceAddress const& a, Ipv6InterfaceAddress const& b);
+    friend bool operator != (Ipv6InterfaceAddress const& a, Ipv6InterfaceAddress const& b);
+
+    /**
+     * \brief Last DAD probe packet UID.
+     */
+    uint32_t m_nsDadUid;
+};
+
+std::ostream& operator<< (std::ostream& os, const Ipv6InterfaceAddress &addr);
+
+/* follow Ipv6InterfaceAddress way, maybe not inline them */
+inline bool operator == (const Ipv6InterfaceAddress& a, const Ipv6InterfaceAddress& b)
+{
+  return (a.m_address == b.m_address && a.m_prefix == b.m_prefix &&
+    a.m_state == b.m_state && a.m_scope == b.m_scope);
+}
+
+inline bool operator != (const Ipv6InterfaceAddress& a, const Ipv6InterfaceAddress& b)
+{
+  return (a.m_address != b.m_address || a.m_prefix != b.m_prefix ||
+    a.m_state != b.m_state || a.m_scope != b.m_scope);
+}
+
+} /* namespace ns3 */
+
+#endif /* IPV6_INTERFACE_ADDRESS_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-raw-socket-factory.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,37 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ipv6-raw-socket-factory.h"
+#include "ns3/uinteger.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6RawSocketFactory);
+
+TypeId Ipv6RawSocketFactory::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6RawSocketFactory")
+    .SetParent<SocketFactory> ()
+    ;
+  return tid;
+}
+
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-raw-socket-factory.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,52 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef IPV6_RAW_SOCKET_FACTORY_H
+#define IPV6_RAW_SOCKET_FACTORY_H
+
+#include "socket-factory.h"
+
+namespace ns3 
+{
+
+class Socket;
+
+/**
+ * \ingroup socket
+ *
+ * \brief API to create IPv6 RAW socket instances 
+ *
+ * This abstract class defines the API for IPv6 RAW socket factory.
+ * 
+ */
+class Ipv6RawSocketFactory : public SocketFactory
+{
+  public:
+    /** 
+     * \brief Get the type ID of this class.
+     * \return type ID
+     */
+    static TypeId GetTypeId (void);
+};
+
+} // namespace ns3
+
+#endif /* IPV6_RAW_SOCKET_FACTORY_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-route.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,147 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include <iostream>
+
+#include "net-device.h"
+
+#include "ipv6-route.h"
+
+namespace ns3
+{
+
+Ipv6Route::Ipv6Route ()
+{
+}
+
+Ipv6Route::~Ipv6Route ()
+{
+}
+
+void Ipv6Route::SetDestination (Ipv6Address dest)
+{
+  m_dest = dest;
+}
+
+Ipv6Address
+Ipv6Route::GetDestination () const
+{
+  return m_dest;
+}
+
+void Ipv6Route::SetSource (Ipv6Address src)
+{
+  m_source = src;
+}
+
+Ipv6Address Ipv6Route::GetSource () const
+{
+  return m_source;
+}
+
+void Ipv6Route::SetGateway (Ipv6Address gw)
+{
+  m_gateway = gw;
+}
+
+Ipv6Address Ipv6Route::GetGateway () const
+{
+  return m_gateway;
+}
+
+void Ipv6Route::SetOutputDevice (Ptr<NetDevice> outputDevice)
+{
+  m_outputDevice = outputDevice;
+}
+
+Ptr<NetDevice> Ipv6Route::GetOutputDevice () const
+{
+  return m_outputDevice;
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv6Route const& route)
+{
+   os << "source=" << route.GetSource () << " dest="<< route.GetDestination () <<" gw=" << route.GetGateway ();
+   return os;
+}
+
+Ipv6MulticastRoute::Ipv6MulticastRoute ()
+{
+  uint32_t initial_ttl = MAX_TTL;
+
+  /* Initialize array to MAX_TTL, which means that all interfaces are "off" */
+  for (uint32_t i = 0; i < MAX_INTERFACES; i++)
+  {
+    m_ttls.push_back (initial_ttl);
+  }
+}
+
+Ipv6MulticastRoute::~Ipv6MulticastRoute ()
+{
+}
+
+void Ipv6MulticastRoute::SetGroup (const Ipv6Address group)
+{
+  m_group = group;
+}
+
+Ipv6Address Ipv6MulticastRoute::GetGroup () const
+{
+  return m_group;
+}
+
+void Ipv6MulticastRoute::SetOrigin (const Ipv6Address origin)
+{
+  m_origin = origin;
+}
+
+Ipv6Address Ipv6MulticastRoute::GetOrigin () const
+{
+  return m_origin;
+}
+
+void Ipv6MulticastRoute::SetParent (uint32_t parent)
+{
+  m_parent = parent;
+}
+
+uint32_t Ipv6MulticastRoute::GetParent () const
+{
+  return m_parent;
+}
+
+void Ipv6MulticastRoute::SetOutputTtl (uint32_t oif, uint32_t ttl)
+{
+  m_ttls[oif] = ttl;
+}
+
+uint32_t Ipv6MulticastRoute::GetOutputTtl (uint32_t oif) const
+{
+  return m_ttls[oif];
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoute const& route)
+{
+   os << "origin=" << route.GetOrigin () << " group="<< route.GetGroup () <<" parent=" << route.GetParent ();
+   return os;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-route.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,227 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_ROUTE_H
+#define IPV6_ROUTE_H
+
+#include <list>
+#include <vector>
+#include <ostream>
+
+#include "ns3/ref-count-base.h"
+#include "ipv6-address.h"
+
+namespace ns3
+{
+
+class NetDevice;
+
+/**
+ * \ingroup ipv6Routing
+ * \class Ipv6Route
+ * \brief IPv6 route cache entry.
+ */
+class Ipv6Route : public RefCountBase
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6Route ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6Route ();
+
+    /**
+     * \brief Set destination address.
+     * \param dest IPv6 destination address
+     */
+    void SetDestination (Ipv6Address dest);
+
+    /**
+     * \brief Get destination address.
+     * \return destination address
+     */
+    Ipv6Address GetDestination () const;
+
+    /**
+     * \brief Set source address.
+     * \param src IPv6 source address
+     */
+    void SetSource (Ipv6Address src);
+
+    /**
+     * \brief Get source address.
+     * \return source address
+     */
+    Ipv6Address GetSource () const;
+
+    /**
+     * \brief Set gateway address.
+     * \param gw IPv6 gateway address
+     */
+    void SetGateway (Ipv6Address gw);
+
+    /**
+     * \brief Get gateway address.
+     * \return gateway address
+     */
+    Ipv6Address GetGateway () const;
+
+    /**
+     * \brief Set output device for outgoing packets.
+     * \param outputDevice output device
+     */
+    void SetOutputDevice (Ptr<NetDevice> outputDevice);
+
+    /**
+     * \brief Get output device.
+     * \return output device
+     */
+    Ptr<NetDevice> GetOutputDevice () const;
+
+  private:
+    /**
+     * \brief Destination address.
+     */
+    Ipv6Address m_dest;
+
+    /**
+     * \brief source address.
+     */
+    Ipv6Address m_source;
+
+    /**
+     * \brief Gateway address.
+     */
+    Ipv6Address m_gateway;
+
+    /**
+     * \brief Output device.
+     */
+    Ptr<NetDevice> m_outputDevice;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv6Route const& route);
+
+/**
+ * \ingroup ipv6Routing
+ * \class Ipv6MulticastRoute
+ * \brief IPv6 multicast route entry.
+ */
+class Ipv6MulticastRoute : public RefCountBase
+{
+  public:
+    /**
+     * \brief Maximum number of multicast interfaces on a router.
+     */
+    static const uint32_t MAX_INTERFACES = 16;
+
+    /**
+     * \brief Maximum Time-To-Live (TTL).
+     */
+    static const uint32_t MAX_TTL = 255;
+
+    /**
+     * \brief Constructor.
+     */
+    Ipv6MulticastRoute ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6MulticastRoute ();
+
+    /**
+     * \brief Set IPv6 group.
+     * \param group Ipv6Address of the multicast group
+     */
+    void SetGroup (const Ipv6Address group);
+
+    /**
+     * \brief Get IPv6 group.
+     * \return Ipv6Address of the multicast group
+     */
+    Ipv6Address GetGroup (void) const;
+
+    /**
+     * \brief Set origin address.
+     * \param origin Ipv6Address of the origin address
+     */
+    void SetOrigin (const Ipv6Address origin);
+
+    /**
+     * \brief Get source address.
+     * \return Ipv6Address of the origin address
+     */
+    Ipv6Address GetOrigin (void) const;
+
+    /**
+     * \param iif Parent (input interface) for this route
+     */
+    void SetParent (uint32_t iif);
+    /**
+     * \return Parent (input interface) for this route
+     */
+    uint32_t GetParent (void) const;
+
+    /**
+     * \param oif Outgoing interface index
+     * \param ttl time-to-live for this route
+     */
+    void SetOutputTtl (uint32_t oif, uint32_t ttl);
+
+    /**
+     * \brief Get output TTL.
+     * \param oif outgoing interface
+     * \return TTL for this route
+     */
+    uint32_t GetOutputTtl (uint32_t oif) const;
+
+  private:
+    /**
+     * \brief IPv6 group.
+     */
+    Ipv6Address m_group;
+
+    /**
+     * \brief IPv6 origin (source).
+     */
+    Ipv6Address m_origin;
+
+    /**
+     * \brief Source interface.
+     */
+    uint32_t m_parent;
+
+    /**
+     * \brief TTLs;
+     */
+    std::vector<uint32_t> m_ttls;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoute const& route);
+
+} /* namespace ns3 */
+
+#endif /* IPV6_ROUTE_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-routing-protocol.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,39 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* taken from src/node/ipv4-routing-protocol.cc and adapted to IPv6 */
+
+#include "ns3/assert.h"
+#include "ipv6-route.h"
+#include "ipv6-routing-protocol.h"
+
+namespace ns3 
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6RoutingProtocol);
+
+TypeId Ipv6RoutingProtocol::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6RoutingProtocol")
+    .SetParent<Object> ()
+    ;
+  return tid;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6-routing-protocol.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,170 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* taken from src/node/ipv4-routing-protocol.h and adapted to IPv6 */
+
+#ifndef IPV6_ROUTING_PROTOCOL_H
+#define IPV6_ROUTING_PROTOCOL_H
+
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/object.h"
+#include "ns3/socket.h"
+#include "ipv6-header.h"
+#include "ipv6-interface-address.h"
+#include "ipv6.h"
+
+namespace ns3 {
+
+class Ipv6MulticastRoute;
+class Ipv6Route;
+class NetDevice;
+
+/**
+ * \ingroup node 
+ * \defgroup ipv6Routing Ipv6 Routing
+ *
+ * Abstract base class for Ipv6 routing protocols.  Defines two
+ * virtual functions for packet routing and forwarding.  The first, 
+ * RouteOutput (), is used for locally originated packets, and the second,
+ * RouteInput (), is used for forwarding and/or delivering received packets. 
+ * Also defines the signatures of four callbacks used in RouteInput ().
+ *
+ */
+class Ipv6RoutingProtocol : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  typedef Callback<void, Ptr<Ipv6Route>, Ptr<const Packet>, const Ipv6Header &> UnicastForwardCallback;
+  typedef Callback<void, Ptr<Ipv6MulticastRoute>, Ptr<const Packet>, const Ipv6Header &> MulticastForwardCallback;
+  typedef Callback<void, Ptr<const Packet>, const Ipv6Header &, uint32_t > LocalDeliverCallback;
+  typedef Callback<void, Ptr<const Packet>, const Ipv6Header &, Socket::SocketErrno > ErrorCallback;
+  
+  /**
+   * \brief Query routing cache for an existing route, for an outbound packet
+   *
+   * This lookup is used by transport protocols.  It does not cause any
+   * packet to be forwarded, and is synchronous.  Can be used for
+   * multicast or unicast.  The Linux equivalent is ip_route_output ()
+   *
+   * \param p packet to be routed.  Note that this method may modify the packet.
+   *          Callers may also pass in a null pointer. 
+   * \param header input parameter (used to form key to search for the route)
+   * \param oif Output interface index.  May be zero, or may be bound via
+   *            socket options to a particular output interface.
+   * \param sockerr Output parameter; socket errno 
+   *
+   * \returns a code that indicates what happened in the lookup
+   */
+  virtual Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr) = 0;
+  
+  /**
+   * \brief Route an input packet (to be forwarded or locally delivered)
+   *
+   * This lookup is used in the forwarding process.  The packet is
+   * handed over to the Ipv6RoutingProtocol, and will get forwarded onward
+   * by one of the callbacks.  The Linux equivalent is ip_route_input ().
+   * There are four valid outcomes, and a matching callbacks to handle each.
+   *
+   * \param p received packet
+   * \param header input parameter used to form a search key for a route
+   * \param idev Pointer to ingress network device
+   * \param ucb Callback for the case in which the packet is to be forwarded
+   *            as unicast
+   * \param mcb Callback for the case in which the packet is to be forwarded
+   *            as multicast
+   * \param lcb Callback for the case in which the packet is to be locally
+   *            delivered
+   * \param ecb Callback to call if there is an error in forwarding
+   * \returns true if the Ipv6RoutingProtocol takes responsibility for 
+   *          forwarding or delivering the packet, false otherwise
+   */ 
+  virtual bool RouteInput  (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev, 
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+                             LocalDeliverCallback lcb, ErrorCallback ecb) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   *
+   * Protocols are expected to implement this method to be notified of the state change of
+   * an interface in a node.
+   */
+  virtual void NotifyInterfaceUp (uint32_t interface) = 0;
+  /**
+   * \param interface the index of the interface we are being notified about
+   *
+   * Protocols are expected to implement this method to be notified of the state change of
+   * an interface in a node.
+   */
+  virtual void NotifyInterfaceDown (uint32_t interface) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   * \param address a new address being added to an interface
+   *
+   * Protocols are expected to implement this method to be notified whenever
+   * a new address is added to an interface. Typically used to add a 'network route' on an
+   * interface. Can be invoked on an up or down interface.
+   */
+  virtual void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   * \param address a new address being added to an interface
+   *
+   * Protocols are expected to implement this method to be notified whenever
+   * a new address is removed from an interface. Typically used to remove the 'network route' of an
+   * interface. Can be invoked on an up or down interface.
+   */
+  virtual void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address) = 0;
+
+  /**
+   * \brief Notify a new route.
+   *
+   * Typically this is used to add another route from IPv6 stack (i.e. ICMPv6
+   * redirect case, ...).
+   * \param dst destination address
+   * \param mask destination mask
+   * \param nextHop nextHop for this destination
+   * \param interface output interface
+   * \param prefixToUse prefix to use as source with this route
+   */
+  virtual void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ()) = 0;
+
+  /**
+   * \brief Notify route removing.
+   * \param dst destination address
+   * \param mask destination mask
+   * \param nextHop nextHop for this destination
+   * \param interface output interface
+   */
+  virtual void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface) = 0;
+
+  /**
+   * \param ipv6 the ipv6 object this routing protocol is being associated with
+   * 
+   * Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol
+   */
+  virtual void SetIpv6 (Ptr<Ipv6> ipv6) = 0;
+};
+
+} //namespace ns3
+
+#endif /* IPV6_ROUTING_PROTOCOL_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,60 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+/* taken from src/node/ipv4.h and adapted to IPv6 */
+
+#include "ns3/assert.h" 
+#include "ns3/node.h" 
+#include "ns3/boolean.h"
+#include "ipv6.h"
+
+namespace ns3 
+{
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6);
+
+TypeId Ipv6::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv6")
+    .SetParent<Object> ()
+    .AddAttribute ("IpForward", "Globally enable or disable IP forwarding for all current and future IPv6 devices.",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&Ipv6::SetIpForward,
+                                        &Ipv6::GetIpForward),
+                   MakeBooleanChecker ())
+#if 0
+    .AddAttribute ("MtuDiscover", "If enabled, every outgoing IPv6 packet will have the DF flag set.",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&UdpSocket::SetMtuDiscover,
+                                        &UdpSocket::GetMtuDiscover),
+                   MakeBooleanChecker ())
+#endif
+    ;
+  return tid;
+}
+
+Ipv6::Ipv6 ()
+{}
+
+Ipv6::~Ipv6 ()
+{}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv6.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,289 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+/* taken from src/node/ipv4.h and adapted to IPv6 */
+
+#ifndef IPV6_H
+#define IPV6_H
+
+#include <stdint.h>
+#include "ns3/object.h"
+#include "ns3/socket.h"
+#include "ns3/callback.h"
+#include "ipv6-address.h"
+#include "ipv6-interface-address.h"
+
+namespace ns3 {
+
+class Node;
+class NetDevice;
+class Packet;
+class Ipv6RoutingProtocol;
+
+/**
+ * \ingroup node
+ * \defgroup ipv6 Ipv6
+ */
+
+/**
+ * \ingroup ipv6
+ * \brief Access to the IPv6 forwarding table, interfaces, and configuration
+ *
+ * This class defines the API to manipulate the following aspects of
+ * the IPv6 implementation:  
+ * -# set/get an Ipv6RoutingProtocol 
+ * -# register a NetDevice for use by the IPv6 layer (basically, to
+ * create IPv6-related state such as addressing and neighbor cache that 
+ * is associated with a NetDevice)
+ * -# manipulate the status of the NetDevice from the IPv6 perspective, 
+ * such as marking it as Up or Down, 
+ * -# adding, deleting, and getting addresses associated to the IPv6 
+ * interfaces.
+ * -# exporting IPv6 configuration attributes
+ * 
+ * Each NetDevice has conceptually a single IPv6 interface associated
+ * with it (the corresponding structure in the Linux IPv6 implementation
+ * is struct in_device).  Each interface may have one or more IPv6
+ * addresses associated with it.  Each IPv6 address may have different
+ * subnet mask, scope, etc., so all of this per-address information 
+ * is stored in an Ipv6InterfaceAddress class (the corresponding 
+ * structure in Linux is struct in6_ifaddr)
+ *
+ * IPv6 attributes such as whether IP forwarding is enabled and disabled
+ * are also stored in this class
+ *
+ * TO DO:  Add API to allow access to the IPv6 neighbor table
+ *
+ * \see Ipv6RoutingProtocol
+ * \see Ipv6InterfaceAddress
+ */
+class Ipv6 : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  
+  /**
+   * \brief Constructor.
+   */
+  Ipv6 ();
+
+  /**
+   * \brief Destructor.
+   */
+  virtual ~Ipv6 ();
+
+  /**
+   * \brief Register a new routing protocol to be used by this IPv6 stack
+   *   
+   * This call will replace any routing protocol that has been previously 
+   * registered.  If you want to add multiple routing protocols, you must
+   * add them to a Ipv6ListRoutingProtocol directly.
+   * 
+   * \param routingProtocol smart pointer to Ipv6RoutingProtocol object
+   */
+  virtual void SetRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol) = 0;
+
+  /**
+   * \brief Get the routing protocol to be used by this IPv6 stack
+   * 
+   * \returns smart pointer to Ipv6RoutingProtocol object, or null pointer if none
+   */
+  virtual Ptr<Ipv6RoutingProtocol> GetRoutingProtocol (void) const = 0;
+
+  /**
+   * \param device device to add to the list of IPv6 interfaces
+   *        which can be used as output interfaces during packet forwarding.
+   * \returns the index of the IPv6 interface added.
+   *
+   * Once a device has been added, it can never be removed: if you want
+   * to disable it, you can invoke Ipv6::SetDown which will
+   * make sure that it is never used during packet forwarding.
+   */
+  virtual uint32_t AddInterface (Ptr<NetDevice> device) = 0;
+
+  /**
+   * \returns the number of interfaces added by the user.
+   */
+  virtual uint32_t GetNInterfaces (void) const = 0;  
+
+  /**
+   * \brief Return the interface number of the interface that has been
+   *        assigned the specified IP address.
+   *
+   * \param address The IP address being searched for
+   * \returns The interface number of the IPv6 interface with the given 
+   *          address or -1 if not found.
+   *
+   * Each IP interface has one or more IP addresses associated with it.  
+   * This method searches the list of interfaces for one that holds a
+   * particular address.  This call takes an IP address as a parameter and
+   * returns the interface number of the first interface that has been assigned
+   * that address, or -1 if not found.  There must be an exact match.
+   */
+  virtual int32_t GetInterfaceForAddress (Ipv6Address address) const = 0;
+
+  /**
+   * \brief Return the interface number of first interface found that 
+   *  has an IPv6 address within the prefix specified by the input
+   *  address and mask parameters
+   *
+   * \param address The IP address assigned to the interface of interest.
+   * \param mask The IP prefix to use in the mask
+   * \returns The interface number of the IPv6 interface with the given 
+   *          address or -1 if not found.
+   *
+   * Each IP interface has one or more IP addresses associated with it.  
+   * This method searches the list of interfaces for the first one found
+   * that holds an address that is included within the prefix 
+   * formed by the input address and mask parameters.  The value -1 is
+   * returned if no match is found.
+   */
+  virtual int32_t GetInterfaceForPrefix (Ipv6Address address,
+    Ipv6Prefix mask) const = 0;
+
+  /**
+   * \param interface The interface number of an IPv6 interface.
+   * \returns The NetDevice associated with the IPv6 interface number.
+   */
+  virtual Ptr<NetDevice> GetNetDevice (uint32_t interface) = 0;
+
+  /**
+   * \param device The NetDevice for an Ipv6Interface
+   * \returns The interface number of an IPv6 interface or -1 if not found.
+   */
+  virtual int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const = 0;
+
+  /**
+   * \param interface Interface number of an IPv6 interface
+   * \param address Ipv6InterfaceAddress address to associate with the underlying IPv6 interface
+   * \returns true if the operation succeeded
+   */
+  virtual bool AddAddress (uint32_t interface, Ipv6InterfaceAddress address) = 0;
+
+  /**
+   * \param interface Interface number of an IPv6 interface
+   * \returns the number of Ipv6InterfaceAddress entries for the interface.
+   */
+  virtual uint32_t GetNAddresses (uint32_t interface) const = 0;
+
+  /**
+   * Because addresses can be removed, the addressIndex is not guaranteed
+   * to be static across calls to this method.
+   * 
+   * \param interface Interface number of an IPv6 interface
+   * \param addressIndex index of Ipv6InterfaceAddress 
+   * \returns the Ipv6InterfaceAddress associated to the interface and addresIndex
+   */
+  virtual Ipv6InterfaceAddress GetAddress (uint32_t interface, uint32_t addressIndex) const = 0;
+
+  /**
+   * Remove the address at addressIndex on named interface.  The addressIndex
+   * for all higher indices will decrement by one after this method is called;
+   * so, for example, to remove 5 addresses from an interface i, one could
+   * call RemoveAddress (i, 0); 5 times.  
+   * 
+   * \param interface Interface number of an IPv6 interface
+   * \param addressIndex index of Ipv6InterfaceAddress to remove 
+   * \returns true if the operation succeeded
+   */
+  virtual bool RemoveAddress (uint32_t interface, uint32_t addressIndex) = 0;
+
+  /**
+   * \param interface The interface number of an IPv6 interface
+   * \param metric routing metric (cost) associated to the underlying 
+   *          IPv6 interface
+   */
+  virtual void SetMetric (uint32_t interface, uint16_t metric) = 0;
+
+  /**
+   * \param interface The interface number of an IPv6 interface
+   * \returns routing metric (cost) associated to the underlying 
+   *          IPv6 interface
+   */
+  virtual uint16_t GetMetric (uint32_t interface) const = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   * \returns the Maximum Transmission Unit (in bytes) associated
+   *          to the underlying IPv6 interface
+   */
+  virtual uint16_t GetMtu (uint32_t interface) const = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   * \returns true if the underlying interface is in the "up" state,
+   *          false otherwise.
+   */
+  virtual bool IsUp (uint32_t interface) const = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   * 
+   * Set the interface into the "up" state. In this state, it is
+   * considered valid during IPv6 forwarding.
+   */
+  virtual void SetUp (uint32_t interface) = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   *
+   * Set the interface into the "down" state. In this state, it is
+   * ignored during IPv6 forwarding.
+   */
+  virtual void SetDown (uint32_t interface) = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   * \returns true if IPv6 forwarding enabled for input datagrams on this device
+   */
+  virtual bool IsForwarding (uint32_t interface) const = 0;
+
+  /**
+   * \param interface Interface number of IPv6 interface
+   * \param val Value to set the forwarding flag
+   * 
+   * If set to true, IPv6 forwarding is enabled for input datagrams on this device
+   */
+  virtual void SetForwarding (uint32_t interface, bool val) = 0;
+
+  /**
+   * \brief Any interface magic number.
+   */
+  static const uint32_t IF_ANY = 0xffffffff;
+
+private:
+  // Indirect the IPv6 attributes through private pure virtual methods
+  /**
+   * \brief Set IPv6 forwarding state.
+   * \param forward IPv6 forwarding enabled or not
+   */
+  virtual void SetIpForward (bool forward) = 0;
+
+  /**
+   * \brief Get IPv6 forwarding state.
+   * \return forwarding state (enabled or not)
+   */
+  virtual bool GetIpForward (void) const = 0;
+};
+
+} // namespace ns3 
+
+#endif /* IPV6_H */
+
--- a/src/node/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/node/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -33,13 +33,18 @@
         'tcp-socket.cc',
         'tcp-socket-factory.cc',
         'ipv4.cc',
+        'ipv4-raw-socket-factory.cc',
         'application.cc',
         'simple-channel.cc',
         'simple-net-device.cc',
         'inet6-socket-address.cc',
         'ipv6-address.cc',
         'ipv6-header.cc',
-        'ipv4-raw-socket-factory.cc',
+        'ipv6-interface-address.cc',
+        'ipv6-route.cc',
+        'ipv6.cc',
+        'ipv6-raw-socket-factory.cc',
+        'ipv6-routing-protocol.cc',
         ]
 
     headers = bld.new_task_gen('ns3header')
@@ -56,7 +61,7 @@
         'ipv4-address-generator.h',
         'ipv4-header.h',
         'net-device.h',
-	'address-utils.h',
+      	'address-utils.h',
         'ipv4-route.h',
         'ipv4-routing-protocol.h',
         'queue.h',
@@ -74,11 +79,16 @@
         'tcp-socket.h',
         'tcp-socket-factory.h',
         'ipv4.h',
+        'ipv4-raw-socket-factory.h',
         'application.h',
         'simple-channel.h',
         'simple-net-device.h',
         'inet6-socket-address.h',
         'ipv6-address.h',
         'ipv6-header.h',
-        'ipv4-raw-socket-factory.h',
+        'ipv6-interface-address.h',
+        'ipv6-route.h',
+        'ipv6.h',
+        'ipv6-raw-socket-factory.h',
+        'ipv6-routing-protocol.h',
         ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/list-routing/ipv6-list-routing.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,423 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include "ns3/log.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-route.h"
+#include "ns3/node.h"
+#include "ns3/ipv6-static-routing.h"
+#include "ipv6-list-routing.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6ListRouting");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv6ListRouting);
+
+TypeId
+Ipv6ListRouting::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv6ListRouting")
+    .SetParent<Ipv6RoutingProtocol> ()
+    .AddConstructor<Ipv6ListRouting> ()
+    ;
+  return tid;
+}
+
+
+Ipv6ListRouting::Ipv6ListRouting () 
+ : m_ipv6 (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv6ListRouting::~Ipv6ListRouting () 
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+Ipv6ListRouting::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (Ipv6RoutingProtocolList::iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++)
+    {
+      // Note:  Calling dispose on these protocols causes memory leak
+      //        The routing protocols should not maintain a pointer to
+      //        this object, so Dispose () shouldn't be necessary.
+      (*rprotoIter).second = 0;
+    }
+  m_routingProtocols.clear ();
+  m_ipv6 = 0;
+}
+
+Ptr<Ipv6Route>
+Ipv6ListRouting::RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr)
+{
+  NS_LOG_FUNCTION (this << header.GetDestinationAddress () << header.GetSourceAddress () << oif);
+  Ptr<Ipv6Route> route;
+
+  for (Ipv6RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
+       i != m_routingProtocols.end (); i++)
+    {
+      NS_LOG_LOGIC ("Checking protocol " << (*i).second->GetInstanceTypeId () << " with priority " << (*i).first);
+      NS_LOG_LOGIC ("Requesting source address for destination " << header.GetDestinationAddress ());
+      route = (*i).second->RouteOutput (p, header, oif, sockerr);
+      if (route)
+        {
+          NS_LOG_LOGIC ("Found route " << route);
+          sockerr = Socket::ERROR_NOTERROR;
+          return route;
+        }
+    }
+  NS_LOG_LOGIC ("Done checking " << GetTypeId ());
+  NS_LOG_LOGIC ("");
+  sockerr = Socket::ERROR_NOROUTETOHOST;
+  return 0;
+}
+
+// Patterned after Linux ip_route_input and ip_route_input_slow
+bool 
+Ipv6ListRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev, 
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb, 
+                             LocalDeliverCallback lcb, ErrorCallback ecb)
+{
+  bool retVal = false;
+  NS_LOG_FUNCTION (p << header << idev);
+  NS_LOG_LOGIC ("RouteInput logic for node: " << m_ipv6->GetObject<Node> ()->GetId ());
+
+  NS_ASSERT (m_ipv6 != 0);
+  // Check if input device supports IP 
+  NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
+  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev); 
+  Ipv6Address dst = header.GetDestinationAddress ();
+
+  // Multicast recognition; handle local delivery here
+  //
+  if (dst.IsMulticast ())
+    {
+#ifdef NOTYET
+      if (m_ipv6->MulticastCheckGroup (iif, dst))
+#endif
+      if (true)
+        {
+          NS_LOG_LOGIC ("Multicast packet for me-- local deliver");
+          Ptr<Packet> packetCopy = p->Copy ();
+          // Here may want to disable lcb callback in recursive RouteInput
+          // call below
+          lcb (packetCopy, header, iif);
+          // Fall through-- we may also need to forward this
+          retVal = true;
+        }
+
+      /* do not forward link-local multicast address */
+      if (dst == Ipv6Address::GetAllNodesMulticast () || dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
+        {
+          return retVal;
+        }
+
+      for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin (); rprotoIter != m_routingProtocols.end ();
+           rprotoIter++)
+        {
+          NS_LOG_LOGIC ("Multicast packet for me-- trying to forward");
+          if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
+            {
+              retVal = true;
+            }
+        }
+      return retVal;
+    }
+
+ // TODO:  Configurable option to enable RFC 1222 Strong End System Model
+ // Right now, we will be permissive and allow a source to send us
+ // a packet to one of our other interface addresses; that is, the
+ // destination unicast address does not match one of the iif addresses,
+ // but we check our other interfaces.  This could be an option
+ // (to remove the outer loop immediately below and just check iif).
+  for (uint32_t j = 0; j < m_ipv6->GetNInterfaces (); j++)
+    {
+      for (uint32_t i = 0; i < m_ipv6->GetNAddresses (j); i++)
+        {
+          Ipv6InterfaceAddress iaddr = m_ipv6->GetAddress (j, i);
+          Ipv6Address addr = iaddr.GetAddress ();
+          if (addr.IsEqual (header.GetDestinationAddress ()))
+            {
+              if (j == iif)
+                {
+                  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestinationAddress ());
+                }
+              lcb (p, header, iif);
+              return true;
+            }
+          NS_LOG_LOGIC ("Address "<< addr << " not a match");
+        }
+    }
+  // Check if input device supports IP forwarding
+  if (m_ipv6->IsForwarding (iif) == false)
+    {
+      NS_LOG_LOGIC ("Forwarding disabled for this interface");
+      ecb (p, header, Socket::ERROR_NOROUTETOHOST);
+      return false;
+    }
+  // Next, try to find a route
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      if ((*rprotoIter).second->RouteInput (p, header, idev, ucb, mcb, lcb, ecb))
+        {
+          return true;
+        }
+    }
+  // No routing protocol has found a route.  
+  return retVal;
+}
+
+void 
+Ipv6ListRouting::NotifyInterfaceUp (uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << interface);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyInterfaceUp (interface);
+    }  
+}
+void 
+Ipv6ListRouting::NotifyInterfaceDown (uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << interface);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyInterfaceDown (interface);
+    }  
+}
+void 
+Ipv6ListRouting::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address)
+{
+  NS_LOG_FUNCTION (this << interface << address);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyAddAddress (interface, address);
+    }  
+}
+void 
+Ipv6ListRouting::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address)
+{
+  NS_LOG_FUNCTION (this << interface << address);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyRemoveAddress (interface, address);
+    }  
+}
+
+void Ipv6ListRouting::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyAddRoute (dst, mask, nextHop, interface, prefixToUse);
+    }
+}
+
+void Ipv6ListRouting::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->NotifyRemoveRoute (dst, mask, nextHop, interface);
+    }
+}
+
+void 
+Ipv6ListRouting::SetIpv6 (Ptr<Ipv6> ipv6)
+{
+  NS_LOG_FUNCTION (this << ipv6);
+  NS_ASSERT (m_ipv6 == 0);
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter =
+         m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end ();
+       rprotoIter++)
+    {
+      (*rprotoIter).second->SetIpv6 (ipv6);
+    }  
+  m_ipv6 = ipv6;
+}
+
+void
+Ipv6ListRouting::AddRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol, int16_t priority)
+{
+  NS_LOG_FUNCTION (this << routingProtocol->GetInstanceTypeId () << priority);
+  m_routingProtocols.push_back (std::make_pair (priority, routingProtocol));
+  m_routingProtocols.sort ( Compare );
+  if (m_ipv6 != 0)
+    {
+      routingProtocol->SetIpv6 (m_ipv6);
+    }
+}
+
+uint32_t 
+Ipv6ListRouting::GetNRoutingProtocols (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_routingProtocols.size (); 
+}
+
+Ptr<Ipv6RoutingProtocol> 
+Ipv6ListRouting::GetRoutingProtocol (uint32_t index, int16_t& priority) const
+{
+  NS_LOG_FUNCTION (index);
+  if (index > m_routingProtocols.size ())
+    {
+      NS_FATAL_ERROR ("Ipv6ListRouting::GetRoutingProtocol ():  index " << index << " out of range");
+    }
+  uint32_t i = 0;
+  for (Ipv6RoutingProtocolList::const_iterator rprotoIter = m_routingProtocols.begin ();
+       rprotoIter != m_routingProtocols.end (); rprotoIter++, i++)
+    {
+      if (i == index)
+        {
+          priority = (*rprotoIter).first;
+          return (*rprotoIter).second;
+        }
+    }
+  return 0;
+}
+
+bool 
+Ipv6ListRouting::Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b)
+{
+  return a.first > b.first;
+}
+
+
+} // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+#include "ipv6-list-routing.h"
+#include "ns3/ipv6-routing-protocol.h"
+
+namespace ns3 {
+
+class Ipv6ARouting : public Ipv6RoutingProtocol {
+public:
+  Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr)  { return 0;}
+  bool RouteInput  (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb) {return false;}
+  void NotifyInterfaceUp (uint32_t interface) {}
+  void NotifyInterfaceDown (uint32_t interface) {}
+  void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address) {}
+  void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address) {}
+  void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ()) {}
+  void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface) {}
+  void SetIpv6 (Ptr<Ipv6> ipv6) {}
+};
+
+class Ipv6BRouting : public Ipv6RoutingProtocol {
+public:
+  Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr)  { return 0;}
+  bool RouteInput  (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb) {return false;}
+  void NotifyInterfaceUp (uint32_t interface) {}
+  void NotifyInterfaceDown (uint32_t interface) {}
+  void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address) {}
+  void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address) {}
+  void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ()) {}
+  void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface) {}
+  void SetIpv6 (Ptr<Ipv6> ipv6) {}
+};
+
+class Ipv6ListRoutingTest: public Test {
+public:
+  virtual bool RunTests (void);
+  Ipv6ListRoutingTest ();
+};
+
+Ipv6ListRoutingTest::Ipv6ListRoutingTest ()
+  : Test ("Ipv6ListRouting") {}
+
+bool
+Ipv6ListRoutingTest::RunTests (void)
+{
+  bool result = true;
+  Ptr<Ipv6ListRouting> lr = CreateObject<Ipv6ListRouting> ();
+  Ptr<Ipv6RoutingProtocol> aRouting = CreateObject<Ipv6ARouting> ();
+  Ptr<Ipv6RoutingProtocol> bRouting = CreateObject<Ipv6BRouting> ();
+  // The Ipv6ARouting should be added with higher priority (larger integer 
+  // value) and will be fetched first below
+  lr->AddRoutingProtocol (aRouting, 10);
+  lr->AddRoutingProtocol (bRouting, 5);
+  int16_t first = 3;
+  int16_t second = 3;
+  uint32_t num = lr->GetNRoutingProtocols ();
+  NS_TEST_ASSERT_EQUAL (num, 2);
+  Ptr<Ipv6RoutingProtocol> firstRp = lr->GetRoutingProtocol (0, first);
+  NS_TEST_ASSERT_EQUAL (10, first);
+  NS_TEST_ASSERT_EQUAL (firstRp, aRouting);
+  Ptr<Ipv6RoutingProtocol> secondRp = lr->GetRoutingProtocol (1, second);
+  NS_TEST_ASSERT_EQUAL (5, second);
+  NS_TEST_ASSERT_EQUAL (secondRp, bRouting);
+
+  // Test negative values
+  lr = CreateObject<Ipv6ListRouting> ();
+  // The Ipv6BRouting should be added with higher priority (larger integer value)
+  lr->AddRoutingProtocol (aRouting, -10);
+  lr->AddRoutingProtocol (bRouting, -5);
+  num = lr->GetNRoutingProtocols ();
+  NS_TEST_ASSERT_EQUAL (num, 2);
+  firstRp = lr->GetRoutingProtocol (0, first);
+  NS_TEST_ASSERT_EQUAL (-5, first);
+  NS_TEST_ASSERT_EQUAL (firstRp, bRouting);
+  
+  return result;
+}
+
+static Ipv6ListRoutingTest gIpv6ListRoutingTest;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/list-routing/ipv6-list-routing.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,105 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef IPV6_LIST_ROUTING_H
+#define IPV6_LIST_ROUTING_H
+
+#include <list>
+#include "ns3/ipv6-routing-protocol.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup routing 
+ * \defgroup ipv6ListRouting Ipv6 List Routing
+ */
+/**
+ * \ingroup ipv6ListRouting
+ *
+ * This class is a specialization of Ipv6RoutingProtocol that allows 
+ * other instances of Ipv6RoutingProtocol to be inserted in a 
+ * prioritized list.  Routing protocols in the list are consulted one
+ * by one, from highest to lowest priority, until a routing protocol
+ * is found that will take the packet (this corresponds to a non-zero
+ * return value to RouteOutput, or a return value of true to RouteInput).
+ * The order by which routing protocols with the same priority value 
+ * are consulted is undefined.
+ * 
+ */
+class Ipv6ListRouting : public Ipv6RoutingProtocol
+{
+public:
+  static TypeId GetTypeId (void);
+
+  Ipv6ListRouting ();  
+  virtual ~Ipv6ListRouting ();  
+
+  /**
+   * \brief Register a new routing protocol to be used in this IPv4 stack
+   *
+   * \param routingProtocol new routing protocol implementation object
+   * \param priority priority to give to this routing protocol.
+   * Values may range between -32768 and +32767.  
+   */
+  virtual void AddRoutingProtocol (Ptr<Ipv6RoutingProtocol> routingProtocol, int16_t priority);
+  /**
+   * \return number of routing protocols in the list
+   */
+  virtual uint32_t GetNRoutingProtocols (void) const;
+  /**
+   * Return pointer to routing protocol stored at index, with the
+   * first protocol (index 0) the highest priority, the next one (index 1)
+   * the second highest priority, and so on.  The priority parameter is an
+   * output parameter and it returns the integer priority of the protocol.
+   * 
+   * \return pointer to routing protocol indexed by 
+   * \param index index of protocol to return
+   * \param priority output parameter, set to the priority of the protocol
+            being returned
+   */
+  virtual Ptr<Ipv6RoutingProtocol> GetRoutingProtocol (uint32_t index, int16_t& priority) const;
+
+  // Below are from Ipv6RoutingProtocol
+  virtual Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+
+  virtual bool RouteInput (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
+                           UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                           LocalDeliverCallback lcb, ErrorCallback ecb);
+  virtual void NotifyInterfaceUp (uint32_t interface);
+  virtual void NotifyInterfaceDown (uint32_t interface);
+  virtual void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address);
+  virtual void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address);
+  virtual void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ());
+  virtual void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface);
+  virtual void SetIpv6 (Ptr<Ipv6> ipv6);
+
+protected:
+  void DoDispose (void);
+private:
+  typedef std::pair<int16_t, Ptr<Ipv6RoutingProtocol> > Ipv6RoutingProtocolEntry;
+  typedef std::list<Ipv6RoutingProtocolEntry> Ipv6RoutingProtocolList;
+  Ipv6RoutingProtocolList m_routingProtocols;
+  static bool Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b);
+  Ptr<Ipv6> m_ipv6;
+
+};
+
+} //namespace ns3
+
+#endif /* IPV6_LIST_ROUTING_H */
+
--- a/src/routing/list-routing/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/routing/list-routing/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -4,10 +4,12 @@
     module = bld.create_ns3_module('list-routing', ['node'])
     module.source = [
         'ipv4-list-routing.cc',
+        'ipv6-list-routing.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'list-routing'
     headers.source = [
         'ipv4-list-routing.h',
+        'ipv6-list-routing.h',
         ]
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/static-routing/ipv6-routing-table-entry.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,331 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ipv6-routing-table-entry.h"
+#include "ns3/assert.h"
+
+namespace ns3
+{
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry ()
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6RoutingTableEntry const& route)
+  : m_dest (route.m_dest),
+  m_destNetworkPrefix (route.m_destNetworkPrefix),
+  m_gateway (route.m_gateway),
+  m_interface (route.m_interface),
+  m_prefixToUse (route.m_prefixToUse)
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6RoutingTableEntry const* route) 
+  : m_dest (route->m_dest),
+  m_destNetworkPrefix (route->m_destNetworkPrefix),
+  m_gateway (route->m_gateway),
+  m_interface (route->m_interface),
+  m_prefixToUse (route->m_prefixToUse)
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address dest, Ipv6Address gateway, uint32_t interface)
+  : m_dest (dest),
+  m_destNetworkPrefix (Ipv6Prefix::GetZero ()),
+  m_gateway (gateway),
+  m_interface (interface),
+  m_prefixToUse (Ipv6Address ("::"))
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address dest, uint32_t interface)
+  : m_dest (dest),
+  m_destNetworkPrefix (Ipv6Prefix (128)),
+  m_gateway (Ipv6Address::GetZero ()),
+  m_interface (interface),
+  m_prefixToUse (Ipv6Address ("::"))
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address gateway, uint32_t interface, Ipv6Address prefixToUse)
+  : m_dest (network),
+  m_destNetworkPrefix (networkPrefix),
+  m_gateway (gateway),
+  m_interface (interface),
+  m_prefixToUse (prefixToUse)
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address gateway, uint32_t interface)
+  : m_dest (network),
+  m_destNetworkPrefix (networkPrefix),
+  m_gateway (gateway),
+  m_interface (interface),
+  m_prefixToUse (Ipv6Address::GetZero ())
+{
+}
+
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface, Ipv6Address prefixToUse)
+  : m_dest (network),
+  m_destNetworkPrefix (networkPrefix),
+  m_gateway (Ipv6Address::GetZero ()),
+  m_interface (interface),
+  m_prefixToUse (prefixToUse)
+{
+}
+
+Ipv6RoutingTableEntry::Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
+  : m_dest (network),
+  m_destNetworkPrefix (networkPrefix),
+  m_gateway (Ipv6Address::GetZero ()),
+  m_interface (interface),
+  m_prefixToUse (Ipv6Address ("::"))
+{
+}
+
+Ipv6RoutingTableEntry::~Ipv6RoutingTableEntry ()
+{
+}
+
+bool Ipv6RoutingTableEntry::IsHost () const
+{
+  static Ipv6Prefix prefix (128);
+  if (m_destNetworkPrefix.IsEqual (prefix))
+  {
+    return true;
+  }
+  return false;
+}
+
+Ipv6Address Ipv6RoutingTableEntry::GetDest () const
+{
+  return m_dest;
+}
+
+Ipv6Address Ipv6RoutingTableEntry::GetPrefixToUse () const
+{
+  return m_prefixToUse;
+}
+
+void Ipv6RoutingTableEntry::SetPrefixToUse (Ipv6Address prefix)
+{
+  m_prefixToUse = prefix;
+}
+
+bool Ipv6RoutingTableEntry::IsNetwork () const
+{
+  return !IsHost ();
+}
+
+bool Ipv6RoutingTableEntry::IsDefault () const
+{
+  if (m_dest.IsEqual (Ipv6Address::GetZero ()))
+  {
+    return true;
+  }
+  return false;
+}
+
+Ipv6Address Ipv6RoutingTableEntry::GetDestNetwork () const
+{
+  return m_dest;
+}
+
+Ipv6Prefix Ipv6RoutingTableEntry::GetDestNetworkPrefix () const
+{
+  return m_destNetworkPrefix;
+}
+
+bool Ipv6RoutingTableEntry::IsGateway () const
+{
+  if (m_gateway.IsEqual (Ipv6Address::GetZero ()))
+  {
+    return false;
+  }
+  return true;
+}
+
+Ipv6Address Ipv6RoutingTableEntry::GetGateway () const
+{
+  return m_gateway;
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateHostRouteTo (Ipv6Address dest, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  return Ipv6RoutingTableEntry (dest, Ipv6Prefix (128), nextHop, interface, prefixToUse);
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateHostRouteTo (Ipv6Address dest, uint32_t interface)
+{
+  return Ipv6RoutingTableEntry (dest, interface);
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface)
+{
+  return Ipv6RoutingTableEntry (network, networkPrefix, nextHop, interface);
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  return Ipv6RoutingTableEntry (network, networkPrefix, nextHop, interface, prefixToUse);
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
+{
+  return Ipv6RoutingTableEntry (network, networkPrefix, interface, network);
+}
+
+Ipv6RoutingTableEntry Ipv6RoutingTableEntry::CreateDefaultRoute (Ipv6Address nextHop, uint32_t interface)
+{
+  return Ipv6RoutingTableEntry (Ipv6Address::GetZero (), nextHop, interface);
+}
+
+uint32_t Ipv6RoutingTableEntry::GetInterface () const
+{
+  return m_interface;
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv6RoutingTableEntry const& route)
+{
+  if (route.IsDefault ())
+  {
+    NS_ASSERT (route.IsGateway ());
+    os << "default out =" << route.GetInterface () << ", next hop =" << route.GetGateway ();
+  }
+  else if (route.IsHost ())
+  {
+    if (route.IsGateway ())
+    {
+      os << "host ="<< route.GetDest () <<
+        ", out =" << route.GetInterface () <<
+        ", next hop =" << route.GetGateway ();
+    }
+    else
+    {
+      os << "host =" << route.GetDest () <<
+        ", out =" << route.GetInterface ();
+    }
+  }
+  else if (route.IsNetwork ())
+  {
+    if (route.IsGateway ())
+    {
+      os << "network =" << route.GetDestNetwork () <<
+        ", mask =" << route.GetDestNetworkPrefix () <<
+        ",out =" << route.GetInterface () <<
+        ", next hop =" << route.GetGateway ();
+    }
+    else
+    {
+      os << "network =" << route.GetDestNetwork () <<
+        ", mask =" << route.GetDestNetworkPrefix () <<
+        ",out =" << route.GetInterface ();
+    }
+  }
+  else
+  {
+    NS_ASSERT (false);
+  }
+  return os;
+}
+
+Ipv6MulticastRoutingTableEntry::Ipv6MulticastRoutingTableEntry ()
+{
+}
+
+Ipv6MulticastRoutingTableEntry::Ipv6MulticastRoutingTableEntry (Ipv6MulticastRoutingTableEntry const & route) 
+  : m_origin (route.m_origin),
+  m_group (route.m_group),
+  m_inputInterface (route.m_inputInterface),
+  m_outputInterfaces (route.m_outputInterfaces)
+{
+}
+
+Ipv6MulticastRoutingTableEntry::Ipv6MulticastRoutingTableEntry (Ipv6MulticastRoutingTableEntry const* route)
+  : m_origin (route->m_origin),
+  m_group (route->m_group),
+  m_inputInterface (route->m_inputInterface),
+  m_outputInterfaces (route->m_outputInterfaces)
+{
+}
+
+Ipv6MulticastRoutingTableEntry::Ipv6MulticastRoutingTableEntry (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces)
+  : m_origin (origin),
+  m_group (group),
+  m_inputInterface (inputInterface),
+  m_outputInterfaces (outputInterfaces)
+{
+}
+
+Ipv6Address Ipv6MulticastRoutingTableEntry::GetOrigin () const
+{
+  return m_origin;
+}
+
+Ipv6Address Ipv6MulticastRoutingTableEntry::GetGroup () const
+{
+  return m_group;
+}
+
+uint32_t Ipv6MulticastRoutingTableEntry::GetInputInterface () const
+{
+  return m_inputInterface;
+}
+
+uint32_t Ipv6MulticastRoutingTableEntry::GetNOutputInterfaces () const
+{
+  return m_outputInterfaces.size ();
+}
+
+uint32_t Ipv6MulticastRoutingTableEntry::GetOutputInterface (uint32_t n) const
+{
+  NS_ASSERT_MSG (n < m_outputInterfaces.size (), "Ipv6MulticastRoutingTableEntry::GetOutputInterface () : index out of bounds");
+
+  return m_outputInterfaces[n];
+}
+
+std::vector <uint32_t> Ipv6MulticastRoutingTableEntry::GetOutputInterfaces () const
+{
+  return m_outputInterfaces;
+}
+
+Ipv6MulticastRoutingTableEntry Ipv6MulticastRoutingTableEntry::CreateMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces)
+{
+  return Ipv6MulticastRoutingTableEntry (origin, group, inputInterface, outputInterfaces);
+}
+
+std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoutingTableEntry const& route)
+{
+  os << "origin =" << route.GetOrigin () <<
+    ", group =" << route.GetGroup () <<
+    ", input interface =" << route.GetInputInterface () <<
+    ", output interfaces =";
+
+  for (uint32_t i = 0; i < route.GetNOutputInterfaces (); ++i)
+  {
+    os << route.GetOutputInterface (i) << " ";
+  }
+
+  return os;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/static-routing/ipv6-routing-table-entry.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,372 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_ROUTING_TABLE_ENTRY_H
+#define IPV6_ROUTING_TABLE_ENTRY_H
+
+#include <list>
+#include <vector>
+#include <ostream>
+
+#include "ns3/ipv6-address.h"
+
+namespace ns3
+{
+
+/**
+ * \class Ipv6RoutingTableEntry
+ * \brief A record of an IPv6 route.
+ */
+class Ipv6RoutingTableEntry 
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6RoutingTableEntry ();
+
+    /**
+     * \brief Copy constructor.
+     * \param route the route to copy
+     */
+    Ipv6RoutingTableEntry (Ipv6RoutingTableEntry const & route);
+
+    /**
+     * \brief Copy constructor.
+     * \param route the route to copy
+     */
+    Ipv6RoutingTableEntry (Ipv6RoutingTableEntry const* route);
+
+    /**
+     * \brief Destructor
+     */
+    ~Ipv6RoutingTableEntry ();
+
+    /**
+     * \brief Is the route entry correspond to a host ?
+     * \return true if the route is a host, false otherwise
+     */
+    bool IsHost () const;
+
+    /**
+     * \brief Get the destination.
+     * \return the IPv6 address of the destination of this route
+     */
+    Ipv6Address GetDest () const;
+
+    /**
+     * \brief Get the prefix to use (for multihomed link).
+     * \return prefix address to use
+     */
+    Ipv6Address GetPrefixToUse () const;
+
+    /**
+     * \brief Set the prefix to use.
+     * \param prefix prefix to use
+     */
+    void SetPrefixToUse (Ipv6Address prefix);
+
+    /**
+     * \brief Is the route entry correspond to a network ? 
+     * \return true if the route is a network, false otherwise
+     */
+    bool IsNetwork () const;
+
+    /**
+     * \brief Get the destination network.
+     * \return the destination network
+     */
+    Ipv6Address GetDestNetwork () const;
+
+    /**
+     * \brief Get the destination prefix.
+     * \return the destination prefix
+     */
+    Ipv6Prefix GetDestNetworkPrefix () const;
+
+    /**
+     * \brief Is it the default route ?
+     * \return true if this route is a default route, false otherwise
+     */
+    bool IsDefault () const;
+
+    /**
+     * \brief Is it the gateway ? 
+     * \return true if this route is a gateway, false otherwise
+     */
+    bool IsGateway () const;
+
+    /**
+     * \brief Get the gateway.
+     * \return the IPv6 address of the gateway
+     */
+    Ipv6Address GetGateway () const;
+
+    /**
+     * \brief Get the interface index.
+     * \return the index of the interface
+     */
+    uint32_t GetInterface () const;
+
+    /**
+     * \brief Create a route to a host.
+     * \param dest destination address
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \param prefixToUse prefix that should be used for source address for this destination
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateHostRouteTo (Ipv6Address dest, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address ());
+
+    /**
+     * \brief Create a route to a host.
+     * \param dest destination address
+     * \param interface interface index
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateHostRouteTo (Ipv6Address dest, uint32_t interface);
+
+    /**
+     * \brief Create a route to a network.
+     * \param network network address
+     * \param networkPrefix network prefix
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface);
+
+    /**
+     * \brief Create a route to a network.
+     * \param network network address
+     * \param networkPrefix network prefix
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \param prefixToUse prefix that should be used for source address for this destination
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse);
+
+    /**
+     * \brief Create a route to a network.
+     * \param network network address
+     * \param networkPrefix network prefix
+     * \param interface interface index
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface);
+
+    /**
+     * \brief Create a default route.
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \return IPv6Route object
+     */
+    static Ipv6RoutingTableEntry CreateDefaultRoute (Ipv6Address nextHop, uint32_t interface);
+
+  private:
+    /**
+     * \brief Constructor.
+     * \param network network address
+     * \param prefix network prefix
+     * \param gateway the gateway
+     * \param interface the interface index
+     */
+    Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix prefix, Ipv6Address gateway, uint32_t interface);
+
+    /**
+     * \brief Constructor.
+     * \param network network address
+     * \param prefix network prefix
+     * \param interface the interface index
+     * \param prefixToUse prefix to use
+     */
+    Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix prefix, uint32_t interface, Ipv6Address prefixToUse);
+
+    /**
+     * \brief Constructor.
+     * \param network network address
+     * \param prefix network prefix
+     * \param gateway the gateway
+     * \param interface the interface index
+     * \param prefixToUse prefix to use
+     */
+    Ipv6RoutingTableEntry (Ipv6Address network, Ipv6Prefix prefix, Ipv6Address gateway, uint32_t interface, Ipv6Address prefixToUse);  
+
+    /**
+     * \brief Constructor.
+     * \param dest destination address
+     * \param prefix destiation prefix
+     * \param interface interface index
+     */
+    Ipv6RoutingTableEntry (Ipv6Address dest, Ipv6Prefix prefix, uint32_t interface);
+
+    /**
+     * \brief Constructor.
+     * \param dest destination address
+     * \param gateway the gateway
+     * \param interface interface index
+     */
+    Ipv6RoutingTableEntry (Ipv6Address dest, Ipv6Address gateway, uint32_t interface);
+
+    /**
+     * \brief Constructor.
+     * \param dest destination address
+     * \param interface interface index
+     */
+    Ipv6RoutingTableEntry (Ipv6Address dest, uint32_t interface);
+
+    /**
+     * \brief IPv6 address of the destination.
+     */
+    Ipv6Address m_dest;
+
+    /**
+     * \brief IPv6 prefix of the destination
+     */
+    Ipv6Prefix m_destNetworkPrefix;
+
+    /**
+     * \brief IPv6 address of the gateway.
+     */
+    Ipv6Address m_gateway;
+
+    /**
+     * \brief The interface index.
+     */
+    uint32_t m_interface;
+
+    /**
+     * \brief Prefix to use.
+     */
+    Ipv6Address m_prefixToUse;
+
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv6RoutingTableEntry const& route);
+
+/**
+ * \class Ipv6MulticastRoutingTableEntry
+ * \brief A record of an IPv6 multicast route.
+ */
+class Ipv6MulticastRoutingTableEntry
+{
+  public:
+    /**
+     * \brief Constructor.
+     */
+    Ipv6MulticastRoutingTableEntry ();
+
+    /**
+     * \brief Copy constructor.
+     * \param route the route to copy
+     */
+    Ipv6MulticastRoutingTableEntry (Ipv6MulticastRoutingTableEntry const & route);
+
+    /**
+     * \brief Copy constructor.
+     * \param route the route to copy
+     */
+    Ipv6MulticastRoutingTableEntry (Ipv6MulticastRoutingTableEntry const* route);
+
+    /**
+     * \brief Get the source of this route
+     * \return IPv6 address of the source of this route
+     */
+    Ipv6Address GetOrigin () const;
+
+    /**
+     * \brief Get the group.
+     * \return IPv6 address of the multicast group of this route
+     */
+    Ipv6Address GetGroup () const;
+
+    /**
+     * \brief Get the input interface address.
+     * \return input interface index
+     */
+    uint32_t GetInputInterface () const;
+
+    /**
+     * \brief Get the number of output interfaces of this route.
+     * \return number of output interfaces of this route.
+     */
+    uint32_t GetNOutputInterfaces () const;
+
+    /**
+     * \brief Get a specified output interface.
+     * \param n index
+     * \return a specified output interface
+     */
+    uint32_t GetOutputInterface (uint32_t n) const;
+
+    /**
+     * \brief Get all of the output interfaces of this route.
+     * \return a vector of all output interfaces of this route
+     */
+    std::vector<uint32_t> GetOutputInterfaces () const;
+
+    /**
+     * \brief Create a multicast route.
+     * \param origin IPv6 address of the origin source
+     * \param group Ipv6Address of the group
+     * \param inputInterface interface number
+     * \param outputInterfaces list of output interface number
+     * \return a multicast route
+     */
+    static Ipv6MulticastRoutingTableEntry CreateMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
+
+  private:
+    /**
+     * \brief Constructor.
+     * \param origin IPv6 address of the source
+     * \param group IPv6 address of the group
+     * \param inputInterface interface number
+     * \param outputInterfaces list of output interface number
+     */
+    Ipv6MulticastRoutingTableEntry (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
+
+    /**
+     * \brief The IPv6 address of the source.
+     */
+    Ipv6Address m_origin;
+
+    /**
+     * \brief The IPv6 address of the group.
+     */
+    Ipv6Address m_group;
+
+    /**
+     * \brief The input interface.
+     */
+    uint32_t m_inputInterface;
+
+    /**
+     * \brief The output interfaces.
+     */
+    std::vector<uint32_t> m_outputInterfaces;
+};
+
+std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoutingTableEntry const& route);
+
+} /* namespace ns3 */
+
+#endif /* IPV6_ROUTING_TABLE_ENTRY_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/static-routing/ipv6-static-routing.cc	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,793 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/ipv6-route.h"
+#include "ns3/net-device.h"
+
+#include "ipv6-static-routing.h"
+#include "ipv6-routing-table-entry.h"
+
+namespace ns3
+{
+
+NS_LOG_COMPONENT_DEFINE ("Ipv6StaticRouting");
+
+TypeId Ipv6StaticRouting::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::Ipv6StaticRouting")
+    .SetParent<Ipv6RoutingProtocol> ()
+    .AddConstructor<Ipv6StaticRouting> ()
+    ;
+  return tid;
+}
+
+Ipv6StaticRouting::Ipv6StaticRouting ()
+  : m_defaultRoute (0),
+  m_ipv6 (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+Ipv6StaticRouting::~Ipv6StaticRouting ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void Ipv6StaticRouting::SetIpv6 (Ptr<Ipv6> ipv6)
+{
+  NS_LOG_FUNCTION (this << ipv6);
+  NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
+  uint32_t i = 0; 
+  m_ipv6 = ipv6;
+  
+  for (i = 0 ; i < m_ipv6->GetNInterfaces () ; i++)
+  {
+    if (m_ipv6->IsUp (i))
+    {
+      NotifyInterfaceUp (i);
+    }
+    else
+    {
+      NotifyInterfaceDown (i);
+    }
+  }
+}
+
+void Ipv6StaticRouting::AddHostRouteTo (Ipv6Address dst, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  NS_LOG_FUNCTION (this << dst << nextHop << interface << prefixToUse);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateHostRouteTo (dst, nextHop, interface, prefixToUse);
+  m_hostRoutes.push_back (route);
+}
+
+void Ipv6StaticRouting::AddHostRouteTo (Ipv6Address dst, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << dst << interface);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateHostRouteTo (dst, interface);
+  m_hostRoutes.push_back (route);
+}
+
+void Ipv6StaticRouting::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface);
+  m_networkRoutes.push_back (route);
+}
+
+void Ipv6StaticRouting::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface << prefixToUse);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface, prefixToUse);
+  m_networkRoutes.push_back (route);
+}
+
+
+void Ipv6StaticRouting::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface);
+  m_networkRoutes.push_back (route);
+}
+
+void Ipv6StaticRouting::SetDefaultRoute (Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  NS_LOG_FUNCTION (this << nextHop << interface << prefixToUse);
+  Ipv6RoutingTableEntry* route = new Ipv6RoutingTableEntry ();
+  *route = Ipv6RoutingTableEntry::CreateDefaultRoute (nextHop, interface);
+  route->SetPrefixToUse (prefixToUse);
+  delete m_defaultRoute;
+  m_defaultRoute = route;
+}
+
+void Ipv6StaticRouting::RemoveDefaultRoute ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_defaultRoute)
+  {
+    delete m_defaultRoute;
+    m_defaultRoute = 0;
+  }
+}
+
+void Ipv6StaticRouting::AddMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces)
+{
+  NS_LOG_FUNCTION (this << origin << group << inputInterface);
+  Ipv6MulticastRoutingTableEntry* route = new Ipv6MulticastRoutingTableEntry ();
+  *route = Ipv6MulticastRoutingTableEntry::CreateMulticastRoute (origin, group, inputInterface, outputInterfaces);
+  m_multicastRoutes.push_back (route);
+}
+
+void Ipv6StaticRouting::SetDefaultMulticastRoute (uint32_t outputInterface)
+{
+  NS_LOG_FUNCTION (this << outputInterface);
+  Ipv6RoutingTableEntry *route = new Ipv6RoutingTableEntry ();
+  Ipv6Address network = Ipv6Address ("ff00::"); /* RFC 3513 */
+  Ipv6Prefix networkMask = Ipv6Prefix (8);
+  *route = Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkMask, outputInterface);
+  m_networkRoutes.push_back (route);
+}
+
+uint32_t Ipv6StaticRouting::GetNMulticastRoutes () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_multicastRoutes.size ();
+}
+
+Ipv6MulticastRoutingTableEntry Ipv6StaticRouting::GetMulticastRoute (uint32_t index) const
+{
+  NS_LOG_FUNCTION (this << index);
+  NS_ASSERT_MSG (index < m_multicastRoutes.size (), "Ipv6StaticRouting::GetMulticastRoute () : Index out of range");
+
+  if (index < m_multicastRoutes.size ())
+  {
+    uint32_t tmp = 0;
+    for (MulticastRoutesCI i = m_multicastRoutes.begin () ; i != m_multicastRoutes.end () ; i++)
+    {
+      if (tmp  == index)
+      {
+        return *i;
+      }
+      tmp++;
+    }
+  }
+  return 0;
+}
+
+bool Ipv6StaticRouting::RemoveMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface)
+{
+  NS_LOG_FUNCTION (this << origin << group << inputInterface);
+  for (MulticastRoutesI i = m_multicastRoutes.begin (); i != m_multicastRoutes.end (); i++)
+  {
+    Ipv6MulticastRoutingTableEntry *route = *i;
+    if (origin == route->GetOrigin () &&
+        group == route->GetGroup () &&
+        inputInterface == route->GetInputInterface ())
+    {
+      delete *i;
+      m_multicastRoutes.erase (i);
+      return true;
+    }
+  }
+  return false;
+}
+
+void Ipv6StaticRouting::RemoveMulticastRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION (this << index);
+  uint32_t tmp = 0;
+  
+  for (MulticastRoutesI i = m_multicastRoutes.begin () ; i != m_multicastRoutes.end () ; i++)
+  {
+    if (tmp == index)
+    {
+      delete *i;
+      m_multicastRoutes.erase (i);
+      return;
+    }
+    tmp++;
+  }
+}
+
+bool Ipv6StaticRouting::HasNetworkDest (Ipv6Address network, uint32_t interfaceIndex)
+{
+  NS_LOG_FUNCTION (this << network << interfaceIndex);
+
+  /* in the network table */
+  for (NetworkRoutesI j = m_networkRoutes.begin () ; j != m_networkRoutes.end () ; j++)
+  {
+    NS_ASSERT ((*j)->IsNetwork ());
+    Ipv6Prefix prefix = (*j)->GetDestNetworkPrefix ();
+    Ipv6Address entry = (*j)->GetDestNetwork ();
+
+    if (prefix.IsMatch (network, entry) && (*j)->GetInterface () == interfaceIndex)
+    {
+      return true;
+    }
+  }
+
+  /* beuh!!! not route at all */
+  return false;
+}
+
+Ptr<Ipv6Route> Ipv6StaticRouting::LookupStatic (Ipv6Address dst, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << dst << interface);
+  Ptr<Ipv6Route> rtentry = 0;
+
+  /* when sending on link-local multicast, there have to be interface specified */
+  if (dst == Ipv6Address::GetAllNodesMulticast () || dst.IsSolicitedMulticast () || 
+     dst == Ipv6Address::GetAllRoutersMulticast () || dst == Ipv6Address::GetAllHostsMulticast ())
+  {
+    NS_ASSERT_MSG (interface > 0, "Try to send on link-local multicast address, and no interface index is given!");
+    rtentry = Create<Ipv6Route> ();
+    rtentry->SetSource (SourceAddressSelection (interface, dst));
+    rtentry->SetDestination (dst);
+    rtentry->SetGateway (Ipv6Address::GetZero ());
+    rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interface));
+    return rtentry;
+  }
+
+  /* is the destination in hosts table */
+  for (HostRoutesCI i = m_hostRoutes.begin () ; i != m_hostRoutes.end () ; i++)
+  {
+    NS_ASSERT ((*i)->IsHost ());
+    if ((*i)->GetDest ().IsEqual (dst))
+    {
+      if (!interface || interface == (*i)->GetInterface ())
+      {
+        NS_LOG_LOGIC ("Found global host route " << *i);
+        Ipv6RoutingTableEntry* route = (*i);
+        rtentry = Create<Ipv6Route> ();
+        uint32_t interfaceIdx = route->GetInterface ();
+        rtentry->SetDestination (route->GetDest ());
+
+        if (route->GetGateway ().IsAny ())
+        {
+          rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetDest ()));
+        }
+        else
+        {
+          rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetGateway ()));
+        }
+
+        rtentry->SetGateway (route->GetGateway ());
+        rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
+        return rtentry;
+      }
+    }
+  }
+
+  /* or in the network table */
+  for (NetworkRoutesI j = m_networkRoutes.begin () ; j != m_networkRoutes.end () ; j++)
+  {
+    NS_ASSERT ((*j)->IsNetwork ());
+    Ipv6Prefix prefix = (*j)->GetDestNetworkPrefix ();
+    Ipv6Address entry = (*j)->GetDestNetwork ();
+
+    if (prefix.IsMatch (dst, entry))
+    {
+      /* if interface is given, check the route will output on this interface */
+      if (!interface || interface == (*j)->GetInterface ())
+      {
+        NS_LOG_LOGIC ("Found global network route " << *j);
+        Ipv6RoutingTableEntry* route = (*j);
+        rtentry = Create<Ipv6Route>();
+        uint32_t interfaceIdx = route->GetInterface ();
+        rtentry->SetDestination (route->GetDest ());
+        
+        if (route->GetGateway ().IsAny ())
+        {
+          rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetDest ()));
+        }
+        else
+        {
+          rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetGateway ()));
+        }
+
+        rtentry->SetGateway (route->GetGateway ());
+        rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
+        return rtentry;
+      }
+    }
+  }
+
+  /* not found, return the default route if any */
+  if (m_defaultRoute != 0)
+  {
+    NS_ASSERT (m_defaultRoute->IsDefault ());
+    NS_LOG_LOGIC ("Found global network route via default route " << m_defaultRoute);
+    Ipv6RoutingTableEntry* route = m_defaultRoute;
+    rtentry = Create<Ipv6Route>();
+    uint32_t interfaceIdx = route->GetInterface ();
+    rtentry->SetDestination (route->GetDest ());
+    rtentry->SetSource (SourceAddressSelection (interfaceIdx, route->GetPrefixToUse ().IsAny () ? route->GetGateway () : route->GetPrefixToUse ()));
+    rtentry->SetGateway (route->GetGateway ());
+    rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
+    return rtentry;
+  }  
+
+  /* beuh!!! not route at all */
+  return 0;
+}
+
+void Ipv6StaticRouting::DoDispose ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (HostRoutesI i = m_hostRoutes.begin () ; i != m_hostRoutes.end () ; i = m_hostRoutes.erase (i))
+  {
+    delete (*i);
+  }
+  m_hostRoutes.clear ();
+  
+  for (NetworkRoutesI j = m_networkRoutes.begin () ;  j != m_networkRoutes.end () ; j = m_networkRoutes.erase (j))
+  {
+    delete (*j);
+  }
+  m_networkRoutes.clear ();
+  
+  if (m_defaultRoute != 0)
+  {
+    delete m_defaultRoute;
+    m_defaultRoute = 0;
+  }
+  
+  for (MulticastRoutesI i = m_multicastRoutes.begin () ; i != m_multicastRoutes.end () ; i = m_multicastRoutes.erase (i))
+  {
+    delete (*i);
+  }
+  m_multicastRoutes.clear ();
+
+  m_ipv6 = 0;
+  Ipv6RoutingProtocol::DoDispose ();
+}
+
+Ptr<Ipv6MulticastRoute> Ipv6StaticRouting::LookupStatic (Ipv6Address origin, Ipv6Address group, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << origin << group << interface);
+  Ptr<Ipv6MulticastRoute> mrtentry = 0;
+
+  for (MulticastRoutesI i = m_multicastRoutes.begin () ; i != m_multicastRoutes.end () ; i++)
+  {
+    Ipv6MulticastRoutingTableEntry* route = *i;
+
+    /*
+       We've been passed an origin address, a multicast group address and an
+       interface index.  We have to decide if the current route in the list is
+       a match.
+
+       The first case is the restrictive case where the origin, group and index
+       matches.  This picks up exact routes during forwarded and exact routes from
+       the local node (in which case the ifIndex is a wildcard).
+     */
+
+    if (origin == route->GetOrigin () && group == route->GetGroup ())
+    {
+      /* skipping SSM case */
+      NS_LOG_LOGIC ("Find source specific multicast route" << *i);
+    }
+
+    if (group == route->GetGroup ())
+    {
+       if (interface == Ipv6::IF_ANY || interface == route->GetInputInterface ())
+       {
+          NS_LOG_LOGIC ("Found multicast route" << *i);
+          mrtentry = Create<Ipv6MulticastRoute>();
+          mrtentry->SetGroup (route->GetGroup ());
+          mrtentry->SetOrigin (route->GetOrigin ());
+          mrtentry->SetParent (route->GetInputInterface ());
+          for (uint32_t j = 0 ; j < route->GetNOutputInterfaces () ; j++)
+          {
+            if (route->GetOutputInterface (j))
+            {
+              NS_LOG_LOGIC ("Setting output interface index " << route->GetOutputInterface (j));
+              mrtentry->SetOutputTtl (route->GetOutputInterface (j), Ipv6MulticastRoute::MAX_TTL - 1);
+            }
+          }
+          return mrtentry;
+       } 
+    }
+  }
+  return mrtentry;
+}
+
+uint32_t Ipv6StaticRouting::GetNRoutes ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  uint32_t n = 0;
+  if (m_defaultRoute != 0)
+  {
+    n++;
+  }
+  n += m_hostRoutes.size ();
+  n += m_networkRoutes.size ();
+  return n;
+}
+
+Ipv6RoutingTableEntry Ipv6StaticRouting::GetDefaultRoute ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (m_defaultRoute != 0)
+  {
+    return *m_defaultRoute;
+  }
+  else
+  {
+    return Ipv6RoutingTableEntry ();
+  }
+}
+
+Ipv6RoutingTableEntry Ipv6StaticRouting::GetRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION (this << index);
+
+  if (index == 0 && m_defaultRoute != 0)
+  {
+    return *m_defaultRoute;
+  }
+
+  if (index > 0 && m_defaultRoute != 0)
+  {
+    index--;
+  }
+
+  if (index < m_hostRoutes.size ())
+  {
+    uint32_t tmp = 0;
+    for (HostRoutesCI i = m_hostRoutes.begin () ; i != m_hostRoutes.end () ; i++)
+    {
+      if (tmp == index)
+      {
+        return *i;
+      }
+      tmp++;
+    }
+  }
+  
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+
+  for (NetworkRoutesI j = m_networkRoutes.begin () ; j != m_networkRoutes.end () ; j++)
+  {
+    if (tmp == index)
+    {
+      return *j;
+    }
+    tmp++;
+  }
+  NS_ASSERT (false);
+  // quiet compiler.
+  return 0;
+}
+
+void Ipv6StaticRouting::RemoveRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION (this << index);
+  if (index == 0 && m_defaultRoute != 0)
+  {
+    delete m_defaultRoute;
+    m_defaultRoute = 0;
+  }
+  
+  if (index > 0 && m_defaultRoute != 0)
+  {
+    index--;
+  }
+  
+  if (index < m_hostRoutes.size ())
+  {
+    uint32_t tmp = 0;
+    for (HostRoutesI i = m_hostRoutes.begin () ; i != m_hostRoutes.end () ; i++)
+    {
+      if (tmp  == index)
+      {
+        delete *i;
+        m_hostRoutes.erase (i);
+        return;
+      }
+      tmp++;
+    }
+  }
+  index -= m_hostRoutes.size ();
+  uint32_t tmp = 0;
+  
+  for (NetworkRoutesI j = m_networkRoutes.begin () ; j != m_networkRoutes.end () ; j++)
+  {
+    if (tmp == index)
+    {
+      delete *j;
+      m_networkRoutes.erase (j);
+      return;
+    }
+    tmp++;
+  }
+  NS_ASSERT (false);
+}
+
+void Ipv6StaticRouting::RemoveRoute (Ipv6Address network, Ipv6Prefix prefix, uint32_t ifIndex)
+{
+  NS_LOG_FUNCTION (this << network << prefix << ifIndex);
+  for (NetworkRoutesI i = m_networkRoutes.begin () ; i != m_networkRoutes.end () ; i++)
+  {
+    if (network == (*i)->GetDest () and (*i)->GetInterface () == ifIndex)
+    {
+      delete *i;
+      m_networkRoutes.erase (i);
+      return;
+    }
+  }
+}
+
+Ptr<Ipv6Route> Ipv6StaticRouting::RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
+{
+  NS_LOG_FUNCTION (this << header << oif);
+  Ipv6Address destination = header.GetDestinationAddress ();
+  Ptr<Ipv6Route> rtentry = 0;
+
+  if (destination.IsMulticast ())
+  {
+    // Note:  Multicast routes for outbound packets are stored in the
+    // normal unicast table.  An implication of this is that it is not
+    // possible to source multicast datagrams on multiple interfaces.
+    // This is a well-known property of sockets implementation on
+    // many Unix variants.
+    // So, we just log it and fall through to LookupStatic ()
+    NS_LOG_LOGIC ("RouteOutput ()::Multicast destination");
+  }
+  
+  rtentry = LookupStatic (destination, oif);
+  if (rtentry)
+  {
+    sockerr = Socket::ERROR_NOTERROR;
+  }
+  else
+  {
+    sockerr = Socket::ERROR_NOROUTETOHOST;
+  }
+  return rtentry;
+}
+
+bool Ipv6StaticRouting::RouteInput (Ptr<const Packet> p, const Ipv6Header &ipHeader, Ptr<const NetDevice> idev,
+                                    UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                                    LocalDeliverCallback lcb, ErrorCallback ecb)
+{
+  NS_LOG_FUNCTION (this << p << ipHeader << ipHeader.GetSourceAddress () << ipHeader.GetDestinationAddress () << idev);
+
+  if (ipHeader.GetDestinationAddress ().IsMulticast ())
+  {
+    NS_LOG_LOGIC ("Multicast destination");
+    Ptr<Ipv6MulticastRoute> mrtentry = LookupStatic (ipHeader.GetSourceAddress (),
+    ipHeader.GetDestinationAddress (), m_ipv6->GetInterfaceForDevice (idev));
+
+    if (mrtentry)
+    {
+      NS_LOG_LOGIC ("Multicast route found");
+      mcb (mrtentry, p, ipHeader); // multicast forwarding callback
+      return true;
+    }
+    else
+    {
+      NS_LOG_LOGIC ("Multicast route not found");
+      return false; // Let other routing protocols try to handle this
+    }
+  }
+//
+// This is a unicast packet.  Check to see if we have a route for it.
+//
+  NS_LOG_LOGIC ("Unicast destination");
+  Ptr<Ipv6Route> rtentry = LookupStatic (ipHeader.GetDestinationAddress ());
+
+  if (rtentry != 0)
+  {
+    NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
+    ucb (rtentry, p, ipHeader);  // unicast forwarding callback
+    return true;
+  }
+  else
+  {
+    NS_LOG_LOGIC ("Did not find unicast destination- returning false");
+    return false; // Let other routing protocols try to handle this
+  }
+}
+
+void Ipv6StaticRouting::NotifyInterfaceUp (uint32_t i)
+{
+  for (uint32_t j = 0 ; j < m_ipv6->GetNAddresses (i) ; j++)
+  {
+    if (m_ipv6->GetAddress (i, j).GetAddress () != Ipv6Address () &&
+       m_ipv6->GetAddress (i, j).GetPrefix () != Ipv6Prefix ())
+    {
+      if (m_ipv6->GetAddress (i, j).GetPrefix () == Ipv6Prefix (128))
+      {
+        /* host route */
+        AddHostRouteTo (m_ipv6->GetAddress (i, j).GetAddress (), i);
+      }
+      else
+      {
+        AddNetworkRouteTo (m_ipv6->GetAddress (i, j).GetAddress ().CombinePrefix (m_ipv6->GetAddress (i, j).GetPrefix ()),
+                          m_ipv6->GetAddress (i, j).GetPrefix (), i);
+      }
+    }
+  }
+}
+
+void Ipv6StaticRouting::NotifyInterfaceDown (uint32_t i)
+{
+  /* remove all static routes that are going through this interface */
+  for (uint32_t j = 0 ; j < GetNRoutes () ; j++)
+  {
+    Ipv6RoutingTableEntry route = GetRoute (j);
+
+    if (route.GetInterface () == i)
+    {
+      RemoveRoute (j);
+    }
+  }
+}
+
+void Ipv6StaticRouting::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address)
+{
+  if (!m_ipv6->IsUp (interface))
+  {
+    return;
+  }
+
+  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
+  Ipv6Prefix networkMask = address.GetPrefix ();
+
+  if (address.GetAddress () != Ipv6Address () && address.GetPrefix () != Ipv6Prefix ())
+  {
+    AddNetworkRouteTo (networkAddress, networkMask, interface);
+  }
+}
+
+void Ipv6StaticRouting::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address)
+{
+  if (!m_ipv6->IsUp (interface))
+  {
+    return;
+  }
+
+  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
+  Ipv6Prefix networkMask = address.GetPrefix ();
+  
+  // Remove all static routes that are going through this interface
+  // which reference this network
+  for (uint32_t j = 0 ; j < GetNRoutes () ; j++)
+  {
+    Ipv6RoutingTableEntry route = GetRoute (j);
+    
+    if (route.GetInterface () == interface &&
+        route.IsNetwork () &&
+        route.GetDestNetwork () == networkAddress &&
+        route.GetDestNetworkPrefix () == networkMask)
+    {
+      RemoveRoute (j);
+    }
+  }
+}
+
+void Ipv6StaticRouting::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
+{
+  NS_LOG_INFO (this << dst << mask << nextHop << interface << prefixToUse);
+  if (mask == Ipv6Prefix (128))
+  {
+    AddHostRouteTo (dst, nextHop, interface);
+  }
+  else if (dst != Ipv6Address::GetZero ())
+  {
+    AddNetworkRouteTo (dst, mask, nextHop, interface);
+  }
+  else /* default route */
+  {
+    /* this case is mainly used by configuring default route following RA processing,
+     * in case of multipe prefix in RA, the first will configured default route
+     */
+    if (!m_defaultRoute)
+    {
+      SetDefaultRoute (nextHop, interface, prefixToUse);
+    }
+  }
+}
+
+void Ipv6StaticRouting::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface)
+{
+  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
+  if (mask == Ipv6Prefix (128))
+  {
+    for (HostRoutesI j = m_hostRoutes.begin () ; j != m_hostRoutes.end () ; j++)
+    {
+      Ipv6Prefix prefix = (*j)->GetDestNetworkPrefix ();
+      Ipv6Address entry = (*j)->GetDestNetwork ();
+
+      if (dst == entry && prefix == mask && (*j)->GetInterface () == interface)
+      {
+        delete (*j);
+        m_hostRoutes.erase (j);
+      } 
+    }
+  }
+  else if (dst != Ipv6Address::GetZero ())
+  {
+    for (NetworkRoutesI j = m_networkRoutes.begin () ; j != m_networkRoutes.end () ; j++)
+    {
+      Ipv6Prefix prefix = (*j)->GetDestNetworkPrefix ();
+      Ipv6Address entry = (*j)->GetDestNetwork ();
+
+      if (dst == entry && prefix == mask && (*j)->GetInterface () == interface)
+      {
+        delete (*j);
+        m_networkRoutes.erase (j);
+      } 
+    }
+  }
+  else
+  {
+    /* default route case */
+    if (!m_defaultRoute)
+    {
+      return;
+    }
+
+    if (m_defaultRoute->GetInterface () == interface && m_defaultRoute->GetGateway () == nextHop)
+    {
+      NS_LOG_LOGIC ("Remove default route (maybe because autoconfigured address expired)");
+      delete m_defaultRoute;
+      m_defaultRoute = 0;
+    }
+  }
+}
+
+Ipv6Address Ipv6StaticRouting::SourceAddressSelection (uint32_t interface, Ipv6Address dest)
+{
+  NS_LOG_FUNCTION (this << interface << dest);
+  Ipv6Address ret;
+
+  /* first address of an IPv6 interface is link-local ones */
+  ret = m_ipv6->GetAddress (interface, 0).GetAddress ();
+
+  if (dest == Ipv6Address::GetAllNodesMulticast () || dest == Ipv6Address::GetAllRoutersMulticast () || dest == Ipv6Address::GetAllHostsMulticast ())
+  {
+    return ret; 
+  }
+
+  /* useally IPv6 interfaces have one link-local address and one global address */
+
+  for (uint32_t i = 1 ; i < m_ipv6->GetNAddresses (interface) ; i++)
+  {
+    Ipv6InterfaceAddress test = m_ipv6->GetAddress (interface, i);
+
+    if (test.GetAddress ().CombinePrefix (test.GetPrefix ()) == dest.CombinePrefix (test.GetPrefix ()))
+    {
+      return test.GetAddress ();
+    }
+  }
+  
+  return ret;
+}
+
+} /* namespace ns3 */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/static-routing/ipv6-static-routing.h	Wed Aug 26 15:29:03 2009 +0400
@@ -0,0 +1,303 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007-2009 Strasbourg University
+ *
+ * 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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
+ */
+
+#ifndef IPV6_STATIC_ROUTING_H
+#define IPV6_STATIC_ROUTING_H
+
+#include <list>
+#include <stdint.h>
+
+#include "ns3/ptr.h"
+#include "ns3/ipv6-address.h"
+#include "ns3/ipv6.h"
+#include "ns3/ipv6-header.h"
+#include "ns3/ipv6-routing-protocol.h"
+
+namespace ns3
+{
+
+class Packet;
+class NetDevice;
+class Ipv6Interface;
+class Ipv6Route;
+class Node;
+class Ipv6RoutingTableEntry;
+class Ipv6MulticastRoutingTableEntry;
+
+/**
+ * \ingroup routing
+ * \defgroup ipv6StaticRouting Ipv6StaticRouting
+ * \class Ipv6StaticRouting
+ * \brief Static routing protocol for IP version 6 stack.
+ * \see Ipv6RoutingProtocol
+ * \see Ipv6ListRouting
+ */
+class Ipv6StaticRouting : public Ipv6RoutingProtocol
+{
+  public:
+    /**
+     * \brief The interface Id associated with this class.
+     * \return type identificator
+     */
+    static TypeId GetTypeId ();
+
+    /**
+     * \brief Constructor.
+     */
+    Ipv6StaticRouting ();
+
+    /**
+     * \brief Destructor.
+     */
+    virtual ~Ipv6StaticRouting ();
+
+    /**
+     * \brief Add route to host.
+     * \param dest destination address
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \param prefixToUse prefix that should be used for source address for this destination
+     */
+    void AddHostRouteTo (Ipv6Address dest, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address ("::"));
+
+    /**
+     * \brief Add route to host.
+     * \param dest destination address.
+     * \param interface interface index
+     */
+    void AddHostRouteTo (Ipv6Address dest, uint32_t interface);
+
+    /**
+     * \brief Add route to network.
+     * \param network network address
+     * \param networkPrefix network prefix*
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     */
+    void AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface);
+
+    /**
+     * \brief Add route to network.
+     * \param network network address
+     * \param networkPrefix network prefix*
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \param prefixToUse prefix that should be used for source address for this destination
+     */
+    void AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse);
+
+    /**
+     * \brief Add route to network.
+     * \param network network address
+     * \param networkPrefix network prefix
+     * \param interface interface index
+     */
+    void AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface);
+
+    /**
+     * \brief Set the default route.
+     * \param nextHop next hop address to route the packet
+     * \param interface interface index
+     * \param prefixToUse prefix to use (i.e for multihoming)
+     */
+    void SetDefaultRoute (Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address ("::"));
+
+    /**
+     * \brief Remove the default route.
+     */
+    void RemoveDefaultRoute ();
+
+    /**
+     * \brief Get the number or entries in the routing table.
+     * \return number of entries
+     */
+    uint32_t GetNRoutes ();
+
+    /**
+     * \brief Get the default route.
+     * \return default Ipv6Route
+     */
+    Ipv6RoutingTableEntry GetDefaultRoute ();
+
+    /**
+     * \brief Get a specified route.
+     * \param i index
+     * \return the route whose index is i
+     */
+    Ipv6RoutingTableEntry GetRoute (uint32_t i);
+
+    /**
+     * \brief Remove a route from the routing table.
+     * \param i index
+     */
+    void RemoveRoute (uint32_t i);
+
+    /**
+     * \brief Remove a route from the routing table.
+     * \param network IPv6 network
+     * \param prefix IPv6 prefix
+     * \param ifIndex interface index
+     */
+    void RemoveRoute (Ipv6Address network, Ipv6Prefix prefix, uint32_t ifIndex);
+
+    /**
+     * \brief Add a multicast route for a given multicast source and group.
+     * \param origin IPv6 address of the source
+     * \param group the multicast group address.
+     * \param inputInterface the interface index
+     * \param outputInterfaces the list of output interface indices over which the packet
+     * should be sent (excluding the inputInterface).
+     */
+    void AddMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector<uint32_t> outputInterfaces);
+
+    /**
+     * \brief Set the default multicast route.
+     * \param outputInterface default output interface
+     */
+    void SetDefaultMulticastRoute (uint32_t outputInterface);
+
+    /**
+     * \brief Get the number of entries in the multicast routing table.
+     * \return number of entries
+     */
+    uint32_t GetNMulticastRoutes () const;
+
+    /**
+     * \brief Get the specified multicast route.
+     * \param i index
+     * \return the route whose index is i
+     */
+    Ipv6MulticastRoutingTableEntry GetMulticastRoute (uint32_t i) const;
+
+    /**
+     * \brief Get the default multicast IPv6 route.
+     * \return default Ipv6MulticastRoute
+     */
+    Ipv6MulticastRoutingTableEntry GetDefaultMulticastRoute () const;
+
+    /**
+     * \brief Remove a static multicast route.
+     * \param origin IPv6 address of the source
+     * \param group the multicast group address.
+     * \param inputInterface the input interface index
+     */
+    bool RemoveMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface);
+
+    /**
+     * \brief Remove a multicast route.
+     * \param i index of route to remove
+     */
+    void RemoveMulticastRoute (uint32_t i);
+
+    /**
+     * \brief If the destination is already present in network destination list.
+     * \param dest destination address
+     * \param interfaceIndex interface index
+     * \return true if dest is already in list, false otherwise
+     */
+    bool HasNetworkDest (Ipv6Address dest, uint32_t interfaceIndex);
+
+    virtual Ptr<Ipv6Route> RouteOutput (Ptr<Packet> p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+
+    virtual bool RouteInput  (Ptr<const Packet> p, const Ipv6Header &header, Ptr<const NetDevice> idev,
+                             UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                             LocalDeliverCallback lcb, ErrorCallback ecb);
+
+    virtual void NotifyInterfaceUp (uint32_t interface);
+    virtual void NotifyInterfaceDown (uint32_t interface);
+    virtual void NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address);
+    virtual void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address);
+    virtual void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ());
+    virtual void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface);
+    virtual void SetIpv6 (Ptr<Ipv6> ipv6);
+
+  protected:
+    /**
+     * \brief Dispose this object.
+     */
+    void DoDispose ();
+
+  private:
+    typedef std::list<Ipv6RoutingTableEntry *> HostRoutes;
+    typedef std::list<Ipv6RoutingTableEntry *>::const_iterator HostRoutesCI;
+    typedef std::list<Ipv6RoutingTableEntry *>::iterator HostRoutesI;
+    typedef std::list<Ipv6RoutingTableEntry *> NetworkRoutes;
+    typedef std::list<Ipv6RoutingTableEntry *>::const_iterator NetworkRoutesCI;
+    typedef std::list<Ipv6RoutingTableEntry *>::iterator NetworkRoutesI;
+
+    typedef std::list<Ipv6MulticastRoutingTableEntry *> MulticastRoutes;
+    typedef std::list<Ipv6MulticastRoutingTableEntry *>::const_iterator MulticastRoutesCI;
+    typedef std::list<Ipv6MulticastRoutingTableEntry *>::iterator MulticastRoutesI;
+
+    /**
+     * \brief Lookup in the forwarding table for destination.
+     * \param dest destination address
+     * \param interface output interface if any (put 0 otherwise)
+     * \return Ipv6Route to route the packet to reach dest address
+     */
+    Ptr<Ipv6Route> LookupStatic (Ipv6Address dest, uint32_t interface = 0);
+
+    /**
+     * \brief Lookup in the multicast forwarding table for destination.
+     * \param origin source address
+     * \param group group multicast address
+     * \param ifIndex interface index
+     * \return Ipv6MulticastRoute to route the packet to reach dest address
+     */
+    Ptr<Ipv6MulticastRoute> LookupStatic (Ipv6Address origin, Ipv6Address group, uint32_t ifIndex);
+
+    /**
+     * \brief Choose the source address to use with destination address.
+     * \param interface interface index
+     * \param dest IPv6 destination address
+     * \return IPv6 source address to use
+     */
+    Ipv6Address SourceAddressSelection (uint32_t interface, Ipv6Address dest);
+
+    /**
+     * \brief the forwarding table for hosts.
+     */
+    HostRoutes m_hostRoutes;
+
+    /**
+     * \brief the forwarding table for network.
+     */
+    NetworkRoutes m_networkRoutes;
+
+    /**
+     * \brief the default route.
+     */
+    Ipv6RoutingTableEntry *m_defaultRoute;
+
+    /**
+     * \brief the forwarding table for multicast.
+     */
+    MulticastRoutes m_multicastRoutes;
+
+    /**
+     * \brief Ipv6 reference.
+     */
+    Ptr<Ipv6> m_ipv6;
+};
+
+} /* namespace ns3 */
+
+#endif /* IPV6_STATIC_ROUTING_H */
+
--- a/src/routing/static-routing/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/routing/static-routing/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -5,11 +5,15 @@
     module.source = [
         'ipv4-static-routing.cc',
         'ipv4-routing-table-entry.cc',
+        'ipv6-static-routing.cc',
+        'ipv6-routing-table-entry.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'static-routing'
     headers.source = [
         'ipv4-static-routing.h',
         'ipv4-routing-table-entry.h',
+        'ipv6-static-routing.h',
+        'ipv6-routing-table-entry.h',
         ]
 
--- a/src/wscript	Tue Aug 25 20:12:53 2009 +0400
+++ b/src/wscript	Wed Aug 26 15:29:03 2009 +0400
@@ -39,6 +39,8 @@
     'devices/mesh',
     'devices/mesh/dot11s',
     'devices/mesh/flame',
+    'applications/ping6',
+    'applications/radvd',
     )
 
 def set_options(opt):