# HG changeset patch # User Kirill Andreev # Date 1251286143 -14400 # Node ID 9d48acef10b3e99402806d7ba349a5d0f7d79886 # Parent 08d3bef3b477971c802d5f5fb782860966237553# Parent 34acfd7ad508fe189f6b871d10b89c71a256f141 Merge with code.nsnam.org diff -r 08d3bef3b477 -r 9d48acef10b3 AUTHORS --- 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) diff -r 08d3bef3b477 -r 9d48acef10b3 CHANGES.html --- 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 @@

New API:

Changes to existing API:

diff -r 08d3bef3b477 -r 9d48acef10b3 RELEASE_NOTES --- 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 diff -r 08d3bef3b477 -r 9d48acef10b3 bindings/python/ns3_module_core.py --- 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::Connect(ns3::CallbackBase const & cb, std::string path) [member function] + ## traced-value.h: void ns3::TracedValue::Connect(ns3::CallbackBase const & cb, std::basic_string,std::allocator > 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::Disconnect(ns3::CallbackBase const & cb, std::string path) [member function] + ## traced-value.h: void ns3::TracedValue::Disconnect(ns3::CallbackBase const & cb, std::basic_string,std::allocator > 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', diff -r 08d3bef3b477 -r 9d48acef10b3 bindings/python/ns3_module_node.py --- 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', diff -r 08d3bef3b477 -r 9d48acef10b3 bindings/python/ns3_module_olsr.py --- 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): diff -r 08d3bef3b477 -r 9d48acef10b3 bindings/python/ns3_module_wifi.py --- 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 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 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 remoteManager) [member function] - cls.add_method('SetWifiRemoteStationManager', - 'void', - [param('ns3::Ptr< ns3::WifiRemoteStationManager >', 'remoteManager')]) - ## dca-txop.h: void ns3::DcaTxop::SetTxOkCallback(ns3::Callback 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 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 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::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 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 remoteManager) [member function] + cls.add_method('SetWifiRemoteStationManager', + 'void', + [param('ns3::Ptr< ns3::WifiRemoteStationManager >', 'remoteManager')]) + ## dca-txop.h: void ns3::DcaTxop::SetTxOkCallback(ns3::Callback 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 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 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::MakeSsidChecker() [free function] diff -r 08d3bef3b477 -r 9d48acef10b3 examples/icmpv6-redirect.cc --- /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 + */ + +// 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 +#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& n) + { + Ptr routing = 0; + Ipv6StaticRoutingHelper routingHelper; + Ptr ipv6 = n->GetObject (); + 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& n, Ipv6Address dst, Ipv6Address nextHop, uint32_t interface) + { + Ptr routing = 0; + Ipv6StaticRoutingHelper routingHelper; + Ptr ipv6 = n->GetObject (); + + 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 sta1 = CreateObject (); + Ptr r1 = CreateObject (); + Ptr r2 = CreateObject (); + Ptr sta2 = CreateObject (); + 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."); +} + diff -r 08d3bef3b477 -r 9d48acef10b3 examples/multi-rate-first.cc --- 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 +#include NS_LOG_COMPONENT_DEFINE ("Main"); @@ -34,6 +41,7 @@ void AdvancePosition (Ptr node); void BackTrackPosition (Ptr node); void StationaryPosition (Ptr node); + void MultiPosition (Ptr node1, Ptr node2); Ptr SetupPacketReceive (Ptr node); uint32_t m_bytesTotal; @@ -108,6 +116,26 @@ m_output.Add ((Simulator::Now()).GetSeconds(), mbs); } +void +Experiment::MultiPosition (Ptr n1, Ptr 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) @@ -169,21 +197,30 @@ Ptr 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 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 positionAlloc = CreateObject (); + gnuplot = Gnuplot ("multi-rate-first-scen1.eps"); + + positionAlloc = CreateObject (); 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 positionAlloc = CreateObject (); + gnuplot = Gnuplot ("multi-rate-first-scen2.eps"); + + positionAlloc = CreateObject (); 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 positionAlloc = CreateObject (); + + gnuplot = Gnuplot ("multi-rate-first-scen3.eps"); + + positionAlloc = CreateObject (); 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 (); + // 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; } diff -r 08d3bef3b477 -r 9d48acef10b3 examples/multi-rate-second.cc --- 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 n1 = c.Get(0); Ptr ipv41 = n1->GetObject (); - + // 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 ratesControl; + ratesControl.push_back ("Minstrel"); ratesControl.push_back ("Ideal"); - ratesControl.push_back ("Minstrel"); std::vector 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; } diff -r 08d3bef3b477 -r 9d48acef10b3 examples/ping6.cc --- /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 + */ + +// 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 +#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."); +} + diff -r 08d3bef3b477 -r 9d48acef10b3 examples/radvd-two-prefix.cc --- /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 + * Sebastien Vincent + */ + +// 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 +#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& n, uint32_t interface, Ipv6Address address) + { + Ptr ipv6 = n->GetObject (); + ipv6->AddAddress (interface, address); + } + + /** + * \brief Print the routing table. + * \param n the node + */ + inline void PrintRoutingTable (Ptr& n) + { + Ptr routing = 0; + Ipv6StaticRoutingHelper routingHelper; + Ptr ipv6 = n->GetObject (); + 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 n0 = CreateObject (); + Ptr r = CreateObject (); + Ptr n1 = CreateObject (); + + 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 = CreateObject (); + Ptr routerInterface = Create (indexRouter, 2000, 1000); + Ptr routerPrefix = Create (prefix, 64, 3, 5); + Ptr routerPrefixBis = Create (prefixBis, 64, 3, 5); + Ptr routerInterface2 = Create (indexRouter2, 2000, 1000); + Ptr routerPrefix2 = Create (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."); +} + diff -r 08d3bef3b477 -r 9d48acef10b3 examples/radvd.cc --- /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 + * Sebastien Vincent + */ + +// 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 +#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 n0 = CreateObject (); + Ptr r = CreateObject (); + Ptr n1 = CreateObject (); + + 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 = CreateObject (); + Ptr routerInterface = Create (indexRouter, 5000, 1000); + Ptr routerPrefix = Create (prefix, 64, 3, 5); + Ptr routerInterface2 = Create (indexRouter2, 5000, 1000); + Ptr routerPrefix2 = Create (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."); +} + diff -r 08d3bef3b477 -r 9d48acef10b3 examples/simple-routing-ping6.cc --- /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 + * Sebastien Vincent + */ + +// Network topology +// // +// // n0 r n1 +// // | _ | +// // ====|_|==== +// // router +// // +// // - Tracing of queues and packet receptions to file "simple-routing-ping6.tr" + +#include +#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 n0 = CreateObject (); + Ptr r = CreateObject (); + Ptr n1 = CreateObject (); + + 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."); +} + diff -r 08d3bef3b477 -r 9d48acef10b3 examples/static-routing-slash32.cc --- 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); diff -r 08d3bef3b477 -r 9d48acef10b3 examples/wifi-ap.cc --- 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 @@ -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 (); diff -r 08d3bef3b477 -r 9d48acef10b3 examples/wscript --- 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']) diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/ping6/ping6.cc --- /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 + */ + +#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() + .AddConstructor() + .AddAttribute ("MaxPackets", + "The maximum number of packets the application will send", + UintegerValue (100), + MakeUintegerAccessor (&Ping6::m_count), + MakeUintegerChecker()) + .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()) + ; + 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 >()); + } + + 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 p = 0; + uint8_t data[4]; + Ipv6Address src; + Ptr ipv6 = GetNode ()->GetObject (); + + if (m_ifIndex > 0) + { + /* hack to have ifIndex in Ipv6RawSocketImpl + * maybe add a SetIfIndex in Ipv6RawSocketImpl directly + */ + src = GetNode ()->GetObject ()->GetAddress (m_ifIndex, 0).GetAddress (); + } + else + { + src = m_localAddress; + } + + data[0] = 0xDE; + data[1] = 0xAD; + data[2] = 0xBE; + data[3] = 0xEF; + + p = Create(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) +{ + NS_LOG_FUNCTION (this << socket); + + Ptr 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/ping6/ping6.h --- /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 + */ + +#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); + + /** + * \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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/ping6/waf --- /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 "$@" diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/ping6/wscript --- /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', + ] + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd-interface.cc --- /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 + */ + +#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 routerPrefix) +{ + m_prefixes.push_back (routerPrefix); +} + + +uint32_t RadvdInterface::GetInterface () const +{ + return m_interface; +} + +std::list > 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd-interface.h --- /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 + */ + +#ifndef RADVD_INTERFACE_H +#define RADVD_INTERFACE_H + +#include + +#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 > GetPrefixes () const; + + /** + * \brief Add a prefix to advertise on interface. + * \param routerPrefix prefix to advertise + */ + void AddPrefix (Ptr 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 > RadvdPrefixList; + typedef std::list >::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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd-prefix.cc --- /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 + */ + +#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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd-prefix.h --- /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 + */ + +#ifndef RADVD_PREFIX_H +#define RADVD_PREFIX_H + +#include + +#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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd.cc --- /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 + * Mehdi Benamor + */ + +#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 () + .AddConstructor () + ; + 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 > ()); + } + + for (EventIdMapI it = m_eventIds.begin () ; it != m_eventIds.end () ; ++it) + { + Simulator::Cancel ((*it).second); + } + m_eventIds.clear (); +} + +void Radvd::AddConfiguration (Ptr routerInterface) +{ + m_configurations.push_back (routerInterface); +} + +void Radvd::ScheduleTransmit (Time dt, Ptr config, EventId& eventId) +{ + NS_LOG_FUNCTION (this << dt); + eventId = Simulator::Schedule (dt, &Radvd::Send, this, config, Ipv6Address::GetAllNodesMulticast ()); +} + +void Radvd::Send (Ptr 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 > prefixes = config->GetPrefixes (); + Ptr p = Create (); + Ptr ipv6 = GetNode ()->GetObject (); + + /* 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 >::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 (rnd.GetValue (config->GetMinRtrAdvInterval (), config->GetMaxRtrAdvInterval ()) + 0.5); + Time t = MilliSeconds (delay); + ScheduleTransmit (t, config, m_eventIds[config->GetInterface ()]); +} + +void Radvd::HandleRead (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); + Ptr 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 (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 (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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/radvd.h --- /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 + * Mehdi Benamor + */ + +#ifndef RADVD_H +#define RADVD_H + +#include + +#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 routerInterface); + + protected: + /** + * \brief Dispose the instance. + */ + virtual void DoDispose (); + + private: + typedef std::list > RadvdInterfaceList; + typedef std::list >::iterator RadvdInterfaceListI; + typedef std::list >::const_iterator RadvdInterfaceListCI; + + typedef std::map EventIdMap; + typedef std::map::iterator EventIdMapI; + typedef std::map::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 config, EventId& eventId); + + /** + * \brief Send a packet. + * \param config interface configuration + * \param dst destination address (default ff02::1) + */ + void Send (Ptr config, Ipv6Address dst = Ipv6Address::GetAllNodesMulticast ()); + + /** + * \brief Handle received packet, especially router solicitation + * \param socket socket to read data from + */ + void HandleRead (Ptr socket); + + /** + * \brief Raw socket to send RA. + */ + Ptr m_socket; + + /** + * \brief List of configuration for interface. + */ + RadvdInterfaceList m_configurations; + + /** + * \brief Event ID map. + */ + EventIdMap m_eventIds; +}; + +} /* namespace ns3 */ + +#endif /* RADVD_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/applications/radvd/wscript --- /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', + ] + diff -r 08d3bef3b477 -r 9d48acef10b3 src/common/sgi-hashmap.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 +namespace sgi { using ::hash_map; }; // inherit globals + #else + #if __GNUC__ < 4 + #include + #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 +namespace sgi = ::__gnu_cxx; + #else +#undef __DEPRECATED + #include +namespace sgi = ::__gnu_cxx; + #endif + #endif + #endif +#else // ... there are other compilers, right? +namespace sgi = std; +#endif + + +#endif /* SGI_HASHMAP_H */ diff -r 08d3bef3b477 -r 9d48acef10b3 src/common/wscript --- 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', ] diff -r 08d3bef3b477 -r 9d48acef10b3 src/core/random-variable.cc --- 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() { diff -r 08d3bef3b477 -r 9d48acef10b3 src/devices/wifi/wifi-mac-header.cc --- 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: diff -r 08d3bef3b477 -r 9d48acef10b3 src/devices/wifi/wifi-remote-station-manager.cc --- 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 (); } diff -r 08d3bef3b477 -r 9d48acef10b3 src/devices/wifi/wifi-remote-station-manager.h --- 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 > Stations; + typedef std::vector 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 m_macTxRtsFailed; + + /** + * The trace source fired when the transmission of a data packet has failed + * + * \see class CallBackTraceSource + */ + TracedCallback m_macTxDataFailed; + + /** + * The trace source fired when the transmission of a RTS has + * exceeded the maximum number of attempts + * + * \see class CallBackTraceSource + */ + TracedCallback m_macTxFinalRtsFailed; + + /** + * The trace source fired when the transmission of a data packet has + * exceeded the maximum number of attempts + * + * \see class CallBackTraceSource + */ + TracedCallback 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 GetManager (void) const = 0; virtual WifiMode DoGetDataMode (uint32_t size) = 0; @@ -294,6 +363,7 @@ TracedValue m_slrc; double m_avgSlrcCoefficient; double m_avgSlrc; + Mac48Address m_address; }; } // namespace ns3 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/athstats-helper.cc --- /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 + */ + +#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 +#include +#include + + +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 athstats = CreateObject (); + 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 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 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 = *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 () + .AddConstructor () + .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 p) +{ + NS_LOG_FUNCTION (this << context < p) +{ + NS_LOG_FUNCTION (this << context < packet, double snr, WifiMode mode, enum WifiPreamble preamble) +{ + NS_LOG_FUNCTION (this << context <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 + + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/athstats-helper.h --- /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 + */ + +#ifndef ATHSTATS_HELPER_H +#define ATHSTATS_HELPER_H + +#include +#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 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 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 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 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 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 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 */ diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/internet-stack-helper.cc --- 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 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::max(); + uint32_t illegal = std::numeric_limits::max (); for (std::vector::iterator i = m_traces.begin (); i != m_traces.end (); i++) @@ -244,7 +273,7 @@ InternetStackHelper::CreateAndAggregateObjectFromTypeId (Ptr node, const std::string typeId) { ObjectFactory factory; - factory.SetTypeId(typeId); + factory.SetTypeId (typeId); Ptr protocol = factory.Create (); node->AggregateObject (protocol); } @@ -252,24 +281,45 @@ void InternetStackHelper::Install (Ptr node) const { - if (node->GetObject () != 0) + if (m_ipv4Enabled) { - NS_FATAL_ERROR ("InternetStackHelper::Install(): Aggregating " - "an InternetStack to a node with an existing Ipv4 object"); - return; + if (node->GetObject () != 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 ()); + Ptr factory = CreateObject (); + node->AggregateObject (factory); + // Set routing + Ptr ipv4 = node->GetObject (); + Ptr 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 ()); - Ptr factory = CreateObject (); - node->AggregateObject (factory); - // Set routing - Ptr ipv4 = node->GetObject (); - Ptr ipv4Routing = m_routing->Create (node); - ipv4->SetRoutingProtocol (ipv4Routing); + if (m_ipv6Enabled) + { + /* IPv6 stack */ + if (node->GetObject () != 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 = node->GetObject (); + Ptr 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/internet-stack-helper.h --- 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, const std::string typeId); static void Cleanup (void); static void LogRxIp (std::string context, Ptr packet, uint32_t deviceId); @@ -173,6 +201,16 @@ static uint32_t GetNodeIndex (std::string context); static std::vector 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-address-helper.cc --- /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 + */ + +#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 device = c.Get (i); + + Ptr node = device->GetNode (); + NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node"); + + Ptr ipv6 = node->GetObject (); + 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 withConfiguration) +{ + NS_LOG_FUNCTION_NOARGS (); + Ipv6InterfaceContainer retval; + for (uint32_t i = 0; i < c.GetN (); ++i) + { + Ptr device = c.Get (i); + + Ptr node = device->GetNode (); + NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node"); + + Ptr ipv6 = node->GetObject (); + 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 device = c.Get (i); + + Ptr node = device->GetNode (); + NS_ASSERT_MSG (node, "Ipv6AddressHelper::Allocate (): Bad node"); + + Ptr ipv6 = node->GetObject (); + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-address-helper.h --- /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 + */ + +#ifndef IPV6_ADDRESS_STATIC_HELPER_H +#define IPV6_ADDRESS_STATIC_HELPER_H + +#include + +#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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-interface-container.cc --- /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 + */ + +#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 = m_interfaces[i].first; + uint32_t interface = m_interfaces[i].second; + return ipv6->GetAddress (interface, j).GetAddress (); +} + +void Ipv6InterfaceContainer::Add (Ptr ipv6, uint32_t interface) +{ + m_interfaces.push_back (std::make_pair (ipv6, interface)); +} + +void Ipv6InterfaceContainer::Add (std::string ipv6Name, uint32_t interface) +{ + Ptr ipv6 = Names::Find (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 = 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 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 = m_interfaces[i].first; + Ptr ipv6Router = m_interfaces[router].first; + Ipv6Address routerAddress = ipv6Router->GetAddress (m_interfaces[router].second, 1).GetAddress (); + Ptr routing = 0; + Ipv6StaticRoutingHelper routingHelper; + + routing = routingHelper.GetStaticRouting (ipv6); + routing->SetDefaultRoute (routerAddress, m_interfaces[i].second); +} + +} /* namespace ns3 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-interface-container.h --- /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 + */ + +#ifndef IPV6_INTERFACE_CONTAINER_H +#define IPV6_INTERFACE_CONTAINER_H + +#include +#include +#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, 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, uint32_t> > InterfaceVector; + + /** + * \brief List of IPv6 stack and interfaces index. + */ + InterfaceVector m_interfaces; +}; + +} /* namespace ns3 */ + +#endif /* IPV6_INTERFACE_CONTAINER_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-list-routing-helper.cc --- /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 + */ +#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 +Ipv6ListRoutingHelper::Create (Ptr node) const +{ + Ptr list = CreateObject (); + for (std::list >::const_iterator i = m_list.begin (); + i != m_list.end (); ++i) + { + Ptr prot = i->first->Create (node); + list->AddRoutingProtocol (prot,i->second); + } + return list; +} + +} // namespace ns3 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-list-routing-helper.h --- /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 + */ +#ifndef IPV6_LIST_ROUTING_HELPER_H +#define IPV6_LIST_ROUTING_HELPER_H + +#include "ipv6-routing-helper.h" +#include +#include + +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 Create (Ptr node) const; +private: + std::list > m_list; +}; + +} // namespace ns3 + +#endif /* IPV6_LIST_ROUTING_HELPER_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-routing-helper.cc --- /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 + */ + +#include "ipv6-routing-helper.h" + +namespace ns3 { + +Ipv6RoutingHelper::~Ipv6RoutingHelper () +{} + +} // namespace ns3 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-routing-helper.h --- /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 + */ +#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 Create (Ptr node) const = 0; +}; + +} // namespace ns3 + + +#endif /* IPV6_ROUTING_HELPER_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-static-routing-helper.cc --- /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 +#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 +Ipv6StaticRoutingHelper::Create (Ptr node) const +{ + return CreateObject (); +} + +Ptr +Ipv6StaticRoutingHelper::GetStaticRouting (Ptr ipv6) const +{ + NS_LOG_FUNCTION (this); + Ptr ipv6rp = ipv6->GetRoutingProtocol (); + NS_ASSERT_MSG (ipv6rp, "No routing protocol associated with Ipv6"); + if (DynamicCast (ipv6rp)) + { + NS_LOG_LOGIC ("Static routing found as the main IPv4 routing protocol."); + return DynamicCast (ipv6rp); + } + if (DynamicCast (ipv6rp)) + { + Ptr lrp = DynamicCast (ipv6rp); + int16_t priority; + for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) + { + NS_LOG_LOGIC ("Searching for static routing in list"); + Ptr temp = lrp->GetRoutingProtocol (i, priority); + if (DynamicCast (temp)) + { + NS_LOG_LOGIC ("Found static routing in list"); + return DynamicCast (temp); + } + } + } + NS_LOG_LOGIC ("Static routing not found"); + return 0; +} + +void +Ipv6StaticRoutingHelper::AddMulticastRoute ( + Ptr n, + Ipv6Address source, + Ipv6Address group, + Ptr input, + NetDeviceContainer output) +{ + Ptr ipv6 = n->GetObject (); + + // We need to convert the NetDeviceContainer to an array of interface + // numbers + std::vector outputInterfaces; + for (NetDeviceContainer::Iterator i = output.Begin (); i != output.End (); ++i) + { + Ptr 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 = 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 n, + Ipv6Address source, + Ipv6Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + AddMulticastRoute (n, source, group, input, output); +} + +void +Ipv6StaticRoutingHelper::AddMulticastRoute ( + std::string nName, + Ipv6Address source, + Ipv6Address group, + Ptr input, + NetDeviceContainer output) +{ + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + +void +Ipv6StaticRoutingHelper::AddMulticastRoute ( + std::string nName, + Ipv6Address source, + Ipv6Address group, + std::string inputName, + NetDeviceContainer output) +{ + Ptr input = Names::Find (inputName); + Ptr n = Names::Find (nName); + AddMulticastRoute (n, source, group, input, output); +} + +#if 0 +void +Ipv6StaticRoutingHelper::SetDefaultMulticastRoute ( + Ptr n, + Ptr nd) +{ + Ptr ipv6 = n->GetObject (); + int32_t interfaceSrc = ipv6->GetInterfaceForDevice (nd); + NS_ASSERT_MSG (interfaceSrc >= 0, + "Ipv6StaticRoutingHelper::SetDefaultMulticastRoute (): " + "Expected an interface associated with the device"); + Ipv6StaticRoutingHelper helper; + Ptr 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 n, + std::string ndName) +{ + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); +} + +void +Ipv6StaticRoutingHelper::SetDefaultMulticastRoute ( + std::string nName, + Ptr nd) +{ + Ptr n = Names::Find (nName); + SetDefaultMulticastRoute (n, nd); +} + +void +Ipv6StaticRoutingHelper::SetDefaultMulticastRoute ( + std::string nName, + std::string ndName) +{ + Ptr n = Names::Find (nName); + Ptr nd = Names::Find (ndName); + SetDefaultMulticastRoute (n, nd); +} +#endif + +}; // namespace ns3 diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ipv6-static-routing-helper.h --- /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 Create (Ptr node) const; + + Ptr GetStaticRouting (Ptr ipv6) const; + + void AddMulticastRoute (Ptr n, Ipv6Address source, Ipv6Address group, + Ptr input, NetDeviceContainer output); + void AddMulticastRoute (std::string n, Ipv6Address source, Ipv6Address group, + Ptr input, NetDeviceContainer output); + void AddMulticastRoute (Ptr 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 n, Ptr nd); + void SetDefaultMulticastRoute (Ptr n, std::string ndName); + void SetDefaultMulticastRoute (std::string nName, Ptr nd); + void SetDefaultMulticastRoute (std::string nName, std::string ndName); +#endif +}; + +} // namespace ns3 + +#endif /* IPV6_STATIC_ROUTING_HELPER_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ping6-helper.cc --- /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 + */ + +#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 = *i; + Ptr client = m_factory.Create (); + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/ping6-helper.h --- /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 + */ + +#ifndef PING6_HELPER_H +#define PING6_HELPER_H + +#include +#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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/helper/wscript --- 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') diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/arp-cache.h --- 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 { diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/arp-l3-protocol.h --- 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/icmpv6-header.cc --- /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 + * Mehdi Benamor + * David Gross + */ + +#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
() + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6DestinationUnreachable::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +Icmpv6DestinationUnreachable::Icmpv6DestinationUnreachable () + : m_packet (0) +{ + SetType (ICMPV6_ERROR_DESTINATION_UNREACHABLE); +} + +Icmpv6DestinationUnreachable::~Icmpv6DestinationUnreachable () +{ +} + +Ptr Icmpv6DestinationUnreachable::GetPacket () const +{ + return m_packet; +} + +void Icmpv6DestinationUnreachable::SetPacket (Ptr 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 (data, length); + + return GetSerializedSize (); +} + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6TooBig); + +TypeId Icmpv6TooBig::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6TooBig") + .SetParent () + .AddConstructor () + ; + 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 Icmpv6TooBig::GetPacket () const +{ + return m_packet; +} + +void Icmpv6TooBig::SetPacket (Ptr 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 (data, length); + + return GetSerializedSize (); +} + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6TimeExceeded); + +TypeId Icmpv6TimeExceeded::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6TimeExceeded") + .SetParent () + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6TimeExceeded::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +Icmpv6TimeExceeded::Icmpv6TimeExceeded () + : m_packet (0) +{ + SetType (ICMPV6_ERROR_TIME_EXCEEDED); +} + +Icmpv6TimeExceeded::~Icmpv6TimeExceeded () +{ +} + +Ptr Icmpv6TimeExceeded::GetPacket () const +{ + return m_packet; +} + +void Icmpv6TimeExceeded::SetPacket (Ptr 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 (data, length); + + return GetSerializedSize (); +} + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6ParameterError); + +TypeId Icmpv6ParameterError::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6ParameterError") + .SetParent () + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6ParameterError::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +Icmpv6ParameterError::Icmpv6ParameterError () + : m_packet (0), + m_ptr (0) +{ + SetType (ICMPV6_ERROR_PARAMETER_ERROR); +} + +Icmpv6ParameterError::~Icmpv6ParameterError () +{ +} + +Ptr Icmpv6ParameterError::GetPacket () const +{ + return m_packet; +} + +void Icmpv6ParameterError::SetPacket (Ptr 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 (data, length); + + return GetSerializedSize (); +} + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionHeader); + +TypeId Icmpv6OptionHeader::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6OptionHeader") + .SetParent
() + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + 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 () + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6OptionRedirected::GetInstanceTypeId () const +{ + return GetTypeId (); +} + +Icmpv6OptionRedirected::Icmpv6OptionRedirected () + : m_packet (0) +{ + SetType (Icmpv6Header::ICMPV6_OPT_REDIRECTED); +} + +Icmpv6OptionRedirected::~Icmpv6OptionRedirected () +{ + m_packet = 0; +} + +Ptr Icmpv6OptionRedirected::GetPacket () const +{ + return m_packet; +} + +void Icmpv6OptionRedirected::SetPacket (Ptr 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 (buff, len2); + + return GetSerializedSize (); +} + +} /* namespace ns3 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/icmpv6-header.h --- /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 + * Mehdi Benamor + * David Gross + */ + +#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 GetPacket () const; + + /** + * \brief Set the incorrect packet. + * \param p the incorrect packet + */ + void SetPacket (Ptr 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 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 GetPacket () const; + + /** + * \brief Set the incorrect packet. + * \param p the incorrect packet + */ + void SetPacket (Ptr 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 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 GetPacket () const; + + /** + * \brief Set the incorrect packet. + * \param p the incorrect packet + */ + void SetPacket (Ptr 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 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 GetPacket () const; + + /** + * \brief Set the incorrect packet. + * \param p the incorrect packet + */ + void SetPacket (Ptr 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 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 GetPacket () const; + + /** + * \brief Set the redirected packet. + * \param packet the redirected packet + */ + void SetPacket (Ptr 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 m_packet; +}; + +} /* namespace ns3 */ + +#endif /* ICMPV6_HEADER_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/icmpv6-l4-protocol.cc --- /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 + * David Gross + * Mehdi Benamor + */ + +#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 () + .AddConstructor () + ; + 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 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 = this->GetObject (); + if (node != 0) + { + Ptr ipv6 = this->GetObject (); + if (ipv6 != 0) + { + this->SetNode (node); + ipv6->Insert (this); + Ptr rawFactory = CreateObject (); + ipv6->AggregateObject (rawFactory); + } + } + } + Object::NotifyNewAggregate (); +} + +void Icmpv6L4Protocol::SetNode (Ptr 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 interface) +{ + NS_LOG_FUNCTION (this << target << interface); + Ipv6Address addr; + + Ptr ipv6 = m_node->GetObject (); + NS_ASSERT (ipv6); + + /* TODO : disable multicast loopback to prevent NS probing to be received by the sender */ + + Ptr 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, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + Ptr p = packet->Copy (); + Ptr ipv6 = m_node->GetObject (); + + 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, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + Ptr p = packet->Copy (); + Icmpv6RA raHeader; + Ptr ipv6 = m_node->GetObject (); + 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 interface) +{ + NS_LOG_FUNCTION (this << lla << src << dst << interface); + Address hardwareAddress; + NdiscCache::Entry* entry = NULL; + Ptr 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 > 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 >::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 >::const_iterator it = waiting.begin (); it != waiting.end (); it++) + { + cache->GetInterface ()->Send (*it, src); + } + } + entry->StopReachableTimer (); + entry->StartReachableTimer (); + } + } + } + } +} + +void Icmpv6L4Protocol::HandleRS (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + Ptr ipv6 = m_node->GetObject (); + Icmpv6RS rsHeader; + packet->RemoveHeader (rsHeader); + Address hardwareAddress; + Icmpv6OptionLinkLayerAddress lla (1); + NdiscCache::Entry* entry = NULL; + Ptr 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, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 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 ipv6 = m_node->GetObject (); + + if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (interface->GetDevice ()))) + { + flags += 4; /* R flag */ + } + + hardwareAddress = interface->GetDevice ()->GetAddress (); + Ptr 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 Icmpv6L4Protocol::ForgeRS (Ipv6Address src, Ipv6Address dst, Address hardwareAddress) +{ + NS_LOG_FUNCTION (this << src << dst << hardwareAddress); + Ptr p = Create (); + 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 Icmpv6L4Protocol::ForgeEchoRequest (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr data) +{ + NS_LOG_FUNCTION (this << src << dst << id << seq << data); + Ptr p = data->Copy (); + Ipv6Header ipHeader; + Icmpv6Echo req (1); + + req.SetId (id); + req.SetSeq (seq); + + p->AddHeader (req); + + return p; +} + +void Icmpv6L4Protocol::HandleNA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 cache = FindCache (interface->GetDevice ()); + std::list > 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 >::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 >::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, Ipv6Address const &src, Ipv6Address const &dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + bool hasLla = false; + Ptr 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 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 = m_node->GetObject (); + + 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, Ipv6Address src, Ipv6Address dst, uint8_t ttl) +{ + NS_LOG_FUNCTION (this << packet << src << dst << (uint32_t)ttl); + Ptr ipv6 = m_node->GetObject (); + 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, Ipv6Address dst, Icmpv6Header& icmpv6Hdr, uint8_t ttl) +{ + NS_LOG_FUNCTION (this << packet << dst << icmpv6Hdr << (uint32_t)ttl); + Ptr ipv6 = m_node->GetObject (); + NS_ASSERT (ipv6 != 0 && ipv6->GetRoutingProtocol () != 0); + Ipv6Header header; + SocketIpTtlTag tag; + Socket::SocketErrno err; + Ptr 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 p = Create (); + 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 data) +{ + NS_LOG_FUNCTION (this << src << dst << id << seq << data); + Ptr 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 p = Create (); + /* 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 p = Create (); + 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 malformedPacket, Ipv6Address dst, uint8_t code) +{ + NS_LOG_FUNCTION (this << malformedPacket << dst << (uint32_t)code); + Ptr p = Create (); + 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 fragment = malformedPacket->CreateFragment (0, 1280 - 48); + header.SetPacket (fragment); + } + + header.SetCode (code); + SendMessage (p, dst, header, 255); +} + +void Icmpv6L4Protocol::SendErrorTooBig (Ptr malformedPacket, Ipv6Address dst, uint32_t mtu) +{ + NS_LOG_FUNCTION (this << malformedPacket << dst << mtu); + Ptr p = Create (); + 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 fragment = malformedPacket->CreateFragment (0, 1280 - 48); + header.SetPacket (fragment); + } + + header.SetCode (0); + header.SetMtu (mtu); + SendMessage (p, dst, header, 255); +} + +void Icmpv6L4Protocol::SendErrorTimeExceeded (Ptr malformedPacket, Ipv6Address dst, uint8_t code) +{ + NS_LOG_FUNCTION (this<< malformedPacket << dst << code); + Ptr p = Create (); + 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 fragment = malformedPacket->CreateFragment (0, 1280 - 48); + header.SetPacket (fragment); + } + + header.SetCode (code); + SendMessage (p, dst, header, 255); +} + +void Icmpv6L4Protocol::SendErrorParameterError (Ptr malformedPacket, Ipv6Address dst, uint8_t code, uint32_t ptr) +{ + NS_LOG_FUNCTION (this << malformedPacket << dst << code << ptr); + Ptr p = Create (); + 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 fragment = malformedPacket->CreateFragment (0, 1280 - 48); + header.SetPacket (fragment); + } + + header.SetCode (code); + header.SetPtr (ptr); + SendMessage (p, dst, header, 255); +} + +void Icmpv6L4Protocol::SendRedirection (Ptr redirectedPacket, Ipv6Address dst, Ipv6Address redirTarget, Ipv6Address redirDestination, Address redirHardwareTarget) +{ + NS_LOG_FUNCTION (this << redirectedPacket << dst << redirTarget << redirDestination << redirHardwareTarget); + uint32_t llaSize = 0; + Ptr p = Create (); + 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 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 Icmpv6L4Protocol::ForgeNA (Ipv6Address src, Ipv6Address dst, Address* hardwareAddress, uint8_t flags) +{ + NS_LOG_FUNCTION (this << src << dst << hardwareAddress << (uint32_t)flags); + Ptr p = Create (); + 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 Icmpv6L4Protocol::ForgeNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress) +{ + NS_LOG_FUNCTION (this << src << dst << target << hardwareAddress); + Ptr p = Create (); + 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 Icmpv6L4Protocol::FindCache (Ptr 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 Icmpv6L4Protocol::CreateCache (Ptr device, Ptr interface) +{ + Ptr ipv6 = m_node->GetObject (); + Ptr cache = CreateObject (); + 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 p, Ipv6Address dst, Ptr device, Ptr 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 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 = icmpv6->m_node->GetObject (); + + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/icmpv6-l4-protocol.h --- /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 + * David Gross + * Mehdi Benamor + */ + +#ifndef ICMPV6_L4_PROTOCOL_H +#define ICMPV6_L4_PROTOCOL_H + +#include +#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); + + /** + * \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, 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, 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 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 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 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 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 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 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 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 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 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 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 ForgeEchoRequest (Ipv6Address src, Ipv6Address dst, uint16_t id, uint16_t seq, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 interface); + + /** + * \brief Function called when DAD timeout. + * \param icmpv6 Icmpv6L4Protocol instance + * \param interface the interface + * \param addr the IPv6 address + */ + static void FunctionDadTimeout (Ptr 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 p, Ipv6Address dst, Ptr device, Ptr 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 CreateCache (Ptr device, Ptr interface); + + protected: + /** + * \brief Dispose this object. + */ + virtual void DoDispose (); + + private: + + typedef std::list > CacheList; + + /** + * \brief The node. + */ + Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 interface); + + /** + * \brief Get the cache corresponding to the device. + * \param device the device + */ + Ptr FindCache (Ptr device); +}; + +} /* namespace ns3 */ + +#endif /* ICMPV6_L4_PROTOCOL_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-autoconfigured-prefix.cc --- /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 + */ + +#include +#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, 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 ipv6 = m_node->GetObject (); + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-autoconfigured-prefix.h --- /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 + */ + +#ifndef IPV6_AUTOCONFIGURED_PREFIX_H +#define IPV6_AUTOCONFIGURED_PREFIX_H + +#include +#include +#include + +#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, 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-end-point-demux.cc --- /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 + */ + +#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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-end-point-demux.h --- /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 + */ + +#ifndef IPV6_END_POINT_DEMUX_H +#define IPV6_END_POINT_DEMUX_H + +#include +#include +#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::listEndPoints; + typedef std::list::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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-end-point.cc --- /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 + */ + +#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, Ipv6Address, uint16_t> callback) +{ + m_rxCallback = callback; +} + +void Ipv6EndPoint::SetIcmpCallback (Callback callback) +{ + m_icmpCallback = callback; +} + +void Ipv6EndPoint::SetDestroyCallback (Callback callback) +{ + m_destroyCallback = callback; +} + +void Ipv6EndPoint::ForwardUp (Ptr 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-end-point.h --- /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 + */ + +#ifndef IPV6_END_POINT_H +#define IPV6_END_POINT_H + +#include +#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, Ipv6Address, uint16_t> callback); + + /** + * \brief Set the ICMP callback. + * \param callback callback function + */ + void SetIcmpCallback (Callback callback); + + /** + * \brief Set the default destroy callback. + * \param callback callback function + */ + void SetDestroyCallback (Callback callback); + + /** + * \brief Forward the packet to the upper level. + * \param p the packet + * \param addr source address + * \param port source port + */ + void ForwardUp (Ptr 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 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, Ipv6Address, uint16_t> m_rxCallback; + + /** + * \brief The ICMPv6 callback. + */ + Callback m_icmpCallback; + + /** + * \brief The destroy callback. + */ + Callback m_destroyCallback; +}; + +} /* namespace ns3 */ + +#endif /* IPV6_END_POINT_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-interface.cc --- /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 + */ + +#include "ipv6-interface.h" +#include "ns3/net-device.h" +#include "loopback-net-device.h" +#include "ns3/log.h" +#include "ns3/node.h" +#include + +#include "icmpv6-l4-protocol.h" + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE ("Ipv6Interface"); + +TypeId Ipv6Interface::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Ipv6Interface") + .SetParent () + ; + 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 (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 icmpv6 = m_node->GetObject ()->GetIcmpv6 (); + m_ndCache = icmpv6->CreateCache (m_device, this); +} + +void Ipv6Interface::SetNode (Ptr node) +{ + NS_LOG_FUNCTION (this << node); + m_node = node; + DoSetup (); +} + +void Ipv6Interface::SetDevice (Ptr device) +{ + NS_LOG_FUNCTION (this << device); + m_device = device; + DoSetup (); +} + +Ptr 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 icmpv6 = m_node->GetObject ()->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 p, Ipv6Address dest) +{ + NS_LOG_FUNCTION (this << p << dest); + Ptr ipv6 = m_node->GetObject (); + + if (!IsUp ()) + { + return; + } + + /* check if destination is localhost (::1) */ + if (DynamicCast (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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-interface.h --- /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 + */ + +#ifndef IPV6_INTERFACE_H +#define IPV6_INTERFACE_H + +#include + +#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); + + /** + * \brief Set the NetDevice. + * \param device NetDevice + */ + void SetDevice (Ptr device); + + /** + * \brief Get the NetDevice. + * \return the NetDevice associated with this interface + */ + virtual Ptr 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 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 Ipv6InterfaceAddressList; + typedef std::list::iterator Ipv6InterfaceAddressListI; + typedef std::list::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 m_node; + + /** + * \brief NetDevice associated with this interface. + */ + Ptr m_device; + + /** + * \brief Neighbor cache. + */ + Ptr 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-l3-protocol.cc --- /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 + */ + +#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 () + .AddConstructor () + .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.", + UintegerValue (64), + MakeUintegerAccessor (&Ipv6L3Protocol::m_defaultTtl), + MakeUintegerChecker ()) + .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 ()) + ; + 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 routingProtocol) +{ + NS_LOG_FUNCTION (this << routingProtocol); + m_routingProtocol = routingProtocol; + m_routingProtocol->SetIpv6 (this); +} + +Ptr Ipv6L3Protocol::GetRoutingProtocol () const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_routingProtocol; +} + +uint32_t Ipv6L3Protocol::AddInterface (Ptr device) +{ + NS_LOG_FUNCTION (this << device); + Ptr node = GetObject (); + Ptr interface = CreateObject (); + + 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 interface) +{ + NS_LOG_FUNCTION (this << interface); + uint32_t index = m_nInterfaces; + + m_interfaces.push_back (interface); + m_nInterfaces++; + return index; +} + +Ptr 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 Ipv6L3Protocol::GetNetDevice (uint32_t i) +{ + NS_LOG_FUNCTION (this << i); + return GetInterface (i)->GetDevice (); +} + +int32_t Ipv6L3Protocol::GetInterfaceForDevice (Ptr 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 aPrefix = CreateObject (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 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 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 interface = GetInterface (i); + return interface->GetNAddresses (); +} + +Ipv6InterfaceAddress Ipv6L3Protocol::GetAddress (uint32_t i, uint32_t addressIndex) const +{ + NS_LOG_FUNCTION (this << i << addressIndex); + Ptr interface = GetInterface (i); + return interface->GetAddress (addressIndex); +} + +bool Ipv6L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex) +{ + NS_LOG_FUNCTION (this << i << addressIndex); + Ptr 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 interface = GetInterface (i); + interface->SetMetric (metric); +} + +uint16_t Ipv6L3Protocol::GetMetric (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->GetMetric (); +} + +uint16_t Ipv6L3Protocol::GetMtu (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->GetDevice ()->GetMtu (); +} + +bool Ipv6L3Protocol::IsUp (uint32_t i) const +{ + NS_LOG_FUNCTION (this << i); + Ptr interface = GetInterface (i); + return interface->IsUp (); +} + +void Ipv6L3Protocol::SetUp (uint32_t i) +{ + NS_LOG_FUNCTION (this << i); + Ptr 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 interface = GetInterface (i); + + interface->SetDown (); + + if (m_routingProtocol != 0) + { + m_routingProtocol->NotifyInterfaceDown (i); + } +} + +void Ipv6L3Protocol::SetupLoopback () +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr interface = CreateObject (); + Ptr 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 (m_node->GetDevice (i))) + { + break; + } + } + + if (device == 0) + { + device = CreateObject (); + 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 = GetObject (); + 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 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 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 = this->GetObject (); + // 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) +{ + NS_LOG_FUNCTION (this << node); + m_node = node; + /* add LoopbackNetDevice if needed, and an Ipv6Interface on top of it */ + SetupLoopback (); +} + +void Ipv6L3Protocol::Insert (Ptr protocol) +{ + NS_LOG_FUNCTION (this << protocol); + m_protocols.push_back (protocol); +} + +void Ipv6L3Protocol::Remove (Ptr protocol) +{ + NS_LOG_FUNCTION (this << protocol); + m_protocols.remove (protocol); +} + +Ptr 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 Ipv6L3Protocol::CreateRawSocket () +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr sock = CreateObject (); + sock->SetNode (m_node); + m_sockets.push_back (sock); + return sock; +} + +void Ipv6L3Protocol::DeleteRawSocket (Ptr 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 Ipv6L3Protocol::GetIcmpv6 () const +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr protocol = GetProtocol (Icmpv6L4Protocol::GetStaticProtocolNumber ()); + + if (protocol) + { + return protocol->GetObject (); + } + else + { + return 0; + } +} + +void Ipv6L3Protocol::SetDefaultTtl (uint8_t ttl) +{ + NS_LOG_FUNCTION (this << ttl); + m_defaultTtl = ttl; +} + +void Ipv6L3Protocol::Send (Ptr packet, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr 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 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 device, Ptr 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 = p->Copy (); + Ptr 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 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 route, Ptr 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 dev = route->GetOutputDevice (); + int32_t interface = GetInterfaceForDevice (dev); + NS_ASSERT (interface >= 0); + + Ptr 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 rtentry, Ptr 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 = 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 icmpv6 = GetIcmpv6 (); + Address hardwareTarget; + Ipv6Address dst = header.GetDestinationAddress (); + Ipv6Address src = header.GetSourceAddress (); + Ipv6Address target = rtentry->GetGateway (); + Ptr 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 mrtentry, Ptr 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 = 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 rtentry = Create (); + 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 packet, Ipv6Header const& ip, uint32_t iif) +{ + NS_LOG_FUNCTION (this << packet << ip << iif); + Ptr p = packet->Copy (); + Ptr protocol = GetProtocol (ip.GetNextHeader ()); + + if (protocol) + { + Ptr 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-l3-protocol.h --- /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 + */ + +#ifndef IPV6_L3_PROTOCOL_H +#define IPV6_L3_PROTOCOL_H + +#include + +#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); + + /** + * \brief Add an L4 protocol. + * \param protocol L4 protocol + */ + void Insert (Ptr protocol); + + /** + * \brief Remove an L4 protocol. + * \param protocol L4 protocol to remove + */ + void Remove (Ptr protocol); + + /** + * \brief Get L4 protocol by protocol number. + * \param protocolNumber protocol number + * \return corresponding Ipv6L4Protocol or 0 if not found + */ + Ptr GetProtocol (int protocolNumber) const; + + /** + * \brief Create raw IPv6 socket. + * \return newly raw socket + */ + Ptr CreateRawSocket (); + + /** + * \brief Remove raw IPv6 socket. + * \param socket socket to remove + */ + void DeleteRawSocket (Ptr 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 device, Ptr 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, Ipv6Address source, Ipv6Address destination, uint8_t protocol, Ptr route); + + /** + * \brief Set routing protocol for this stack. + * \param routingProtocol IPv6 routing protocol to set + */ + void SetRoutingProtocol (Ptr routingProtocol); + + /** + * \brief Get current routing protocol used. + * \return routing protocol + */ + Ptr GetRoutingProtocol () const; + + /** + * \brief Add IPv6 interface for a device. + * \param device net device + * \return interface index + */ + uint32_t AddInterface (Ptr device); + + /** + * \brief Get an interface. + * \param i interface index + * \return IPv6 interface pointer + */ + Ptr 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 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 GetNetDevice (uint32_t i); + + /** + * \brief Get ICMPv6 protocol. + * \return Icmpv6L4Protocol pointer + */ + Ptr 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 > Ipv6InterfaceList; + typedef std::list > SocketList; + typedef std::list > L4List_t; + + typedef std::list< Ptr > Ipv6AutoconfiguredPrefixList; + typedef std::list< Ptr >::iterator Ipv6AutoconfiguredPrefixListI; + + /** + * \brief Callback to trace TX (transmission) packets. + */ + TracedCallback, uint32_t> m_txTrace; + + /** + * \brief Callback to trace RX (reception) packets. + */ + TracedCallback, uint32_t> m_rxTrace; + + /** + * \brief Callback to trace drop packets. + */ + TracedCallback > 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 route, Ptr 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 rtentry, Ptr 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 mrtentry, Ptr 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 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 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 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 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-l4-protocol.cc --- /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 + */ + +#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 () + .AddAttribute ("ProtocolNumber", "The IPv6 protocol number.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv6L4Protocol::GetProtocolNumber), + MakeUintegerChecker ()) + ; + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-l4-protocol.h --- /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 + */ + +#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 p, Ipv6Address const &src, Ipv6Address const &dst, Ptr 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-raw-socket-factory-impl.cc --- /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 Ipv6RawSocketFactoryImpl::CreateSocket () +{ + Ptr ipv6 = GetObject (); + Ptr socket = ipv6->CreateRawSocket (); + return socket; +} + +} /* namespace ns3 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-raw-socket-factory-impl.h --- /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 CreateSocket (); +}; + +} /* namespace ns3 */ + +#endif /* IPV6_RAW_SOCKET_FACTORY_IMPL_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-raw-socket-impl.cc --- /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 + */ + +#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 () + .AddAttribute ("Protocol", "Protocol number to match.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv6RawSocketImpl::m_protocol), + MakeUintegerChecker ()) + .AddAttribute ("IcmpFilter", "Any ICMPv6 header whose type field matches a bit in this filter is dropped.", + UintegerValue (0), + MakeUintegerAccessor (&Ipv6RawSocketImpl::m_icmpFilter), + MakeUintegerChecker ()) + ; + 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) +{ + NS_LOG_FUNCTION (this << node); + m_node = node; +} + +Ptr 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 ipv6 = m_node->GetObject (); + + 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 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 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 ipv6 = m_node->GetObject (); + Ipv6Address dst = ad.GetIpv6 (); + + if (ipv6->GetRoutingProtocol ()) + { + Ipv6Header hdr; + hdr.SetDestinationAddress (dst); + SocketErrno err = ERROR_NOTERROR; + Ptr 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 Ipv6RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags) +{ + NS_LOG_FUNCTION (this << maxSize << flags); + Address tmp; + return RecvFrom (maxSize, flags, tmp); +} + +Ptr 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 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::const_iterator it = m_data.begin () ; it != m_data.end () ; ++it) + { + rx+= (it->packet)->GetSize (); + } + + return rx; +} + +bool Ipv6RawSocketImpl::ForwardUp (Ptr p, Ipv6Header hdr, Ptr 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-raw-socket-impl.h --- /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 + */ + +#ifndef IPV6_RAW_SOCKET_IMPL_H +#define IPV6_RAW_SOCKET_IMPL_H + +#include + +#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); + + /** + * \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 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 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 p, uint32_t flags, const Address& toAddress); + + /** + * \brief Receive packet. + * \param maxSize maximum size + * \param flags additionnal flags + * \return packet received + */ + virtual Ptr 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 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 p, Ipv6Header hdr, Ptr device); + + private: + /** + * \struct Data + * \brief IPv6 raw data and additionnal information. + */ + struct Data + { + Ptr 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 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ipv6-test.cc --- /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 + */ + +#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 = CreateObject (); + Ptr ipv6 = CreateObject (); + Ptr icmpv6 = CreateObject (); + Ptr interface = CreateObject (); + Ptr interface2 = CreateObject (); + Ptr device = CreateObject (); + Ptr device2 = CreateObject (); + 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ndisc-cache.cc --- /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 + */ + +#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 () + .AddAttribute ("UnresolvedQueueSize", + "Size of the queue for packets pending an NA reply.", + UintegerValue (DEFAULT_UNRES_QLEN), + MakeUintegerAccessor (&NdiscCache::m_unresQlen), + MakeUintegerChecker ()) + ; + 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 device, Ptr interface) +{ + NS_LOG_FUNCTION (this << device << interface); + m_device = device; + m_interface = interface; +} + +Ptr NdiscCache::GetInterface () const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_interface; +} + +Ptr 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 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 icmpv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject ()->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 malformedPacket = m_waiting.front (); + if (malformedPacket == 0) + { + malformedPacket = Create (); + } + + icmpv6->SendErrorDestinationUnreachable (malformedPacket, addr, Icmpv6Header::ICMPV6_ADDR_UNREACHABLE); + + /* delete the entry */ + m_ndCache->Remove (this); + } +} + +void NdiscCache::Entry::FunctionDelayTimeout () +{ + NS_LOG_FUNCTION_NOARGS (); + Ptr ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject (); + Ptr 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 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 ipv6 = m_ndCache->GetDevice ()->GetNode ()->GetObject (); + Ptr 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 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 p) +{ + NS_LOG_FUNCTION (this << p); + m_state = INCOMPLETE; + + if (p) + { + m_waiting.push_back (p); + } +} + +std::list > 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 > 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/ndisc-cache.h --- /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 + */ + +#ifndef NDISC_CACHE_H +#define NDISC_CACHE_H + +#include + +#include + +#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 GetDevice () const; + + /** + * \brief Get the Ipv6Interface associated with this cache. + */ + Ptr 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 device, Ptr 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 p); + + /** + * \brief Changes the state to this entry to REACHABLE. + * \param mac MAC address + * \return the list of packet waiting + */ + std::list > 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 > 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 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 > 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 Cache; + typedef sgi::hash_map::iterator CacheI; + + /** + * \brief Dispose this object. + */ + void DoDispose (); + + /** + * \brief The NetDevice. + */ + Ptr m_device; + + /** + * \brief the interface. + */ + Ptr 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/nsc-tcp-l4-protocol.cc --- 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 prot); +private: + virtual void send_callback(const void *data, int datalen); + virtual void wakeup(); + virtual void gettime(unsigned int *, unsigned int *); +private: + Ptr m_prot; +}; + +NscInterfaceImpl::NscInterfaceImpl (Ptr 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 () .AddConstructor() - .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 rtt = m_rttFactory.Create (); Ptr socket = CreateObject (); socket->SetNode (m_node); socket->SetTcp (this); - socket->SetRtt (rtt); m_sockets.push_back (socket); return socket; } diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/nsc-tcp-l4-protocol.h --- 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 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 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; diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/nsc-tcp-socket-impl.cc --- 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 rtt) -{ - m_rtt = rtt; -} enum Socket::SocketErrno diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/nsc-tcp-socket-impl.h --- 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); void SetTcp (Ptr tcp); - void SetRtt (Ptr rtt); virtual enum SocketErrno GetErrno (void) const; virtual Ptr GetNode (void) const; @@ -158,7 +158,6 @@ uint32_t m_initialCWnd; //Initial cWnd value // Round trip time estimation - Ptr m_rtt; Time m_lastMeasuredRtt; // Timer-related members diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/sgi-hashmap.h --- 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 -namespace sgi { using ::hash_map; }; // inherit globals - #else - #if __GNUC__ < 4 - #include - #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 -namespace sgi = ::__gnu_cxx; - #else -#undef __DEPRECATED - #include -namespace sgi = ::__gnu_cxx; - #endif - #endif - #endif -#else // ... there are other compilers, right? -namespace sgi = std; -#endif - - -#endif /* SGI_HASHMAP_H */ diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/tcp-l4-protocol.cc --- 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 @@ -558,17 +559,18 @@ } void -TcpL4Protocol::SendPacket (Ptr packet, TcpHeader outgoingHeader, +TcpL4Protocol::SendPacket (Ptr 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 ()) diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/tcp-l4-protocol.h --- 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, TcpHeader, + void SendPacket (Ptr, const TcpHeader &, Ipv4Address, Ipv4Address); static ObjectFactory GetDefaultRttEstimatorFactory (void); diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/tcp-socket-impl.cc --- 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/tcp-test.cc --- 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/udp-l4-protocol.h --- 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 diff -r 08d3bef3b477 -r 9d48acef10b3 src/internet-stack/wscript --- 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' diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/inet6-socket-address.cc --- 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) { } diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv4-address.cc --- 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 */ +#include #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 (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) {} diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv4-address.h --- 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); diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-address.cc --- 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); diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-address.h --- 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 { public: - size_t operator() (Ipv6Address const &x) const; + size_t operator () (Ipv6Address const &x) const; }; bool operator == (Ipv6Prefix const &a, Ipv6Prefix const &b); diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-header.cc --- 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 */ diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-header.h --- 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, }; /** diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-interface-address.cc --- /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 + */ + +#include + +#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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-interface-address.h --- /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 + */ + +#ifndef IPV6_INTERFACE_ADDRESS_H +#define IPV6_INTERFACE_ADDRESS_H + +#include + +#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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-raw-socket-factory.cc --- /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 + */ + +#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 () + ; + return tid; +} + +} // namespace ns3 + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-raw-socket-factory.h --- /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 + */ + +#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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-route.cc --- /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 + */ + +#include + +#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 outputDevice) +{ + m_outputDevice = outputDevice; +} + +Ptr 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-route.h --- /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 + */ + +#ifndef IPV6_ROUTE_H +#define IPV6_ROUTE_H + +#include +#include +#include + +#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 outputDevice); + + /** + * \brief Get output device. + * \return output device + */ + Ptr 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 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 m_ttls; +}; + +std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoute const& route); + +} /* namespace ns3 */ + +#endif /* IPV6_ROUTE_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-routing-protocol.cc --- /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 () + ; + return tid; +} + +} /* namespace ns3 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6-routing-protocol.h --- /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, Ptr, const Ipv6Header &> UnicastForwardCallback; + typedef Callback, Ptr, const Ipv6Header &> MulticastForwardCallback; + typedef Callback, const Ipv6Header &, uint32_t > LocalDeliverCallback; + typedef Callback, 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 RouteOutput (Ptr 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 p, const Ipv6Header &header, Ptr 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) = 0; +}; + +} //namespace ns3 + +#endif /* IPV6_ROUTING_PROTOCOL_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6.cc --- /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 + */ + +/* 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 () + .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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/ipv6.h --- /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 + */ + +/* taken from src/node/ipv4.h and adapted to IPv6 */ + +#ifndef IPV6_H +#define IPV6_H + +#include +#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 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 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 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 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/node/wscript --- 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', ] diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/list-routing/ipv6-list-routing.cc --- /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 () + .AddConstructor () + ; + 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 +Ipv6ListRouting::RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, enum Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header.GetDestinationAddress () << header.GetSourceAddress () << oif); + Ptr 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 p, const Ipv6Header &header, Ptr 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 ()->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 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) +{ + 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 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 +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 RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr) { return 0;} + bool RouteInput (Ptr p, const Ipv6Header &header, Ptr 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) {} +}; + +class Ipv6BRouting : public Ipv6RoutingProtocol { +public: + Ptr RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr) { return 0;} + bool RouteInput (Ptr p, const Ipv6Header &header, Ptr 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) {} +}; + +class Ipv6ListRoutingTest: public Test { +public: + virtual bool RunTests (void); + Ipv6ListRoutingTest (); +}; + +Ipv6ListRoutingTest::Ipv6ListRoutingTest () + : Test ("Ipv6ListRouting") {} + +bool +Ipv6ListRoutingTest::RunTests (void) +{ + bool result = true; + Ptr lr = CreateObject (); + Ptr aRouting = CreateObject (); + Ptr bRouting = CreateObject (); + // 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 firstRp = lr->GetRoutingProtocol (0, first); + NS_TEST_ASSERT_EQUAL (10, first); + NS_TEST_ASSERT_EQUAL (firstRp, aRouting); + Ptr secondRp = lr->GetRoutingProtocol (1, second); + NS_TEST_ASSERT_EQUAL (5, second); + NS_TEST_ASSERT_EQUAL (secondRp, bRouting); + + // Test negative values + lr = CreateObject (); + // 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 */ diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/list-routing/ipv6-list-routing.h --- /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 +#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 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 GetRoutingProtocol (uint32_t index, int16_t& priority) const; + + // Below are from Ipv6RoutingProtocol + virtual Ptr RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + + virtual bool RouteInput (Ptr p, const Ipv6Header &header, Ptr 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); + +protected: + void DoDispose (void); +private: + typedef std::pair > Ipv6RoutingProtocolEntry; + typedef std::list Ipv6RoutingProtocolList; + Ipv6RoutingProtocolList m_routingProtocols; + static bool Compare (const Ipv6RoutingProtocolEntry& a, const Ipv6RoutingProtocolEntry& b); + Ptr m_ipv6; + +}; + +} //namespace ns3 + +#endif /* IPV6_LIST_ROUTING_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/list-routing/wscript --- 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', ] diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/static-routing/ipv6-routing-table-entry.cc --- /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 + */ + +#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 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 Ipv6MulticastRoutingTableEntry::GetOutputInterfaces () const +{ + return m_outputInterfaces; +} + +Ipv6MulticastRoutingTableEntry Ipv6MulticastRoutingTableEntry::CreateMulticastRoute (Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/static-routing/ipv6-routing-table-entry.h --- /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 + */ + +#ifndef IPV6_ROUTING_TABLE_ENTRY_H +#define IPV6_ROUTING_TABLE_ENTRY_H + +#include +#include +#include + +#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 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 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 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 m_outputInterfaces; +}; + +std::ostream& operator<< (std::ostream& os, Ipv6MulticastRoutingTableEntry const& route); + +} /* namespace ns3 */ + +#endif /* IPV6_ROUTING_TABLE_ENTRY_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/static-routing/ipv6-static-routing.cc --- /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 + */ + +#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 () + .AddConstructor () + ; + 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) +{ + 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 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 Ipv6StaticRouting::LookupStatic (Ipv6Address dst, uint32_t interface) +{ + NS_LOG_FUNCTION (this << dst << interface); + Ptr 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 (); + 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 (); + 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(); + 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(); + 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 Ipv6StaticRouting::LookupStatic (Ipv6Address origin, Ipv6Address group, uint32_t interface) +{ + NS_LOG_FUNCTION (this << origin << group << interface); + Ptr 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(); + 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 Ipv6StaticRouting::RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header << oif); + Ipv6Address destination = header.GetDestinationAddress (); + Ptr 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 p, const Ipv6Header &ipHeader, Ptr 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 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 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 */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/static-routing/ipv6-static-routing.h --- /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 + */ + +#ifndef IPV6_STATIC_ROUTING_H +#define IPV6_STATIC_ROUTING_H + +#include +#include + +#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 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 RouteOutput (Ptr p, const Ipv6Header &header, uint32_t oif, Socket::SocketErrno &sockerr); + + virtual bool RouteInput (Ptr p, const Ipv6Header &header, Ptr 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); + + protected: + /** + * \brief Dispose this object. + */ + void DoDispose (); + + private: + typedef std::list HostRoutes; + typedef std::list::const_iterator HostRoutesCI; + typedef std::list::iterator HostRoutesI; + typedef std::list NetworkRoutes; + typedef std::list::const_iterator NetworkRoutesCI; + typedef std::list::iterator NetworkRoutesI; + + typedef std::list MulticastRoutes; + typedef std::list::const_iterator MulticastRoutesCI; + typedef std::list::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 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 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 m_ipv6; +}; + +} /* namespace ns3 */ + +#endif /* IPV6_STATIC_ROUTING_H */ + diff -r 08d3bef3b477 -r 9d48acef10b3 src/routing/static-routing/wscript --- 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', ] diff -r 08d3bef3b477 -r 9d48acef10b3 src/wscript --- 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):