diff --git a/src/internet/model/icmpv6-header.h b/src/internet/model/icmpv6-header.h index ff0025433..424c4528b 100644 --- a/src/internet/model/icmpv6-header.h +++ b/src/internet/model/icmpv6-header.h @@ -68,7 +68,9 @@ public: ICMPV6_MOBILITY_MOBILE_PREFIX_SOLICITATION, ICMPV6_SECURE_ND_CERTIFICATE_PATH_SOLICITATION, ICMPV6_SECURE_ND_CERTIFICATE_PATH_ADVERTISEMENT, - ICMPV6_EXPERIMENTAL_MOBILITY + ICMPV6_EXPERIMENTAL_MOBILITY, + ICMPV6_ND_DUPLICATE_ADDRESS_REQUEST = 157, + ICMPV6_ND_DUPLICATE_ADDRESS_CONFIRM }; /** @@ -80,7 +82,10 @@ public: ICMPV6_OPT_LINK_LAYER_TARGET, ICMPV6_OPT_PREFIX, ICMPV6_OPT_REDIRECTED, - ICMPV6_OPT_MTU + ICMPV6_OPT_MTU, + ICMPV6_OPT_ADDRESS_REGISTRATION = 33, + ICMPV6_OPT_SIXLOWPAN_CONTEXT, + ICMPV6_OPT_AUTHORITATIVE_BORDER_ROUTER }; /** diff --git a/src/internet/model/icmpv6-l4-protocol.cc b/src/internet/model/icmpv6-l4-protocol.cc index 5bac99d92..ba63345d7 100644 --- a/src/internet/model/icmpv6-l4-protocol.cc +++ b/src/internet/model/icmpv6-l4-protocol.cc @@ -161,6 +161,12 @@ void Icmpv6L4Protocol::SetNode (Ptr node) m_node = node; } +Ptr Icmpv6L4Protocol::GetNode () +{ + NS_LOG_FUNCTION (this); + return m_node; +} + uint16_t Icmpv6L4Protocol::GetStaticProtocolNumber () { NS_LOG_FUNCTION_NOARGS (); diff --git a/src/internet/model/icmpv6-l4-protocol.h b/src/internet/model/icmpv6-l4-protocol.h index ed853ae14..54b04187f 100644 --- a/src/internet/model/icmpv6-l4-protocol.h +++ b/src/internet/model/icmpv6-l4-protocol.h @@ -115,6 +115,12 @@ public: */ void SetNode (Ptr node); + /** + * \brief Get the node. + * \return node + */ + Ptr GetNode (); + /** * \brief This method is called by AddAgregate and completes the aggregation * by setting the node in the ICMPv6 stack and adding ICMPv6 factory to @@ -199,7 +205,7 @@ public: * \param target target IPv6 address * \param hardwareAddress our mac address */ - void SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress); + virtual void SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address hardwareAddress); /** * \brief Send an error Destination Unreachable. @@ -380,6 +386,31 @@ protected: */ virtual void DoDispose (); + /** + * \brief Get the cache corresponding to the device. + * \param device the device + * \returns the NdiscCache associated with the device + */ + Ptr FindCache (Ptr device); + + /** + * \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 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); + private: typedef std::list > CacheList; //!< container of NdiscCaches @@ -477,15 +508,6 @@ private: */ 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 @@ -531,22 +553,6 @@ private: */ void HandleParameterError (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 - * \returns the NdiscCache associated with the device - */ - Ptr FindCache (Ptr device); - // From IpL4Protocol virtual void SetDownTarget (IpL4Protocol::DownTargetCallback cb); virtual void SetDownTarget6 (IpL4Protocol::DownTargetCallback6 cb); diff --git a/src/internet/model/ndisc-cache.h b/src/internet/model/ndisc-cache.h index f7d4107c9..14bcfadb4 100644 --- a/src/internet/model/ndisc-cache.h +++ b/src/internet/model/ndisc-cache.h @@ -342,6 +342,12 @@ public: */ void SetIpv6Address (Ipv6Address ipv6Address); +protected: + /** + * \brief the NdiscCache associated. + */ + NdiscCache* m_ndCache; + private: /** * \brief The IPv6 address. @@ -366,11 +372,6 @@ private: */ NdiscCacheEntryState_e m_state; - /** - * \brief the NdiscCache associated. - */ - NdiscCache* m_ndCache; - /** * \brief The MAC address. */ @@ -402,6 +403,12 @@ private: uint8_t m_nsRetransmit; }; +protected: + /** + * \brief Dispose this object. + */ + void DoDispose (); + private: /** * \brief Neighbor Discovery Cache container @@ -427,11 +434,6 @@ private: */ NdiscCache& operator= (NdiscCache const &); - /** - * \brief Dispose this object. - */ - void DoDispose (); - /** * \brief The NetDevice. */ diff --git a/src/sixlowpan/model/sixlowpan-nd-header.cc b/src/sixlowpan/model/sixlowpan-nd-header.cc new file mode 100644 index 000000000..31d7b5109 --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-nd-header.cc @@ -0,0 +1,771 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#include "ns3/assert.h" +#include "ns3/address-utils.h" +#include "ns3/log.h" + +#include "sixlowpan-nd-header.h" + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE ("SixLowPanNdHeader"); + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6DuplicateAddress); + +Icmpv6DuplicateAddress::Icmpv6DuplicateAddress () +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_REQUEST); + SetCode (0); + SetChecksum (0); + m_status = 0; + m_reserved = 0; + m_regTime = 0; + m_eui64 = Mac64Address ("00:00:00:00:00:00"); + m_regAddress = Ipv6Address ("::"); +} + +Icmpv6DuplicateAddress::Icmpv6DuplicateAddress (bool request) +{ + NS_LOG_FUNCTION (this << request); + SetType (request ? Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_REQUEST : Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_CONFIRM); + SetCode (0); + SetChecksum (0); + m_status = 0; + m_reserved = 0; + m_regTime = 0; + m_eui64 = Mac64Address ("00:00:00:00:00:00"); + m_regAddress = Ipv6Address ("::"); +} + +Icmpv6DuplicateAddress::Icmpv6DuplicateAddress (uint16_t time, Mac64Address eui, Ipv6Address address) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_REQUEST); + SetCode (0); + SetChecksum (0); + m_status = 0; + m_reserved = 0; + m_regTime = time; + m_eui64 = eui; + m_regAddress = address; +} + +Icmpv6DuplicateAddress::Icmpv6DuplicateAddress (uint8_t status, uint16_t time, Mac64Address eui, Ipv6Address address) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_CONFIRM); + SetCode (0); + SetChecksum (0); + m_status = status; + m_reserved = 0; + m_regTime = time; + m_eui64 = eui; + m_regAddress = address; +} + +Icmpv6DuplicateAddress::~Icmpv6DuplicateAddress () +{ + NS_LOG_FUNCTION (this); +} + +TypeId Icmpv6DuplicateAddress::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6DuplicateAddress") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6DuplicateAddress::GetInstanceTypeId () const +{ + NS_LOG_FUNCTION (this); + return GetTypeId (); +} + +uint8_t Icmpv6DuplicateAddress::GetStatus () const +{ + NS_LOG_FUNCTION (this); + return m_status; +} + +void Icmpv6DuplicateAddress::SetStatus (uint8_t status) +{ + NS_LOG_FUNCTION (this << static_cast (status)); + m_status = status; +} + +uint8_t Icmpv6DuplicateAddress::GetReserved () const +{ + NS_LOG_FUNCTION (this); + return m_reserved; +} + +void Icmpv6DuplicateAddress::SetReserved (uint8_t reserved) +{ + NS_LOG_FUNCTION (this << static_cast (reserved)); + m_reserved = reserved; +} + +uint16_t Icmpv6DuplicateAddress::GetRegTime () const +{ + NS_LOG_FUNCTION (this); + return m_regTime; +} + +void Icmpv6DuplicateAddress::SetRegTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_regTime = time; +} + +Mac64Address Icmpv6DuplicateAddress::GetEui64 () const +{ + NS_LOG_FUNCTION (this); + return m_eui64; +} + +void Icmpv6DuplicateAddress::SetEui64 (Mac64Address eui) +{ + NS_LOG_FUNCTION (this << eui); + m_eui64 = eui; +} + +Ipv6Address Icmpv6DuplicateAddress::GetRegAddress () const +{ + NS_LOG_FUNCTION (this); + return m_regAddress; +} + +void Icmpv6DuplicateAddress::SetRegAddress (Ipv6Address registered) +{ + NS_LOG_FUNCTION (this << registered); + m_regAddress = registered; +} + +void Icmpv6DuplicateAddress::Print (std::ostream& os) const +{ + NS_LOG_FUNCTION (this << &os); + os << "( type = " << (uint32_t)GetType () << " code = " << (uint32_t)GetCode () << " status = " << (uint32_t)m_status << " lifetime = " << m_regTime << " EUI-64 = " << m_eui64 << " registered = " << m_regAddress << " checksum = " << (uint32_t)GetChecksum () << ")"; +} + +uint32_t Icmpv6DuplicateAddress::GetSerializedSize () const +{ + NS_LOG_FUNCTION (this); + return 32; +} + +void Icmpv6DuplicateAddress::Serialize (Buffer::Iterator start) const +{ + NS_LOG_FUNCTION (this << &start); + uint8_t buf1[8]; + uint8_t buf2[16]; + uint16_t checksum = 0; + Buffer::Iterator i = start; + + memset (buf1, 0x00, sizeof (buf1)); + memset (buf2, 0x0000, sizeof (buf2)); + + i.WriteU8 (GetType ()); + i.WriteU8 (GetCode ()); + i.WriteU16 (checksum); + i.WriteU8 (m_status); + i.WriteU8 (m_reserved); + i.WriteU16 (m_regTime); + + m_eui64.CopyTo (buf1); + i.Write (buf1, 8); + + m_regAddress.Serialize (buf2); + i.Write (buf2, 16); + + i = start; + checksum = i.CalculateIpChecksum (i.GetSize (), GetChecksum ()); + + i = start; + i.Next (2); + i.WriteU16 (checksum); +} + +uint32_t Icmpv6DuplicateAddress::Deserialize (Buffer::Iterator start) +{ + NS_LOG_FUNCTION (this << &start); + uint8_t buf1[8]; + uint8_t buf2[16]; + Buffer::Iterator i = start; + + memset (buf1, 0x00, sizeof (buf1)); + memset (buf2, 0x0000, sizeof (buf2)); + + SetType (i.ReadU8 ()); + SetCode (i.ReadU8 ()); + SetChecksum (i.ReadU16 ()); + m_status = i.ReadU8 (); + m_reserved = i.ReadU8 (); + m_regTime = i.ReadU16 (); + + i.Read (buf1, 8); + m_eui64.CopyFrom (buf1); + + i.Read (buf2, 16); + m_regAddress.Deserialize (buf2); + + return GetSerializedSize (); +} + + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionAddressRegistration); + +Icmpv6OptionAddressRegistration::Icmpv6OptionAddressRegistration () +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_ADDRESS_REGISTRATION); + SetLength (2); + m_status = 0; + m_reserved1 = 0; + m_reserved2 = 0; + m_regTime = 0; + m_eui64 = Mac64Address ("00:00:00:00:00:00"); +} + +Icmpv6OptionAddressRegistration::Icmpv6OptionAddressRegistration (uint16_t time, Mac64Address eui) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_ADDRESS_REGISTRATION); + SetLength (2); + m_status = 0; + m_reserved1 = 0; + m_reserved2 = 0; + m_regTime = time; + m_eui64 = eui; +} + +Icmpv6OptionAddressRegistration::Icmpv6OptionAddressRegistration (uint8_t status, uint16_t time, Mac64Address eui) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_ADDRESS_REGISTRATION); + SetLength (2); + m_status = status; + m_reserved1 = 0; + m_reserved2 = 0; + m_regTime = time; + m_eui64 = eui; +} + +Icmpv6OptionAddressRegistration::~Icmpv6OptionAddressRegistration () +{ + NS_LOG_FUNCTION (this); +} + +TypeId Icmpv6OptionAddressRegistration::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6OptionAddressRegistration") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6OptionAddressRegistration::GetInstanceTypeId () const +{ + NS_LOG_FUNCTION (this); + return GetTypeId (); +} + +uint8_t Icmpv6OptionAddressRegistration::GetStatus () const +{ + NS_LOG_FUNCTION (this); + return m_status; +} + +void Icmpv6OptionAddressRegistration::SetStatus (uint8_t status) +{ + NS_LOG_FUNCTION (this << static_cast (status)); + m_status = status; +} + +uint8_t Icmpv6OptionAddressRegistration::GetReserved1 () const +{ + NS_LOG_FUNCTION (this); + return m_reserved1; +} + +void Icmpv6OptionAddressRegistration::SetReserved1 (uint8_t reserved) +{ + NS_LOG_FUNCTION (this << static_cast (reserved)); + m_reserved1 = reserved; +} + +uint16_t Icmpv6OptionAddressRegistration::GetReserved2 () const +{ + NS_LOG_FUNCTION (this); + return m_reserved2; +} + +void Icmpv6OptionAddressRegistration::SetReserved2 (uint16_t reserved) +{ + NS_LOG_FUNCTION (this << reserved); + m_reserved2 = reserved; +} + +uint16_t Icmpv6OptionAddressRegistration::GetRegTime () const +{ + NS_LOG_FUNCTION (this); + return m_regTime; +} + +void Icmpv6OptionAddressRegistration::SetRegTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_regTime = time; +} + +Mac64Address Icmpv6OptionAddressRegistration::GetEui64 () const +{ + NS_LOG_FUNCTION (this); + return m_eui64; +} + +void Icmpv6OptionAddressRegistration::SetEui64 (Mac64Address eui) +{ + NS_LOG_FUNCTION (this << eui); + m_eui64 = eui; +} + +void Icmpv6OptionAddressRegistration::Print (std::ostream& os) const +{ + NS_LOG_FUNCTION (this << &os); + os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " status " << (uint32_t)m_status << " lifetime " << m_regTime << " EUI-64 " << m_eui64 << ")"; +} + +uint32_t Icmpv6OptionAddressRegistration::GetSerializedSize () const +{ + NS_LOG_FUNCTION (this); + return 16; +} + +void Icmpv6OptionAddressRegistration::Serialize (Buffer::Iterator start) const +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[8]; + + memset (buf, 0x00, sizeof (buf)); + + i.WriteU8 (GetType ()); + i.WriteU8 (GetLength ()); + i.WriteU8 (m_status); + i.WriteU8 (m_reserved1); + i.WriteU16 (m_reserved2); + i.WriteU16 (m_regTime); + + m_eui64.CopyTo (buf); + i.Write (buf, 8); +} + +uint32_t Icmpv6OptionAddressRegistration::Deserialize (Buffer::Iterator start) +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[8]; + + memset (buf, 0x00, sizeof (buf)); + + SetType (i.ReadU8 ()); + SetLength (i.ReadU8 ()); + m_status = i.ReadU8 (); + m_reserved1 = i.ReadU8 (); + m_reserved2 = i.ReadU16 (); + m_regTime = i.ReadU16 (); + + i.Read (buf, 8); + m_eui64.CopyFrom (buf); + + return GetSerializedSize (); +} + + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionSixLowPanContext); + +Icmpv6OptionSixLowPanContext::Icmpv6OptionSixLowPanContext () +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_SIXLOWPAN_CONTEXT); + SetLength (0); + m_contextLen = 0; + m_reserved1 = 0; + m_c = false; + m_cid = 0; + m_reserved2 = 0; + m_validTime = 0; + m_prefix = Ipv6Prefix ("::"); +} + +Icmpv6OptionSixLowPanContext::Icmpv6OptionSixLowPanContext (bool c, uint8_t cid, uint16_t time, Ipv6Prefix prefix) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_SIXLOWPAN_CONTEXT); + + if (prefix.GetPrefixLength () > 64) + { + SetLength (3); + } + else + { + SetLength (2); + } + + m_contextLen = prefix.GetPrefixLength (); + m_reserved1 = 0; + m_c = c; + m_cid = cid; + m_reserved2 = 0; + m_validTime = time; + m_prefix = prefix; +} + +Icmpv6OptionSixLowPanContext::~Icmpv6OptionSixLowPanContext () +{ + NS_LOG_FUNCTION (this); +} + +TypeId Icmpv6OptionSixLowPanContext::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6OptionSixLowPanContext") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6OptionSixLowPanContext::GetInstanceTypeId () const +{ + NS_LOG_FUNCTION (this); + return GetTypeId (); +} + +uint8_t Icmpv6OptionSixLowPanContext::GetContextLen () const +{ + NS_LOG_FUNCTION (this); + return m_contextLen; +} + +void Icmpv6OptionSixLowPanContext::SetContextLen (uint8_t cLen) +{ + NS_LOG_FUNCTION (this << static_cast (cLen)); + NS_ASSERT (cLen <= 128); + m_contextLen = cLen; +} + +uint8_t Icmpv6OptionSixLowPanContext::GetReserved1 () const +{ + NS_LOG_FUNCTION (this); + return m_reserved1; +} + +void Icmpv6OptionSixLowPanContext::SetReserved1 (uint8_t reserved1) +{ + NS_LOG_FUNCTION (this << static_cast (reserved1)); + m_reserved1 = reserved1; +} + +bool Icmpv6OptionSixLowPanContext::IsFlagC () const +{ + NS_LOG_FUNCTION (this); + return m_c; +} + +void Icmpv6OptionSixLowPanContext::SetFlagC (bool c) +{ + NS_LOG_FUNCTION (this << c); + m_c = c; +} + +uint8_t Icmpv6OptionSixLowPanContext::GetCid () const +{ + NS_LOG_FUNCTION (this); + return m_cid; +} + +void Icmpv6OptionSixLowPanContext::SetCid (uint8_t cid) +{ + NS_LOG_FUNCTION (this << static_cast (cid)); + NS_ASSERT (cid <= 15); + m_cid = cid; +} + +uint16_t Icmpv6OptionSixLowPanContext::GetReserved2 () const +{ + NS_LOG_FUNCTION (this); + return m_reserved2; +} + +void Icmpv6OptionSixLowPanContext::SetReserved2 (uint16_t reserved2) +{ + NS_LOG_FUNCTION (this << reserved2); + m_reserved2 = reserved2; +} + +uint16_t Icmpv6OptionSixLowPanContext::GetValidTime () const +{ + NS_LOG_FUNCTION (this); + return m_validTime; +} + +void Icmpv6OptionSixLowPanContext::SetValidTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_validTime = time; +} + +Ipv6Prefix Icmpv6OptionSixLowPanContext::GetContextPrefix () const +{ + NS_LOG_FUNCTION (this); + return m_prefix; +} + +void Icmpv6OptionSixLowPanContext::SetContextPrefix (Ipv6Prefix prefix) +{ + NS_LOG_FUNCTION (this << prefix); + m_prefix = prefix; +} + +void Icmpv6OptionSixLowPanContext::Print (std::ostream& os) const +{ + NS_LOG_FUNCTION (this << &os); + os << "( type = " << (uint32_t)GetType () << " length = " + << (uint32_t)GetLength () << " context length = " + << (uint32_t)m_contextLen << " flag C = " << m_c << " CID = " + << (uint32_t)m_cid << " lifetime = " << m_validTime + << " context prefix = " << m_prefix << ")"; +} + +uint32_t Icmpv6OptionSixLowPanContext::GetSerializedSize () const +{ + NS_LOG_FUNCTION (this); + uint8_t nb = GetLength() * 8; + return nb; +} + +void Icmpv6OptionSixLowPanContext::Serialize (Buffer::Iterator start) const +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[16]; + uint8_t reserved = m_reserved1; + + memset (buf, 0x0000, sizeof (buf)); + + i.WriteU8 (GetType ()); + i.WriteU8 (GetLength ()); + i.WriteU8 (m_contextLen); + + reserved |= m_cid; + reserved |= (uint8_t)(m_c << 4); + + i.WriteU8 (reserved); + i.WriteU16 (m_reserved2); + i.WriteU16 (m_validTime); + + m_prefix.GetBytes (buf); + i.Write (buf, 16); +} + +uint32_t Icmpv6OptionSixLowPanContext::Deserialize (Buffer::Iterator start) +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[16]; + uint8_t reserved; + + memset (buf, 0x0000, sizeof (buf)); + + SetType (i.ReadU8 ()); + SetLength (i.ReadU8 ()); + SetContextLen (i.ReadU8 ()); + + reserved = i.ReadU8 (); + m_c = false; + if (reserved & (uint8_t)(1 << 4)) + { + m_c = true; + } + m_cid = reserved & 0xF; + m_reserved1 = reserved >> 5; + + m_reserved2 = i.ReadU16 (); + m_validTime = i.ReadNtohU16 (); + + i.Read (buf, 16); + m_prefix = Ipv6Prefix (buf); + + return GetSerializedSize (); +} + + +NS_OBJECT_ENSURE_REGISTERED (Icmpv6OptionAuthoritativeBorderRouter); + +Icmpv6OptionAuthoritativeBorderRouter::Icmpv6OptionAuthoritativeBorderRouter () +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_AUTHORITATIVE_BORDER_ROUTER); + SetLength (3); + m_version = 0; + m_validTime = 0; + m_routerAddress = Ipv6Address ("::"); +} + +Icmpv6OptionAuthoritativeBorderRouter::Icmpv6OptionAuthoritativeBorderRouter (uint32_t version, uint16_t time, Ipv6Address address) +{ + NS_LOG_FUNCTION (this); + SetType (Icmpv6Header::ICMPV6_OPT_AUTHORITATIVE_BORDER_ROUTER); + SetLength (3); + m_version = version; + m_validTime = time; + m_routerAddress = address; +} + +Icmpv6OptionAuthoritativeBorderRouter::~Icmpv6OptionAuthoritativeBorderRouter () +{ + NS_LOG_FUNCTION (this); +} + +TypeId Icmpv6OptionAuthoritativeBorderRouter::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::Icmpv6OptionAuthoritativeBorderRouter") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + ; + return tid; +} + +TypeId Icmpv6OptionAuthoritativeBorderRouter::GetInstanceTypeId () const +{ + NS_LOG_FUNCTION (this); + return GetTypeId (); +} + +uint32_t Icmpv6OptionAuthoritativeBorderRouter::GetVersion () const +{ + NS_LOG_FUNCTION (this); + return m_version; +} + +void Icmpv6OptionAuthoritativeBorderRouter::SetVersion (uint32_t version) +{ + NS_LOG_FUNCTION (this << version); + m_version = version; +} + +uint16_t Icmpv6OptionAuthoritativeBorderRouter::GetValidTime () const +{ + NS_LOG_FUNCTION (this); + return m_validTime; +} + +void Icmpv6OptionAuthoritativeBorderRouter::SetValidTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_validTime = time; +} + +Ipv6Address Icmpv6OptionAuthoritativeBorderRouter::GetRouterAddress () const +{ + NS_LOG_FUNCTION (this); + return m_routerAddress; +} + +void Icmpv6OptionAuthoritativeBorderRouter::SetRouterAddress (Ipv6Address router) +{ + NS_LOG_FUNCTION (this << router); + m_routerAddress = router; +} + +void Icmpv6OptionAuthoritativeBorderRouter::Print (std::ostream& os) const +{ + NS_LOG_FUNCTION (this << &os); + os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " version = " << m_version << " lifetime = " << m_validTime << " router address = " << m_routerAddress << ")"; +} + +uint32_t Icmpv6OptionAuthoritativeBorderRouter::GetSerializedSize () const +{ + NS_LOG_FUNCTION (this); + return 24; +} + +void Icmpv6OptionAuthoritativeBorderRouter::Serialize (Buffer::Iterator start) const +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[16]; + uint32_t versionL = m_version; + uint32_t versionH = m_version; + + memset (buf, 0x0000, sizeof (buf)); + + i.WriteU8 (GetType ()); + i.WriteU8 (GetLength ()); + + versionL &= 0xFFFF; + i.WriteU16 ((uint16_t)versionL); + versionH >>= 16; + versionH &= 0xFFFF; + i.WriteU16 ((uint16_t)versionH); + + i.WriteU16 (m_validTime); + + m_routerAddress.Serialize (buf); + i.Write (buf, 16); +} + +uint32_t Icmpv6OptionAuthoritativeBorderRouter::Deserialize (Buffer::Iterator start) +{ + NS_LOG_FUNCTION (this << &start); + Buffer::Iterator i = start; + uint8_t buf[16]; + uint32_t versionL; + uint32_t versionH; + + memset (buf, 0x0000, sizeof (buf)); + + SetType (i.ReadU8 ()); + SetLength (i.ReadU8 ()); + + versionL = (uint32_t)i.ReadU16 (); + versionH = (uint32_t)i.ReadU16 (); + versionH <<= 16; + m_version = (versionL &= 0xFFFF) + (versionH &= 0xFFFF0000); + + m_validTime = i.ReadU16 (); + + i.Read (buf, 16); + m_routerAddress.Deserialize (buf); + + return GetSerializedSize (); +} + +} /* namespace ns3 */ diff --git a/src/sixlowpan/model/sixlowpan-nd-header.h b/src/sixlowpan/model/sixlowpan-nd-header.h new file mode 100644 index 000000000..a171ed666 --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-nd-header.h @@ -0,0 +1,668 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#ifndef SIXLOWPAN_ND_HEADER_H +#define SIXLOWPAN_ND_HEADER_H + +#include "ns3/header.h" +#include "ns3/ipv6-address.h" +#include "ns3/mac64-address.h" +#include "ns3/icmpv6-header.h" + +namespace ns3 +{ + +/** + * \ingroup sixlowpan + * \class Icmpv6DuplicateAddress + * \brief ICMPv6 Duplicate Address header. + */ +class Icmpv6DuplicateAddress : public Icmpv6Header +{ +public: + + /** + * \brief Constructor. + */ + Icmpv6DuplicateAddress (); + + /** + * \brief Constructor. + * \param request duplicate address request or duplicate address confirm + */ + Icmpv6DuplicateAddress (bool request); + + /** + * \brief Constructor (DAR). + * \param time the registration lifetime (units of 60 seconds) + * \param eui the EUI-64 + * \param address the registrered address + */ + Icmpv6DuplicateAddress (uint16_t time, Mac64Address eui, Ipv6Address address); + + /** + * \brief Constructor (DAC). + * \param status the status (DAC) + * \param time the registration lifetime (units of 60 seconds) + * \param eui the EUI-64 + * \param address the registrered address + */ + Icmpv6DuplicateAddress (uint8_t status, uint16_t time, Mac64Address eui, Ipv6Address address); + + /** + * \brief Destructor. + */ + virtual ~Icmpv6DuplicateAddress (); + + /** + * \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 status field. + * \return status value + */ + uint8_t GetStatus () const; + + /** + * \brief Set the status field. + * \param status the status value + */ + void SetStatus (uint8_t status); + + /** + * \brief Get the reserved field. + * \return reserved value + */ + uint8_t GetReserved () const; + + /** + * \brief Set the reserved field. + * \param reserved the reserved value + */ + void SetReserved (uint8_t reserved); + + /** + * \brief Get the registration lifetime field. + * \return registration lifetime value (units of 60 seconds) + */ + uint16_t GetRegTime () const; + + /** + * \brief Set the registration lifetime field. + * \param time the registration lifetime value (units of 60 seconds) + */ + void SetRegTime (uint16_t time); + + /** + * \brief Get the EUI-64 field. + * \return EUI-64 value + */ + Mac64Address GetEui64 () const; + + /** + * \brief Set the EUI-64 field. + * \param eui the EUI-64 value + */ + void SetEui64 (Mac64Address eui); + + /** + * \brief Get the registered address field. + * \return registered address value + */ + Ipv6Address GetRegAddress () const; + + /** + * \brief Set the registered address field. + * \param registered the registered address value + */ + void SetRegAddress (Ipv6Address registered); + + /** + * \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 status value. + */ + uint8_t m_status; + + /** + * \brief The reserved value. + */ + uint8_t m_reserved; + + /** + * \brief The registration lifetime value (units of 60 seconds). + */ + uint16_t m_regTime; + + /** + * \brief The EUI-64 value. + */ + Mac64Address m_eui64; + + /** + * \brief The registered address value. + */ + Ipv6Address m_regAddress; + +}; + +/** + * \ingroup sixlowpan + * \class Icmpv6OptionAddressRegistration + * \brief ICMPv6 Address Registration Option header. + */ +class Icmpv6OptionAddressRegistration : public Icmpv6OptionHeader +{ +public: + + /** + * \brief Constructor. + */ + Icmpv6OptionAddressRegistration (); + + /** + * \brief Constructor. + * \param time the registration lifetime (units of 60 seconds) + * \param eui the EUI-64 + */ + Icmpv6OptionAddressRegistration (uint16_t time, Mac64Address eui); + + /** + * \brief Constructor. + * \param status the status value + * \param time the registration lifetime (units of 60 seconds) + * \param eui the EUI-64 + */ + Icmpv6OptionAddressRegistration (uint8_t status, uint16_t time, Mac64Address eui); + + /** + * \brief Destructor. + */ + virtual ~Icmpv6OptionAddressRegistration (); + + /** + * \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 status field. + * \return status value + */ + uint8_t GetStatus () const; + + /** + * \brief Set the status field. + * \param status the status value + */ + void SetStatus (uint8_t status); + + /** + * \brief Get the first reserved field. + * \return first reserved value + */ + uint8_t GetReserved1 () const; + + /** + * \brief Set the first reserved field. + * \param reserved the first reserved value + */ + void SetReserved1 (uint8_t reserved); + + /** + * \brief Get the second reserved field. + * \return second reserved value + */ + uint16_t GetReserved2 () const; + + /** + * \brief Set the second reserved field. + * \param reserved the second reserved value + */ + void SetReserved2 (uint16_t reserved); + + /** + * \brief Get the registration lifetime field. + * \return registration lifetime value (units of 60 seconds) + */ + uint16_t GetRegTime () const; + + /** + * \brief Set the registration lifetime field. + * \param time the registration lifetime value (units of 60 seconds) + */ + void SetRegTime (uint16_t time); + + /** + * \brief Get the EUI-64 field. + * \return EUI-64 value + */ + Mac64Address GetEui64 () const; + + /** + * \brief Set the EUI-64 field. + * \param eui the EUI-64 value + */ + void SetEui64 (Mac64Address eui); + + /** + * \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 status value. + */ + uint8_t m_status; + + /** + * \brief The first reserved value. + */ + uint8_t m_reserved1; + + /** + * \brief The second reserved value. + */ + uint16_t m_reserved2; + + /** + * \brief The registration lifetime value (units of 60 seconds). + */ + uint16_t m_regTime; + + /** + * \brief The EUI-64 value. + */ + Mac64Address m_eui64; + +}; + +/** + * \ingroup sixlowpan + * \class Icmpv6OptionSixLowPanContext + * \brief ICMPv6 SixLowPan Context Option header. + */ +class Icmpv6OptionSixLowPanContext : public Icmpv6OptionHeader +{ +public: + + /** + * \brief Constructor. + */ + Icmpv6OptionSixLowPanContext (); + + /** + * \brief Constructor. + * \param c the c flag + * \param cid the context identifier + * \param time the valid lifetime (units of 60 seconds) + * \param prefix the context prefix + */ + Icmpv6OptionSixLowPanContext (bool c, uint8_t cid, uint16_t time, Ipv6Prefix prefix); + + /** + * \brief Destructor. + */ + virtual ~Icmpv6OptionSixLowPanContext (); + + /** + * \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 context length field. + * \return context length value + */ + uint8_t GetContextLen () const; + + /** + * \brief Set the context length field. + * \param cLen the context length value + */ + void SetContextLen (uint8_t cLen); + + /** + * \brief Get the first reserved field. + * \return first reserved value + */ + uint8_t GetReserved1 () const; + + /** + * \brief Set the first reserved field. + * \param reserved the first reserved value + */ + void SetReserved1 (uint8_t reserved1); + + /** + * \brief Is compression flag ? + * \return true if context is valid for use in compression, false otherwise + */ + bool IsFlagC () const; + + /** + * \brief Set the C flag. + * \param c the C flag + */ + void SetFlagC (bool c); + + /** + * \brief Get the context identifier field. + * \return context identifier value + */ + uint8_t GetCid () const; + + /** + * \brief Set the context identifier field. + * \param cid the context identifier value + */ + void SetCid (uint8_t cid); + + /** + * \brief Get the second reserved field. + * \return second reserved value + */ + uint16_t GetReserved2 () const; + + /** + * \brief Set the second reserved field. + * \param reserved the second reserved value + */ + void SetReserved2 (uint16_t reserved); + + /** + * \brief Get the valid lifetime field. + * \return valid lifetime value (units of 60 seconds) + */ + uint16_t GetValidTime () const; + + /** + * \brief Set the valid lifetime field. + * \param time the valid lifetime value (units of 60 seconds) + */ + void SetValidTime (uint16_t time); + + /** + * \brief Get the context prefix field. + * \return context prefix value + */ + Ipv6Prefix GetContextPrefix () const; + + /** + * \brief Set the context prefix field. + * \param prefix the context prefix value + */ + void SetContextPrefix (Ipv6Prefix 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 context length value. + */ + uint8_t m_contextLen; + + /** + * \brief The first reserved value. + */ + uint8_t m_reserved1; + + /** + * \brief The compression flag, indicates that this context is valid for use in compression. + */ + bool m_c; + + /** + * \brief The context identifier value. + */ + uint8_t m_cid; + + /** + * \brief The second reserved value. + */ + uint16_t m_reserved2; + + /** + * \brief The valid lifetime value (units of 60 seconds). + */ + uint16_t m_validTime; + + /** + * \brief The context prefix value. + */ + Ipv6Prefix m_prefix; + +}; + +/** + * \ingroup sixlowpan + * \class Icmpv6OptionAuthoritativeBorderRouter + * \brief ICMPv6 Authoritative Border Router Option header. + */ +class Icmpv6OptionAuthoritativeBorderRouter : public Icmpv6OptionHeader +{ +public: + + /** + * \brief Constructor. + */ + Icmpv6OptionAuthoritativeBorderRouter (); + + /** + * \brief Constructor. + * \param version the version value + * \param time the valid lifetime (units of 60 seconds) + * \param address the 6LBR address + */ + Icmpv6OptionAuthoritativeBorderRouter (uint32_t version, uint16_t time, Ipv6Address address); + + /** + * \brief Destructor. + */ + virtual ~Icmpv6OptionAuthoritativeBorderRouter (); + + /** + * \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 version field. + * \return version value + */ + uint32_t GetVersion () const; + + /** + * \brief Set the version field. + * \param version the version value + */ + void SetVersion (uint32_t version); + + /** + * \brief Get the valid lifetime field. + * \return valid lifetime value (units of 60 seconds) + */ + uint16_t GetValidTime () const; + + /** + * \brief Set the valid lifetime field. + * \param time the valid lifetime value (units of 60 seconds) + */ + void SetValidTime (uint16_t time); + + /** + * \brief Get the 6LB router address field. + * \return 6LB router address value + */ + Ipv6Address GetRouterAddress () const; + + /** + * \brief Set the 6LB router address field. + * \param router the 6LB router address value + */ + void SetRouterAddress (Ipv6Address router); + + /** + * \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 version value. + */ + uint32_t m_version; + + /** + * \brief The valid lifetime value (units of 60 seconds). + */ + uint16_t m_validTime; + + /** + * \brief The 6LB router address value. + */ + Ipv6Address m_routerAddress; + +}; + +} /* namespace ns3 */ + +#endif /* SIXLOWPAN_ND_HEADER_H */ diff --git a/src/sixlowpan/model/sixlowpan-nd-protocol.cc b/src/sixlowpan/model/sixlowpan-nd-protocol.cc new file mode 100644 index 000000000..db4557969 --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-nd-protocol.cc @@ -0,0 +1,1124 @@ +/* -*- 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 + * Tommaso Pecorella + */ + +#include "ns3/log.h" +#include "ns3/ptr.h" +#include "ns3/assert.h" +#include "ns3/packet.h" +#include "ns3/node.h" +#include "ns3/boolean.h" +#include "ns3/ipv6-routing-protocol.h" +#include "ns3/ipv6-route.h" +#include "ns3/mac64-address.h" +#include "ns3/mac48-address.h" +#include "ns3/mac16-address.h" +#include "ns3/pointer.h" +#include "ns3/uinteger.h" +#include "ns3/string.h" +#include "ns3/sgi-hashmap.h" +#include "ns3/ipv6-l3-protocol.h" +#include "ns3/ipv6-interface.h" + +#include "sixlowpan-nd-protocol.h" +#include "sixlowpan-ndisc-cache.h" +#include "sixlowpan-ndisc-ra-options.h" +#include "sixlowpan-nd-header.h" +#include "sixlowpan-net-device.h" +#include "src/network/model/packet.h" +#include "src/core/model/integer.h" +#include "src/core/model/nstime.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("SixLowPanNdProtocol"); + +NS_OBJECT_ENSURE_REGISTERED (SixLowPanNdProtocol); + +const uint16_t SixLowPanNdProtocol::MIN_CONTEXT_CHANGE_DELAY = 300; + +const uint8_t SixLowPanNdProtocol::MAX_RTR_ADVERTISEMENTS = 3; +const uint8_t SixLowPanNdProtocol::MIN_DELAY_BETWEEN_RAS = 10; +const uint8_t SixLowPanNdProtocol::MAX_RA_DELAY_TIME = 2; +const uint8_t SixLowPanNdProtocol::TENTATIVE_NCE_LIFETIME = 20; + +const uint8_t SixLowPanNdProtocol::MULTIHOP_HOPLIMIT = 64; + +const uint8_t SixLowPanNdProtocol::RTR_SOLICITATION_INTERVAL = 10; +const uint8_t SixLowPanNdProtocol::MAX_RTR_SOLICITATIONS = 3; +const uint8_t SixLowPanNdProtocol::MAX_RTR_SOLICITATION_INTERVAL = 60; + +SixLowPanNdProtocol::SixLowPanNdProtocol () +: m_rsRetransmit (0), + m_aroRetransmit (0) +{ + NS_LOG_FUNCTION (this); +} + +SixLowPanNdProtocol::~SixLowPanNdProtocol () +{ + NS_LOG_FUNCTION (this); +} + +TypeId SixLowPanNdProtocol::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::SixLowPanNdProtocol") + .SetParent () + .SetGroupName ("Internet") + .AddConstructor () + .AddAttribute ("Border", "Is the node a 6LoWPAN Border Router.", + BooleanValue (false), + MakeBooleanAccessor (&SixLowPanNdProtocol::m_border), + MakeBooleanChecker ()) + .AddAttribute ("RegistrationLifeTime", "The amount of time (units of 60 seconds) that the router should retain the NCE for the node.", + UintegerValue (60), + MakeUintegerAccessor (&SixLowPanNdProtocol::m_regTime), + MakeUintegerChecker ()) + .AddAttribute ("AdvanceTime", "The advance to perform maintaining of RA's information and registration.", + UintegerValue (5), + MakeUintegerAccessor (&SixLowPanNdProtocol::m_advance), + MakeUintegerChecker ()) + ; + return tid; +} + +Ptr SixLowPanNdProtocol::ForgeNA (Ipv6Address src, Ipv6Address dst, Ipv6Address target, 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 << " target " << target << ")"); + + /* 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 (target); + + 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; +} + +void SixLowPanNdProtocol::SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, + Address linkAddr) +{ + NS_LOG_FUNCTION (this << src << dst << target << linkAddr); + + Ptr ipv6 = GetNode ()->GetObject (); + uint32_t interfaceId = ipv6->GetInterfaceForAddress (src); + Ptr interface = ipv6->GetInterface (interfaceId); + Ptr cache = FindCache (interface->GetDevice ()); + + if (src != Ipv6Address::GetAny ()) + { + NS_LOG_WARN ("An unspecified source address MUST NOT be used in NS messages."); + return; + } + + // only send NS if the target is a router. + NdiscCache::Entry *entry = cache->Lookup (dst); + if (entry) + { + if (entry->IsRouter ()) + { + Icmpv6L4Protocol::SendNS (interface->GetLinkLocalAddress ().GetAddress (), dst, + target, linkAddr); + } + } +} + +void SixLowPanNdProtocol::SendSixLowPanARO (Ipv6Address src, Ipv6Address dst, uint16_t time, + Mac64Address eui, Address linkAddr) +{ + NS_LOG_FUNCTION (this << src << dst << time << eui << linkAddr); + + /* an unspecified src MUST NOT be used in NS */ + + NS_ASSERT_MSG (src != Ipv6Address::GetAny (), "An unspecified source address MUST NOT be used in ARO messages."); + NS_ASSERT_MSG (!dst.IsMulticast (), "Destination address must not be a multicast address in ARO messages."); + + Ptr p = Create (); + Icmpv6NS ns (Ipv6Address::GetZero ()); + + /* ARO (request) + SLLAO */ + Icmpv6OptionAddressRegistration arOption (time, eui); + Icmpv6OptionLinkLayerAddress llOption (1, linkAddr); + + NS_LOG_LOGIC ("Send NS ( from " << src << " to " << dst << ")"); + + p->AddHeader (arOption); + p->AddHeader (llOption); + ns.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + ns.GetSerializedSize (), PROT_NUMBER); + p->AddHeader (ns); + + SendMessage (p, src, dst, 255); +} + +void SixLowPanNdProtocol::SendSixLowPanARO (Ipv6Address src, Ipv6Address dst, uint8_t status, + uint16_t time, Mac64Address eui) +{ + NS_LOG_FUNCTION (this << src << dst << static_cast (status) << time << eui); + Ptr p = Create (); + Icmpv6NA na; + + /* ARO (response) */ + Icmpv6OptionAddressRegistration arOption (status, time, eui); + + NS_LOG_LOGIC ("Send NA ( from " << src << " to " << dst << ")"); + + na.SetIpv6Target (Ipv6Address::GetZero ()); + na.SetFlagO (false); + na.SetFlagS (true); + na.SetFlagR (true); + + p->AddHeader (arOption); + na.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + na.GetSerializedSize (), PROT_NUMBER); + p->AddHeader (na); + + SendMessage (p, src, dst, 255); +} + +void SixLowPanNdProtocol::SendSixLowPanRA (Ipv6Address src, Ipv6Address dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << src << dst << interface); + + Ptr sixCache = FindSixLowPanCache (interface->GetDevice ()); + std::map raCache = sixCache->GetRaCache (); + + for (std::map::iterator it = raCache.begin (); + it != raCache.end (); it++) + { + Icmpv6RA raHdr; + Ipv6Header ipHeader; + + Ptr p = Create (); + + /* set RA header information */ + raHdr.SetFlagM (it->second->IsManagedFlag ()); + raHdr.SetFlagO (it->second->IsOtherConfigFlag ()); + raHdr.SetFlagH (it->second->IsHomeAgentFlag ()); + raHdr.SetCurHopLimit (it->second->GetCurHopLimit ()); + raHdr.SetLifeTime (it->second->GetRouterLifeTime ()); + raHdr.SetReachableTime (it->second->GetReachableTime ()); + raHdr.SetRetransmissionTime (it->second->GetRetransTimer ()); + + /* Add ABRO */ + Icmpv6OptionAuthoritativeBorderRouter abroHdr; + abroHdr.SetVersion (it->second->GetVersion ()); + abroHdr.SetValidTime (it->second->GetValidTime ()); + abroHdr.SetRouterAddress (it->second->GetBorderAddress ()); + p->AddHeader (abroHdr); + + /* Add SLLAO */ + Address addr = interface->GetDevice ()->GetAddress (); + Icmpv6OptionLinkLayerAddress llaHdr (1, addr); + p->AddHeader (llaHdr); + + /* Add PIOs */ + std::map > prefixes = it->second->GetPrefixes (); + for (std::map >::iterator jt = prefixes.begin (); jt != prefixes.end (); jt++) + { + Icmpv6OptionPrefixInformation prefixHdr; + prefixHdr.SetPrefixLength (jt->second->GetPrefixLength ()); + prefixHdr.SetFlags (jt->second->GetFlags ()); + prefixHdr.SetValidTime (jt->second->GetValidLifeTime ()); + prefixHdr.SetPreferredTime (jt->second->GetPreferredLifeTime ()); + prefixHdr.SetPrefix (jt->second->GetPrefix ()); + p->AddHeader (prefixHdr); + } + + /* Add 6COs */ + std::map > contexts = it->second->GetContexts (); + for (std::map >::iterator i = contexts.begin (); i != contexts.end (); i++) + { + Icmpv6OptionSixLowPanContext sixHdr; + sixHdr.SetContextLen (i->second->GetContextLen ()); + sixHdr.SetFlagC (i->second->IsFlagC ()); + sixHdr.SetCid (i->second->GetCid ()); + sixHdr.SetValidTime (i->second->GetValidTime ()); + sixHdr.SetContextPrefix (i->second->GetContextPrefix ()); + p->AddHeader (sixHdr); + } + + raHdr.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + raHdr.GetSerializedSize (), PROT_NUMBER); + p->AddHeader (raHdr); + + ipHeader.SetSourceAddress (src); + ipHeader.SetDestinationAddress (dst); + ipHeader.SetNextHeader (PROT_NUMBER); + ipHeader.SetPayloadLength (p->GetSize ()); + ipHeader.SetHopLimit (255); + + /* send RA */ + NS_LOG_LOGIC ("Send RA to " << dst); + interface->Send (p, ipHeader, dst); + } +} + +void SixLowPanNdProtocol::SendSixLowPanDAR (Ipv6Address src, Ipv6Address dst, uint16_t time, Mac64Address eui, + Ipv6Address registered) +{ + NS_LOG_FUNCTION (this << src << dst << time << eui << registered); + Ptr p = Create (); + Icmpv6DuplicateAddress dar (time, eui, registered); + + NS_LOG_LOGIC ("Send DAR ( from " << src << " to " << dst << ")"); + + dar.CalculatePseudoHeaderChecksum (src, dst, p->GetSize () + dar.GetSerializedSize (), PROT_NUMBER); + p->AddHeader (dar); + + SendMessage (p, src, dst, MULTIHOP_HOPLIMIT); +} + +enum IpL4Protocol::RxStatus SixLowPanNdProtocol::Receive (Ptr packet, Ipv6Header const &header, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << header.GetSourceAddress () << header.GetDestinationAddress () << + interface); + Ptr ipv6 = GetNode ()->GetObject (); + Ptr sixDevice = DynamicCast (interface->GetDevice()); + NS_ASSERT_MSG (sixDevice != NULL, "SixLowPanNdProtocol cannot be installed on device different from SixLowPanNetDevice"); + + uint8_t type; + packet->CopyData (&type, sizeof(type)); + + switch (type) + { + case Icmpv6Header::ICMPV6_ND_ROUTER_SOLICITATION: + if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (sixDevice))) + { + HandleSixLowPanRS (packet, header.GetSourceAddress (), header.GetDestinationAddress (), interface); + } + break; + case Icmpv6Header::ICMPV6_ND_ROUTER_ADVERTISEMENT: + HandleSixLowPanRA (packet, header.GetSourceAddress (), header.GetDestinationAddress (), interface); + break; + case Icmpv6Header::ICMPV6_ND_NEIGHBOR_SOLICITATION: + if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (sixDevice))) + { + HandleSixLowPanNS (packet, header.GetSourceAddress (), header.GetDestinationAddress (), interface); + } + break; + case Icmpv6Header::ICMPV6_ND_NEIGHBOR_ADVERTISEMENT: + HandleSixLowPanNA (packet, header.GetSourceAddress (), header.GetDestinationAddress (), interface); + break; + case Icmpv6Header::ICMPV6_ND_DUPLICATE_ADDRESS_CONFIRM: + if (ipv6->IsForwarding (ipv6->GetInterfaceForDevice (sixDevice))) + { + HandleSixLowPanDAC (packet, header.GetSourceAddress (), header.GetDestinationAddress (), interface); + } + break; + default: + return Icmpv6L4Protocol::Receive (packet, header, interface); + break; + } + + return IpL4Protocol::RX_OK; +} + +void SixLowPanNdProtocol::DoDispose () +{ + NS_LOG_FUNCTION (this); + + for (SixLowPanCacheList::const_iterator it = m_sixlowCList.begin (); it != m_sixlowCList.end (); it++) + { + Ptr cache = *it; + cache->Dispose (); + cache = 0; + } + m_sixlowCList.clear (); + + Icmpv6L4Protocol::DoDispose (); +} + +void SixLowPanNdProtocol::HandleSixLowPanNS (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + + Icmpv6NS nsHdr; + packet->RemoveHeader (nsHdr); + Ipv6Address target = nsHdr.GetIpv6Target (); + + Ptr sixDevice = DynamicCast (interface->GetDevice()); + NS_ASSERT_MSG (sixDevice != NULL, "SixLowPanNdProtocol cannot be installed on device different from SixLowPanNetDevice"); + + Icmpv6OptionLinkLayerAddress llaHdr (1); /* SLLAO */ + Icmpv6OptionAddressRegistration aroHdr; + + bool next = true; + bool hasLla = false; + bool hasAro = false; + + if (src != Ipv6Address::GetAny ()) + { + /* search all options following the NS header */ + while (next == true) + { + uint8_t type; + packet->CopyData (&type, sizeof(type)); + + switch (type) + { + case Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE: + if (!hasLla) + { + packet->RemoveHeader (llaHdr); + hasLla = true; + } + break; + case Icmpv6Header::ICMPV6_OPT_ADDRESS_REGISTRATION: + if (!hasAro) + { + packet->RemoveHeader (aroHdr); + hasAro = true; + } + break; + default: + /* unknow option, quit */ + next = false; + } + } + + if (!hasLla) /* error! */ + { + NS_LOG_ERROR ("NS message MUST have source link layer option."); + return; + } + else /* NS + SLLAO */ + { + /* Update "ARPv6" table with information of src */ + Ptr cache = FindCache (sixDevice); + + NdiscCache::Entry* entry = 0; + entry = cache->Lookup (src); + + if (!entry && src.IsLinkLocal()) + { + entry = cache->Add (src); + uint8_t buf[16]; + src.GetBytes (buf); + Mac16Address address; + address.CopyFrom (buf+14); + entry->SetRouter (false); + entry->SetMacAddress (llaHdr.GetAddress ()); + entry->MarkReachable (); + } + else if (!entry) + { + entry = cache->Add (src); + entry->SetRouter (false); + entry->MarkStale (llaHdr.GetAddress ()); + } + else if (entry->GetMacAddress () != llaHdr.GetAddress ()) + { + entry->MarkStale (llaHdr.GetAddress ()); + } + } + + if (!hasAro) /* NS + SLLAO */ + { + /* Send NA to src with information requested about target (in "ARPv6" table) */ + Ptr cache = FindCache (sixDevice); + + NdiscCache::Entry* entry = 0; + entry = cache->Lookup (target); + uint8_t flags; + + if (!entry) + { + NS_LOG_LOGIC ("No entry with address " << target); + return; + } + else + { + if (entry->IsRouter ()) + { + flags = 7; /* R + S + O flag */ + } + else + { + flags = 3; /* S + O flags */ + } + + /* NA + TLLAO */ + Ptr p = ForgeNA (interface->GetLinkLocalAddress ().GetAddress (), src, target, + entry->GetMacAddress (), flags); + Ipv6Header header; + p->RemoveHeader (header); + interface->Send (p, header, src); + } + } + else /* NS + SLLAO + ARO */ + { + /* Update NCE with information of src and ARO */ + Ptr nCache = FindSixLowPanCache (sixDevice); + + SixLowPanNdiscCache::SixLowPanEntry* nEntry = 0; + nEntry = nCache->SixLowPanLookup (src); + + std::map raCache = nCache->GetRaCache (); + + if (!nEntry) /* no entry, creating */ + { + if (aroHdr.GetRegTime () != 0) + { + nEntry = nCache->SixLowPanAdd (src); + nEntry->SetRouter (false); + nEntry->SetMacAddress (llaHdr.GetAddress ()); + nEntry->SetEui64 (aroHdr.GetEui64 ()); + nEntry->MarkReachable (); + + if (m_multihopDad) /* multihop DAD used */ + { + nEntry->MarkTentative (); + for (std::map::iterator it = raCache.begin (); + it != raCache.end (); it++) + { + Ipv6Address destination = it->second->GetBorderAddress (); + SendSixLowPanDAR (interface->GetAddressMatchingDestination (destination).GetAddress (), destination, + aroHdr.GetRegTime (), aroHdr.GetEui64 (), src); + } + return; + } + else /* multihop DAD NOT used */ + { + nEntry->MarkRegistered (aroHdr.GetRegTime ()); + SendSixLowPanARO (interface->GetLinkLocalAddress ().GetAddress (), src, 0, aroHdr.GetRegTime (), + aroHdr.GetEui64 ()); + return; + } + } + } + else if (nEntry->GetEui64 () == aroHdr.GetEui64 ()) /* entry found, same EUI-64, updating */ + { + if (aroHdr.GetRegTime () != 0) + { + nEntry->SetRouter (false); + nEntry->SetMacAddress (llaHdr.GetAddress ()); + nEntry->MarkReachable (); + nEntry->MarkRegistered (aroHdr.GetRegTime ()); + SendSixLowPanARO (interface->GetLinkLocalAddress ().GetAddress (), src, 0, aroHdr.GetRegTime (), + aroHdr.GetEui64 ()); + + if (m_multihopDad) + { + for (std::map::iterator it = raCache.begin (); + it != raCache.end (); it++) + { + Ipv6Address destination = it->second->GetBorderAddress (); + + /* Send request to update entry from DAD table */ + SendSixLowPanDAR (interface->GetAddressMatchingDestination (destination).GetAddress (), destination, + aroHdr.GetRegTime (), aroHdr.GetEui64 (), src); + } + } + + return; + } + else /* ARO's Registration Lifetime = 0 */ + { + if (m_multihopDad) + { + for (std::map::iterator it = raCache.begin (); + it != raCache.end (); it++) + { + Ipv6Address destination = it->second->GetBorderAddress (); + + /* Send request to remove entry from DAD table */ + SendSixLowPanDAR (interface->GetAddressMatchingDestination (destination).GetAddress (), destination, + aroHdr.GetRegTime (), aroHdr.GetEui64 (), src); + } + } + /* Remove the entry from Neighbor Cache */ + nCache->SixLowPanRemove (nEntry); + + /* Remove the entry from "ARPv6" table */ + Ptr cache = FindCache (sixDevice); + + NdiscCache::Entry* entry = 0; + entry = cache->Lookup (src); + cache->Remove (entry); + return; + } + } + else /* entry found, different EUI-64 */ + { + if (m_multihopDad && nEntry->IsRegistered ()) + { + SendSixLowPanARO (interface->GetLinkLocalAddress ().GetAddress (), + sixDevice->MakeLinkLocalAddressFromMac (aroHdr.GetEui64 ()), 1, + aroHdr.GetRegTime (), aroHdr.GetEui64 ()); + } + else if (!m_multihopDad) + { + SendSixLowPanARO (interface->GetLinkLocalAddress ().GetAddress (), + sixDevice->MakeLinkLocalAddressFromMac (aroHdr.GetEui64 ()), 1, + aroHdr.GetRegTime (), aroHdr.GetEui64 ()); + } + return; + } + } + } + else + { + NS_LOG_ERROR ("An unspecified source address MUST NOT be used in NS messages."); + return; + } +} + +void SixLowPanNdProtocol::HandleSixLowPanNA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + + Ptr p = packet->Copy (); + Icmpv6NS naHdr; + packet->RemoveHeader (naHdr); + Ipv6Address target = naHdr.GetIpv6Target (); + + Icmpv6OptionLinkLayerAddress llaHdr (0); /* TLLAO */ + Icmpv6OptionAddressRegistration aroHdr; + + uint8_t type; + packet->CopyData (&type, sizeof(type)); + + switch (type) + { + case Icmpv6Header::ICMPV6_OPT_LINK_LAYER_TARGET: /* NA + TLLAO */ + + HandleNA (p, target, dst, interface); /* Handle response of Address Resolution */ + + break; + case Icmpv6Header::ICMPV6_OPT_ADDRESS_REGISTRATION: /* NA + ARO */ + + packet->RemoveHeader (aroHdr); + + m_aroRetransmit = 0; + + if (aroHdr.GetStatus () == 0) /* status=0, success! */ + { + /* schedule a new ARO to maintain NCE in routers */ + + Simulator::Schedule (Time (Minutes (aroHdr.GetRegTime () - m_advance)), &SixLowPanNdProtocol::RetransmitARO, this, + dst, src, aroHdr.GetRegTime (), aroHdr.GetEui64 (), interface->GetDevice ()->GetAddress ()); + } + else /* status NOT 0, fail! */ + { + NS_LOG_LOGIC ("ARO status is NOT 0, registration failed!"); + /// \todo implement method to remove address that generated error. + return; + } + break; + default: + NS_LOG_ERROR ("NA message MUST have option."); + return; + } +} + +void SixLowPanNdProtocol::HandleSixLowPanRS (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + + Ptr sixDevice = DynamicCast (interface->GetDevice()); + NS_ASSERT_MSG (sixDevice != NULL, "SixLowPanNdProtocol cannot be installed on device different from SixLowPanNetDevice"); + + Icmpv6RS rsHeader; + Icmpv6OptionLinkLayerAddress lla (1); + + packet->RemoveHeader (rsHeader); + + if (src != Ipv6Address::GetAny ()) + { + uint8_t type; + packet->CopyData (&type, sizeof(type)); + + if (type != Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE) + { + NS_LOG_ERROR ("RS message MUST have source link layer option."); + return; + } + + packet->RemoveHeader (lla); + + /* Update Neighbor Cache */ + Ptr sixCache = FindSixLowPanCache (sixDevice); + SixLowPanNdiscCache::SixLowPanEntry* sixEntry = 0; + sixEntry = sixCache->SixLowPanLookup (src); + if (!sixEntry) + { + sixEntry = sixCache->SixLowPanAdd (src); + sixEntry->SetRouter (false); + sixEntry->MarkStale (lla.GetAddress ()); + sixEntry->MarkTentative (); + NS_LOG_LOGIC ("Tentative entry created from RS"); + } + else if (sixEntry->GetMacAddress () != lla.GetAddress ()) + { + sixEntry->MarkStale (lla.GetAddress ()); + } + + /* Update "ARPv6" table */ + Ptr cache = FindCache (sixDevice); + NdiscCache::Entry* entry = 0; + 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 ()); + } + } + + if (!m_border) + { + Address addr = lla.GetAddress (); + Ipv6Address destination = sixDevice->MakeLinkLocalAddressFromMac(addr); + + SendSixLowPanRA (interface->GetLinkLocalAddress ().GetAddress (), destination, interface); + } +} + +void SixLowPanNdProtocol::HandleSixLowPanRA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + + m_rsRetransmit = 0; + m_receivedRA = true; + + Ptr sixDevice = DynamicCast (interface->GetDevice()); + NS_ASSERT_MSG (sixDevice != NULL, "SixLowPanNdProtocol cannot be installed on device different from SixLowPanNetDevice"); + + Address addr = sixDevice->GetAddress (); + + Icmpv6RA raHeader; + Ptr ipv6 = GetNode ()->GetObject (); + + Icmpv6OptionAuthoritativeBorderRouter abrHdr; /* ABRO */ + Icmpv6OptionLinkLayerAddress llaHdr (1); /* SLLAO */ + + bool next = true; + Ptr sixCache = FindSixLowPanCache (sixDevice); + SixLowPanNdiscCache::SixLowPanRaEntry* ra = 0; + + Ptr cache = FindCache (sixDevice); + // sgi::hash_map ndiscCache = cache->GetNdiscCache (); + + uint32_t version; + Ipv6Address border; + + packet->RemoveHeader (raHeader); + + Ipv6Address defaultRouter = Ipv6Address::GetZero (); + + if (raHeader.GetLifeTime()) + { + defaultRouter = src; + } + + std::list prefixList; + std::list contextList; + Icmpv6OptionPrefixInformation prefixHdr; + Icmpv6OptionSixLowPanContext contextHdr; + + // \todo check the stop condiiton + while (next == true) + { + uint8_t type = 0; + packet->CopyData (&type, sizeof(type)); + + switch (type) + { + case Icmpv6Header::ICMPV6_OPT_PREFIX: + packet->RemoveHeader (prefixHdr); + prefixList.push_back (prefixHdr); + break; + case Icmpv6Header::ICMPV6_OPT_SIXLOWPAN_CONTEXT: + packet->RemoveHeader (contextHdr); + contextList.push_back (contextHdr); + break; + case Icmpv6Header::ICMPV6_OPT_AUTHORITATIVE_BORDER_ROUTER: + packet->RemoveHeader (abrHdr); + version = abrHdr.GetVersion (); + border = abrHdr.GetRouterAddress (); + break; + case Icmpv6Header::ICMPV6_OPT_LINK_LAYER_SOURCE: + packet->RemoveHeader (llaHdr); + ReceiveLLA (llaHdr, src, dst, interface); // generates an entry in NDISC table with m_router = true + break; + default: + /* Unknown option, quit */ + next = false; + break; + } + } + + ra = sixCache->RaEntryLookup (border); + if (!ra) // Create a new entry + { + ra = sixCache->AddRaEntry (border); + ra->SetManagedFlag (raHeader.GetFlagM ()); + ra->SetOtherConfigFlag (raHeader.GetFlagO ()); + ra->SetHomeAgentFlag (raHeader.GetFlagH ()); + ra->SetReachableTime (raHeader.GetReachableTime ()); + ra->SetRouterLifeTime (raHeader.GetLifeTime ()); + ra->SetRetransTimer (raHeader.GetRetransmissionTime ()); + ra->SetCurHopLimit (raHeader.GetCurHopLimit ()); + ra->SetVersion (version); + ra->SetValidTime (abrHdr.GetValidTime ()); + +// for (std::list::iterator it = prefixList.begin (); it != prefixList.end (); it++) +// { +// Ptr prefix = new SixLowPanPrefix; +// prefix->SetPrefixLength ((*it).GetPrefixLength ()); +// prefix->SetFlags ((*it).GetFlags ()); +// prefix->SetValidLifeTime ((*it).GetValidTime ()); +// prefix->SetPreferredLifeTime ((*it).GetPreferredTime ()); +// prefix->SetPrefix ((*it).GetPrefix ()); +// +// ra->AddPrefix (prefix); +// +// ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (sixDevice), +// (*it).GetPrefix (),(*it).GetPrefixLength (), +// (*it).GetFlags (), (*it).GetValidTime (), +// (*it).GetPreferredTime (), defaultRouter); +// +// for (sgi::hash_map::iterator k = ndiscCache.begin (); +// k != ndiscCache.end (); k++) +// { +// if (k->second->IsRouter ()) +// { +// SendSixLowPanARO (sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// k->second->GetIpv6Address (), m_regTime, Mac64Address::ConvertFrom (addr), +// addr); +// +// Simulator::Schedule (Time (Minutes (m_regTime - m_advance)), &SixLowPanNdProtocol::RetransmitARO, this, +// sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// k->second->GetIpv6Address (), m_regTime, Mac64Address::ConvertFrom (addr), +// addr); +// } +// } +// } + // \todo quiet compiler + NS_ASSERT (m_regTime); + + for (std::list::iterator jt = contextList.begin (); jt != contextList.end (); jt++) + { + Ptr context = new SixLowPanContext; + context->SetCid ((*jt).GetCid ()); + context->SetFlagC ((*jt).IsFlagC ()); + context->SetValidTime ((*jt).GetValidTime ()); + context->SetContextPrefix ((*jt).GetContextPrefix ()); + + ra->AddContext (context); + } + } + else if (ra && version > (ra->GetVersion ())) // Update existing entry from 6LBR with new information + { + ra->SetManagedFlag (raHeader.GetFlagM ()); + ra->SetOtherConfigFlag (raHeader.GetFlagO ()); + ra->SetHomeAgentFlag (raHeader.GetFlagH ()); + ra->SetReachableTime (raHeader.GetReachableTime ()); + ra->SetRouterLifeTime (raHeader.GetLifeTime ()); + ra->SetRetransTimer (raHeader.GetRetransmissionTime ()); + ra->SetCurHopLimit (raHeader.GetCurHopLimit ()); + ra->SetVersion (version); + ra->SetValidTime (abrHdr.GetValidTime ()); + + for (std::list::iterator it = prefixList.begin (); it != prefixList.end (); it++) + { + if (ra->GetPrefixes ().find ((*it).GetPrefix ()) == ra->GetPrefixes ().end ()) /* prefix NOT found */ + { + Ptr prefix = new SixLowPanPrefix; + prefix->SetPrefixLength ((*it).GetPrefixLength ()); + prefix->SetFlags ((*it).GetFlags ()); + prefix->SetValidLifeTime ((*it).GetValidTime ()); + prefix->SetPreferredLifeTime ((*it).GetPreferredTime ()); + prefix->SetPrefix ((*it).GetPrefix ()); + + ra->AddPrefix (prefix); + + ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (sixDevice), + (*it).GetPrefix (), (*it).GetPrefixLength (), + (*it).GetFlags (), (*it).GetValidTime (), + (*it).GetPreferredTime (), defaultRouter); +// for (sgi::hash_map::iterator kt = ndiscCache.begin (); +// kt != ndiscCache.end (); kt++) +// { +// if (kt->second->IsRouter ()) +// { +// SendSixLowPanARO (sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// kt->second->GetIpv6Address (), m_regTime, +// Mac64Address::ConvertFrom (addr), addr); +// +// Simulator::Schedule (Time (Minutes (m_regTime - m_advance)), &SixLowPanNdProtocol::RetransmitARO, this, +// sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// kt->second->GetIpv6Address (), m_regTime, Mac64Address::ConvertFrom (addr), +// addr); +// } +// } + } + else /* prefix found, updating! */ + { + Ptr prefix = (ra->GetPrefixes().find((*it).GetPrefix ()))->second; + + prefix->SetPrefixLength ((*it).GetPrefixLength ()); + prefix->SetFlags ((*it).GetFlags ()); + prefix->SetValidLifeTime ((*it).GetValidTime ()); + prefix->SetPreferredLifeTime ((*it).GetPreferredTime ()); + + ipv6->AddAutoconfiguredAddress (ipv6->GetInterfaceForDevice (sixDevice), + (*it).GetPrefix (), (*it).GetPrefixLength (), + (*it).GetFlags (), (*it).GetValidTime (), + (*it).GetPreferredTime (), defaultRouter); +// for (sgi::hash_map::iterator lt = ndiscCache.begin (); +// lt != ndiscCache.end (); lt++) +// { +// if (lt->second->IsRouter ()) +// { +// SendSixLowPanARO (sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// lt->second->GetIpv6Address (), m_regTime, Mac64Address::ConvertFrom (addr), +// addr); +// +// Simulator::Schedule (Time (Minutes (m_regTime - m_advance)), &SixLowPanNdProtocol::RetransmitARO, this, +// sixDevice->MakeGlobalAddressFromMac(addr, (*it).GetPrefix ()), +// lt->second->GetIpv6Address (), m_regTime, Mac64Address::ConvertFrom (addr), +// addr); +// } +// } + } + } + + for (std::list::iterator jt = contextList.begin (); jt != contextList.end (); jt++) + { + if (ra->GetContexts ().find ((*jt).GetCid ()) == ra->GetContexts ().end ()) /* context NOT found */ + { + Ptr context = new SixLowPanContext; + context->SetCid ((*jt).GetCid ()); + context->SetFlagC ((*jt).IsFlagC ()); + context->SetValidTime ((*jt).GetValidTime ()); + context->SetContextPrefix ((*jt).GetContextPrefix ()); + + ra->AddContext (context); + } + else + { + Ptr context = (ra->GetContexts ().find ((*jt).GetCid ()))->second; + + context->SetFlagC ((*jt).IsFlagC ()); + context->SetValidTime ((*jt).GetValidTime ()); + context->SetContextPrefix ((*jt).GetContextPrefix ()); + } + } + } + else // Old information, not updating + { + return; + } + + uint32_t t = raHeader.GetLifeTime (); + + for (std::list::iterator it = prefixList.begin (); it != prefixList.end (); it++) + { + t = t < ((*it).GetValidTime ()) ? t : ((*it).GetValidTime ()); + } + for (std::list::iterator jt = contextList.begin (); jt != contextList.end (); jt++) + { + t = (60 * ((*jt).GetValidTime ())) < t ? (60 * ((*jt).GetValidTime ())) : t; + } + + t -= (60 * m_advance); + + Simulator::Schedule (Time (Seconds (t - 1)), &SixLowPanNdProtocol::SetReceivedRA, this, false); + Simulator::Schedule (Time (Seconds (t)), &SixLowPanNdProtocol::RetransmitRS, this, + interface->GetLinkLocalAddress ().GetAddress (), src, addr); +} +/// \todo da finire!! (controlla codice, controlla regTime) + +void SixLowPanNdProtocol::HandleSixLowPanDAC (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface) +{ + NS_LOG_FUNCTION (this << packet << src << dst << interface); + + Ptr sixDevice = DynamicCast (interface->GetDevice()); + NS_ASSERT_MSG (sixDevice != NULL, "SixLowPanNdProtocol cannot be installed on device different from SixLowPanNetDevice"); + + Icmpv6DuplicateAddress dacHdr (0); + packet->RemoveHeader (dacHdr); + + if (m_multihopDad) + { + Ipv6Address reg = dacHdr.GetRegAddress (); + + if (!reg.IsMulticast () && src != Ipv6Address::GetAny () && !src.IsMulticast ()) + { + Ptr cache = FindSixLowPanCache (sixDevice); + SixLowPanNdiscCache::SixLowPanEntry* entry = 0; + entry = cache->SixLowPanLookup (reg); + + if (dacHdr.GetStatus () == 0) /* mark the entry as registered, send ARO with status=0 */ + { + entry->MarkRegistered (dacHdr.GetRegTime ()); + + SendSixLowPanARO (dst, dacHdr.GetRegAddress (), dacHdr.GetStatus (), dacHdr.GetRegTime (), + dacHdr.GetEui64 ()); + } + else /* remove the tentative entry, send ARO with error code */ + { + cache->SixLowPanRemove (entry); + + Ipv6Address address = sixDevice->MakeLinkLocalAddressFromMac (dacHdr.GetEui64 ()); + + SendSixLowPanARO (dst, address, dacHdr.GetStatus (), dacHdr.GetRegTime (), dacHdr.GetEui64 ()); + } + } + else + { + NS_LOG_ERROR ("Validity checks for DAR not satisfied."); + return; + } + } +} + +Ptr SixLowPanNdProtocol::FindSixLowPanCache (Ptr device) +{ + NS_LOG_FUNCTION (this << device); + + for (SixLowPanCacheList::const_iterator it = m_sixlowCList.begin (); it != m_sixlowCList.end (); it++) + { + if ((*it)->GetDevice () == device) + { + return *it; + } + } + + /* quiet compiler */ + return 0; +} + +void SixLowPanNdProtocol::RetransmitARO (Ipv6Address src, Ipv6Address dst, uint16_t time, + Mac64Address eui, Address linkAddr) +{ + NS_LOG_FUNCTION (this << src << dst << time << eui << linkAddr); + + IntegerValue maxUnicastSolicit; + GetAttribute ("MaxUnicastSolicit", maxUnicastSolicit); + if (m_aroRetransmit < maxUnicastSolicit.Get ()) + { + m_aroRetransmit++; + + SendSixLowPanARO (src, dst, time, eui, linkAddr); + + TimeValue retransmissionTime; + GetAttribute ("RetransmissionTime", retransmissionTime); + + Simulator::Schedule (retransmissionTime.Get (), &SixLowPanNdProtocol::RetransmitARO, this, + src, dst, time, eui, linkAddr); + return; + } + else + { + return; + } +} + +void SixLowPanNdProtocol::RetransmitRS (Ipv6Address src, Ipv6Address dst, Address linkAddr) +{ + NS_LOG_FUNCTION (this << src << dst << linkAddr); + + /* if the source is NOT unspec, send a RS message + SLLA option */ + if (src != Ipv6Address::GetAny ()) + { + if (!m_receivedRA && m_rsRetransmit < MAX_RTR_SOLICITATIONS) + { + m_rsRetransmit++; + + SendRS (src, dst, linkAddr); + + Simulator::Schedule (Time (Seconds (RTR_SOLICITATION_INTERVAL)), &SixLowPanNdProtocol::RetransmitRS, this, + src, dst, linkAddr); + return; + } + else if (!m_receivedRA) + { + m_rsRetransmit++; + + Ipv6Address destination = Ipv6Address::GetAllRoutersMulticast (); + + SendRS (src, destination, linkAddr); + + Simulator::Schedule (Time (Seconds (MAX_RTR_SOLICITATION_INTERVAL)), &SixLowPanNdProtocol::RetransmitRS, this, + src, destination, linkAddr); + /* inserire truncated binary exponential backoff */ + return; + } + else + { + return; + } + } + else + { + NS_LOG_ERROR ("An unspecified source address MUST NOT be used in RS messages."); + return; + } +} +/// \todo da finire!! (truncated binary exponential backoff) + +void SixLowPanNdProtocol::SetReceivedRA (bool received) +{ + NS_LOG_FUNCTION (this << received); + m_receivedRA = received; +} + +} /* namespace ns3 */ diff --git a/src/sixlowpan/model/sixlowpan-nd-protocol.h b/src/sixlowpan/model/sixlowpan-nd-protocol.h new file mode 100644 index 000000000..237c6e2b2 --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-nd-protocol.h @@ -0,0 +1,307 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#ifndef SIXLOWPAN_ND_PROTOCOL_H +#define SIXLOWPAN_ND_PROTOCOL_H + +#include "ns3/ipv6-address.h" +#include "ns3/mac64-address.h" +#include "ns3/ip-l4-protocol.h" +#include "ns3/icmpv6-l4-protocol.h" + +#include "sixlowpan-ndisc-cache.h" + +namespace ns3 { + +/** + * \ingroup sixlowpan + * \class SixLowPanNdProtocol + * \brief An optimization of the ND protocol for 6LoWPANs. + */ +class SixLowPanNdProtocol : public Icmpv6L4Protocol +{ +public: + /** + * \brief 6LBR constants : min context change delay. + */ + static const uint16_t MIN_CONTEXT_CHANGE_DELAY; + + /** + * \brief 6LR constants : max RA transmission. + */ + static const uint8_t MAX_RTR_ADVERTISEMENTS; + + /** + * \brief 6LR constants : min delay between RA. + */ + static const uint8_t MIN_DELAY_BETWEEN_RAS; + + /** + * \brief 6LR constants : max delay between RA. + */ + static const uint8_t MAX_RA_DELAY_TIME; + + /** + * \brief 6LR constants : tentative neighbor cache entry lifetime. + */ + static const uint8_t TENTATIVE_NCE_LIFETIME; + + /** + * \brief router constants : multihop hoplimit. + */ + static const uint8_t MULTIHOP_HOPLIMIT; + + /** + * \brief host constants : RS interval. + */ + static const uint8_t RTR_SOLICITATION_INTERVAL; + + /** + * \brief host constants : max RS transmission. + */ + static const uint8_t MAX_RTR_SOLICITATIONS; + + /** + * \brief host constants : max RS interval. + */ + static const uint8_t MAX_RTR_SOLICITATION_INTERVAL; + + /** + * \brief Constructor. + */ + SixLowPanNdProtocol (); + + /** + * \brief Destructor. + */ + virtual ~SixLowPanNdProtocol (); + + /** + * \brief Interface ID + */ + static TypeId GetTypeId (); + + /** + * \brief Forge a Neighbor Advertisement. + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param target target IPv6 address + * \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, Ipv6Address target, Address hardwareAddress, uint8_t flags); + + /** + * \brief Send a NS for 6LoWPAN ND (+ SLLAO). + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param target target IPv6 address + * \param linkAddr link-layer address (SLLAO) + */ + virtual void SendNS (Ipv6Address src, Ipv6Address dst, Ipv6Address target, Address linkAddr); + + /** + * \brief Send a NS for 6LoWPAN ND (+ ARO, SLLAO). + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param time registration lifetime (ARO) + * \param eui EUI-64 (ARO) + * \param linkAddr link-layer address (SLLAO) + */ + void SendSixLowPanARO (Ipv6Address src, Ipv6Address dst, uint16_t time, Mac64Address eui, + Address linkAddr); + + /** + * \brief Send a NA for 6LoWPAN ND (+ ARO). + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param status status (ARO) + * \param time registration lifetime (ARO) + * \param eui EUI-64 (ARO) + */ + void SendSixLowPanARO (Ipv6Address src, Ipv6Address dst, uint8_t status, uint16_t time, + Mac64Address eui); + + /** + * \brief Send a RA for 6LoWPAN ND (+ PIO, 6CO, ABRO, SLLAO). + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param interface the interface from which the packet will be sent + */ + void SendSixLowPanRA (Ipv6Address src, Ipv6Address dst, Ptr interface); + + /** + * \brief Send a DAR for 6LoWPAN ND. + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param time registration lifetime + * \param eui EUI-64 + * \param registered registered IPv6 address + */ + void SendSixLowPanDAR (Ipv6Address src, Ipv6Address dst, uint16_t time, Mac64Address eui, + Ipv6Address registered); + + /** + * \brief Receive method. + * \param p the packet + * \param header the IPv6 header + * \param interface the interface from which the packet is coming + * \returns the receive status + */ + virtual enum IpL4Protocol::RxStatus Receive (Ptr p, + Ipv6Header const &header, + Ptr interface); + + /** + * \brief Get the cache corresponding to the device. + * \param device the device + * \returns the SixLowPanNdiscCache associated with the device + */ + Ptr FindSixLowPanCache (Ptr device); + + /** + * \brief Function called to send NS + ARO + SLLAO. + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param time registration lifetime (ARO) + * \param eui EUI-64 (ARO) + * \param linkAddr link-layer address (SLLAO) + */ + void RetransmitARO (Ipv6Address src, Ipv6Address dst, uint16_t time, Mac64Address eui, + Address linkAddr); + + /** + * \brief Function called to send RS + SLLAO. + * \param src source IPv6 address + * \param dst destination IPv6 address + * \param linkAddress link-layer address (SLLAO) + */ + void RetransmitRS (Ipv6Address src, Ipv6Address dst, Address linkAddr); + +protected: + /** + * \brief Dispose this object. + */ + virtual void DoDispose (); + +private: + typedef std::list > SixLowPanCacheList; //!< container of SixLowPanNdiscCaches + + /** + * \brief A list of cache by device. + */ + SixLowPanCacheList m_sixlowCList; + + /** + * \brief Use multihop DAD mechanism + */ + bool m_multihopDad; + + /** + * \brief Number of RS retransmission. + */ + uint8_t m_rsRetransmit; + + /** + * \brief Is an RA received. + */ + bool m_receivedRA; + + /** + * \brief Number of NS + ARO + SLLAO retransmission. + */ + uint8_t m_aroRetransmit; + + /** + * \brief The amount of time (units of 60 seconds) that the router should retain the NCE for the node. + */ + uint16_t m_regTime; + + /** + * \brief The advance to perform maintaining of RA's information and registration. + */ + uint16_t m_advance; + + /** + * \brief Is a 6LoWPAN Border router. + */ + bool m_border; + + /** + * \brief Receive NS for 6LoWPAN ND method. + * \param p the packet + * \param src source address + * \param dst destination address + * \param interface the interface from which the packet is coming + */ + void HandleSixLowPanNS (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface); + + /** + * \brief Receive NA for 6LoWPAN ND method. + * \param p the packet + * \param src source address + * \param dst destination address + * \param interface the interface from which the packet is coming + */ + void HandleSixLowPanNA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface); + + /** + * \brief Receive RS for 6LoWPAN ND method. + * \param p the packet + * \param src source address + * \param dst destination address + * \param interface the interface from which the packet is coming + */ + void HandleSixLowPanRS (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface); + + /** + * \brief Receive RA for 6LoWPAN ND method. + * \param p the packet + * \param src source address + * \param dst destination address + * \param interface the interface from which the packet is coming + */ + void HandleSixLowPanRA (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface); + + /** + * \brief Receive DAC for 6LoWPAN ND method. + * \param p the packet + * \param src source address + * \param dst destination address + * \param interface the interface from which the packet is coming + */ + void HandleSixLowPanDAC (Ptr packet, Ipv6Address const &src, Ipv6Address const &dst, + Ptr interface); + + /** + * \brief Set the m_receivedRA flag. + * \param received value + */ + void SetReceivedRA (bool received); +}; + +} /* namespace ns3 */ + +#endif diff --git a/src/sixlowpan/model/sixlowpan-ndisc-cache.cc b/src/sixlowpan/model/sixlowpan-ndisc-cache.cc new file mode 100644 index 000000000..1ed5df3f3 --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-ndisc-cache.cc @@ -0,0 +1,545 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#include "ns3/log.h" +#include "ns3/uinteger.h" +#include "ns3/names.h" +#include "ns3/ipv6-address.h" +#include "ns3/mac64-address.h" + +#include "sixlowpan-ndisc-cache.h" +#include "sixlowpan-nd-protocol.h" +#include "sixlowpan-ndisc-ra-options.h" + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE ("SixLowPanNdiscCache"); + +NS_OBJECT_ENSURE_REGISTERED (SixLowPanNdiscCache); + +TypeId SixLowPanNdiscCache::GetTypeId () +{ + static TypeId tid = TypeId ("ns3::SixLowPanNdiscCache") + .SetParent () + .SetGroupName ("SixLowPan") + ; + return tid; +} + +SixLowPanNdiscCache::SixLowPanNdiscCache () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +SixLowPanNdiscCache::~SixLowPanNdiscCache () +{ + NS_LOG_FUNCTION_NOARGS (); + Flush (); +} + +void SixLowPanNdiscCache::DoDispose () +{ + NS_LOG_FUNCTION_NOARGS (); + + Flush (); + FlushRaCache (); + NdiscCache::DoDispose(); +} + +SixLowPanNdiscCache::SixLowPanEntry* SixLowPanNdiscCache::SixLowPanLookup (Ipv6Address dst) +{ + NS_LOG_FUNCTION (this << dst); + SixLowPanNdiscCache::SixLowPanEntry* entry; + + if (m_sixlowNdCache.find (dst) != m_sixlowNdCache.end ()) + { + entry = m_sixlowNdCache[dst]; + } + else + { + entry = 0; + } + return entry; +} + +SixLowPanNdiscCache::SixLowPanEntry* SixLowPanNdiscCache::SixLowPanAdd (Ipv6Address to) +{ + NS_LOG_FUNCTION (this << to); + NS_ASSERT (m_sixlowNdCache.find (to) == m_sixlowNdCache.end ()); + + SixLowPanNdiscCache::SixLowPanEntry* entry = new SixLowPanNdiscCache::SixLowPanEntry (this); + entry->SetIpv6Address (to); + m_sixlowNdCache[to] = entry; + return entry; +} + +void SixLowPanNdiscCache::SixLowPanRemove (SixLowPanNdiscCache::SixLowPanEntry* entry) +{ + NS_LOG_FUNCTION_NOARGS (); + + for (SixLowPanCacheI i = m_sixlowNdCache.begin (); i != m_sixlowNdCache.end (); i++) + { + if ((*i).second == entry) + { + m_sixlowNdCache.erase (i); + entry->ClearWaitingPacket (); + delete entry; + return; + } + } +} + +void SixLowPanNdiscCache::Flush () +{ + NS_LOG_FUNCTION_NOARGS (); + + for (SixLowPanCacheI i = m_sixlowNdCache.begin (); i != m_sixlowNdCache.end (); i++) + { + delete (*i).second; + } + + m_sixlowNdCache.erase (m_sixlowNdCache.begin (), m_sixlowNdCache.end ()); +} + +void SixLowPanNdiscCache::PrintNdiscCache (Ptr stream) +{ + NS_LOG_FUNCTION (this << stream); + std::ostream* os = stream->GetStream (); + + for (SixLowPanCacheI i = m_sixlowNdCache.begin (); i != m_sixlowNdCache.end (); i++) + { + *os << i->first << " dev "; + std::string found = Names::FindName (GetDevice ()); + if (Names::FindName (GetDevice ()) != "") + { + *os << found; + } + else + { + *os << static_cast (GetDevice ()->GetIfIndex ()); + } + + *os << " lladdr " << i->second->GetMacAddress (); + + if (i->second->IsReachable ()) + { + *os << " REACHABLE "; + } + else if (i->second->IsDelay ()) + { + *os << " DELAY "; + } + else if (i->second->IsIncomplete ()) + { + *os << " INCOMPLETE "; + } + else if (i->second->IsProbe ()) + { + *os << " PROBE "; + } + else + { + *os << " STALE "; + } + + if (i->second->IsRegistered ()) + { + *os << " REGISTERED\n"; + } + else if (i->second->IsTentative ()) + { + *os << " TENTATIVE\n"; + } + else + { + *os << " GARBAGE\n"; + } + } +} + +SixLowPanNdiscCache::SixLowPanEntry::SixLowPanEntry (NdiscCache* nd) + : NdiscCache::Entry::Entry (nd), + m_registeredTimer (Timer::CANCEL_ON_DESTROY), + m_tentativeTimer (Timer::CANCEL_ON_DESTROY) +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void SixLowPanNdiscCache::SixLowPanEntry::MarkRegistered (uint16_t time) +{ + NS_LOG_FUNCTION_NOARGS (); + m_type = REGISTERED; + + if (m_registeredTimer.IsRunning ()) + { + m_registeredTimer.Cancel (); + } + m_registeredTimer.SetFunction (&SixLowPanNdiscCache::SixLowPanEntry::FunctionTimeout, this); + m_registeredTimer.SetDelay (Minutes (time)); + m_registeredTimer.Schedule (); +} + +void SixLowPanNdiscCache::SixLowPanEntry::MarkTentative () +{ + NS_LOG_FUNCTION_NOARGS (); + m_type = TENTATIVE; + + if (m_tentativeTimer.IsRunning ()) + { + m_tentativeTimer.Cancel (); + } + m_tentativeTimer.SetFunction (&SixLowPanNdiscCache::SixLowPanEntry::FunctionTimeout, this); + m_tentativeTimer.SetDelay (Seconds (SixLowPanNdProtocol::TENTATIVE_NCE_LIFETIME)); + m_tentativeTimer.Schedule (); +} + +void SixLowPanNdiscCache::SixLowPanEntry::MarkGarbage () +{ + NS_LOG_FUNCTION_NOARGS (); + m_type = GARBAGE; +} + +bool SixLowPanNdiscCache::SixLowPanEntry::IsRegistered () const +{ + NS_LOG_FUNCTION_NOARGS (); + return (m_type == REGISTERED); +} + +bool SixLowPanNdiscCache::SixLowPanEntry::IsTentative () const +{ + NS_LOG_FUNCTION_NOARGS (); + return (m_type == TENTATIVE); +} + +bool SixLowPanNdiscCache::SixLowPanEntry::IsGarbage () const +{ + NS_LOG_FUNCTION_NOARGS (); + return (m_type == GARBAGE); +} + +void SixLowPanNdiscCache::SixLowPanEntry::FunctionTimeout () +{ + NS_LOG_FUNCTION_NOARGS (); + + m_ndCache->Remove (this); + return; +} + +Mac64Address SixLowPanNdiscCache::SixLowPanEntry::GetEui64 () const +{ + NS_LOG_FUNCTION (this); + return m_eui64; +} + +void SixLowPanNdiscCache::SixLowPanEntry::SetEui64 (Mac64Address eui) +{ + NS_LOG_FUNCTION (this << eui); + m_eui64 = eui; +} + +SixLowPanNdiscCache::SixLowPanRaEntry* SixLowPanNdiscCache::RaEntryLookup (Ipv6Address border) +{ + NS_LOG_FUNCTION (this << border); + SixLowPanNdiscCache::SixLowPanRaEntry* entry = 0; + + if (m_raCache.find (border) != m_raCache.end ()) + { + entry = m_raCache[border]; + } + return entry; +} + +SixLowPanNdiscCache::SixLowPanRaEntry* SixLowPanNdiscCache::AddRaEntry (Ipv6Address border) +{ + NS_LOG_FUNCTION (this << border); + NS_ASSERT (m_raCache.find (border) == m_raCache.end ()); + + SixLowPanNdiscCache::SixLowPanRaEntry* entry = new SixLowPanNdiscCache::SixLowPanRaEntry (this); + entry->SetBorderAddress (border); + m_raCache[border] = entry; + return entry; +} + +void SixLowPanNdiscCache::RemoveRaEntry (SixLowPanNdiscCache::SixLowPanRaEntry* entry) +{ + NS_LOG_FUNCTION_NOARGS (); + + for (SixLowPanRaCacheI it = m_raCache.begin (); it != m_raCache.end (); it++) + { + if ((*it).second == entry) + { + m_raCache.erase (it); + delete entry; + return; + } + } +} + +void SixLowPanNdiscCache::FlushRaCache () +{ + NS_LOG_FUNCTION_NOARGS (); + + for (SixLowPanRaCacheI it = m_raCache.begin (); it != m_raCache.end (); it++) + { + delete (*it).second; + } + + m_raCache.erase (m_raCache.begin (), m_raCache.end ()); +} + +void SixLowPanNdiscCache::PrintRaCache (Ptr stream) +{ + NS_LOG_FUNCTION (this << stream); + std::ostream* os = stream->GetStream (); + + for (SixLowPanRaCacheI it = m_raCache.begin (); it != m_raCache.end (); it++) + { + *os << it->first << " RA "; + + *os << " Cur Hop Limit: " << it->second->GetCurHopLimit (); + + if (it->second->IsManagedFlag ()) + { + *os << " M flag: true "; + } + else + { + *os << " M flag: false "; + } + if (it->second->IsOtherConfigFlag ()) + { + *os << " O flag: true "; + } + else + { + *os << " O flag: false "; + } + + *os << " Router Lifetime: " << it->second->GetRouterLifeTime (); + *os << " Reachable Time: " << it->second->GetReachableTime (); + *os << " Retrans Timer: " << it->second->GetRetransTimer (); + *os << " (ABRO) Version: " << it->second->GetVersion (); + *os << " (ABRO) Valid Lifetime: " << it->second->GetValidTime (); + *os << " (ABRO) Border Router address: " << it->second->GetBorderAddress (); + + std::map > prefixes = it->second->GetPrefixes (); + for (std::map >::iterator jt = prefixes.begin (); jt != prefixes.end (); jt++) + { + jt->second->PrintPrefix (stream); + } + std::map > contexts = it->second->GetContexts (); + for (std::map >::iterator i = contexts.begin (); i != contexts.end (); i++) + { + i->second->PrintContext (stream); + } + } +} + +std::map SixLowPanNdiscCache::GetRaCache () const +{ + NS_LOG_FUNCTION (this); + return m_raCache; +} + +SixLowPanNdiscCache::SixLowPanRaEntry::SixLowPanRaEntry (SixLowPanNdiscCache* nd) + //: m_cache (nd) +{ + NS_LOG_FUNCTION (this); +} + +SixLowPanNdiscCache::SixLowPanRaEntry::~SixLowPanRaEntry () +{ + NS_LOG_FUNCTION (this); +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::AddPrefix (Ptr prefix) +{ + NS_LOG_FUNCTION (this << prefix); + m_prefixes.insert (std::pair > (prefix->GetPrefix (), prefix)); +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::RemovePrefix (Ptr prefix) +{ + NS_LOG_FUNCTION_NOARGS (); + + for (std::map >::iterator it = m_prefixes.begin (); it != m_prefixes.end (); it++) + { + if (it->second == prefix) + { + m_prefixes.erase (it); + return; + } + } +} + +std::map > SixLowPanNdiscCache::SixLowPanRaEntry::GetPrefixes () const +{ + NS_LOG_FUNCTION (this); + return m_prefixes; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::AddContext (Ptr context) +{ + NS_LOG_FUNCTION (this << context); + m_contexts.insert (std::pair > (context->GetCid (), context)); +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::RemoveContext (Ptr context) +{ + NS_LOG_FUNCTION_NOARGS (); + + for (std::map >::iterator it = m_contexts.begin (); it != m_contexts.end (); it++) + { + if (it->second == context) + { + m_contexts.erase (it); + return; + } + } +} + +std::map > SixLowPanNdiscCache::SixLowPanRaEntry::GetContexts () const +{ + NS_LOG_FUNCTION (this); + return m_contexts; +} + +bool SixLowPanNdiscCache::SixLowPanRaEntry::IsManagedFlag () const +{ + NS_LOG_FUNCTION (this); + return m_managedFlag; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetManagedFlag (bool managedFlag) +{ + NS_LOG_FUNCTION (this << managedFlag); + m_managedFlag = managedFlag; +} + +bool SixLowPanNdiscCache::SixLowPanRaEntry::IsOtherConfigFlag () const +{ + NS_LOG_FUNCTION (this); + return m_otherConfigFlag; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetOtherConfigFlag (bool otherConfigFlag) +{ + NS_LOG_FUNCTION (this << otherConfigFlag); + m_otherConfigFlag = otherConfigFlag; +} + +bool SixLowPanNdiscCache::SixLowPanRaEntry::IsHomeAgentFlag () const +{ + NS_LOG_FUNCTION (this); + return m_homeAgentFlag; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetHomeAgentFlag (bool homeAgentFlag) +{ + NS_LOG_FUNCTION (this << homeAgentFlag); + m_homeAgentFlag = homeAgentFlag; +} + +uint32_t SixLowPanNdiscCache::SixLowPanRaEntry::GetReachableTime () const +{ + NS_LOG_FUNCTION (this); + return m_reachableTime; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetReachableTime (uint32_t time) +{ + NS_LOG_FUNCTION (this << time); + m_reachableTime = time; +} + +uint32_t SixLowPanNdiscCache::SixLowPanRaEntry::GetRouterLifeTime () const +{ + NS_LOG_FUNCTION (this); + return m_routerLifeTime; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetRouterLifeTime (uint32_t time) +{ + NS_LOG_FUNCTION (this << time); + m_routerLifeTime = time; +} + +uint32_t SixLowPanNdiscCache::SixLowPanRaEntry::GetRetransTimer () const +{ + NS_LOG_FUNCTION (this); + return m_retransTimer; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetRetransTimer (uint32_t timer) +{ + NS_LOG_FUNCTION (this << timer); + m_retransTimer = timer; +} + +uint8_t SixLowPanNdiscCache::SixLowPanRaEntry::GetCurHopLimit () const +{ + NS_LOG_FUNCTION (this); + return m_curHopLimit; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetCurHopLimit (uint8_t curHopLimit) +{ + NS_LOG_FUNCTION (this << curHopLimit); + m_curHopLimit = curHopLimit; +} + +uint32_t SixLowPanNdiscCache::SixLowPanRaEntry::GetVersion () const +{ + NS_LOG_FUNCTION (this); + return m_version; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetVersion (uint32_t version) +{ + NS_LOG_FUNCTION (this << version); + m_version = version; +} + +uint16_t SixLowPanNdiscCache::SixLowPanRaEntry::GetValidTime () const +{ + NS_LOG_FUNCTION (this); + return m_validTime; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetValidTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_validTime = time; +} + +Ipv6Address SixLowPanNdiscCache::SixLowPanRaEntry::GetBorderAddress () const +{ + NS_LOG_FUNCTION (this); + return m_border; +} + +void SixLowPanNdiscCache::SixLowPanRaEntry::SetBorderAddress (Ipv6Address border) +{ + NS_LOG_FUNCTION (this << border); + m_border = border; +} + +} /* namespace ns3 */ diff --git a/src/sixlowpan/model/sixlowpan-ndisc-cache.h b/src/sixlowpan/model/sixlowpan-ndisc-cache.h new file mode 100644 index 000000000..91862682a --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-ndisc-cache.h @@ -0,0 +1,512 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#ifndef SIXLOW_NDISC_CACHE_H +#define SIXLOW_NDISC_CACHE_H + +#include "ns3/ipv6-address.h" +#include "ns3/mac64-address.h" +#include "ns3/ptr.h" +#include "ns3/timer.h" +#include "ns3/sgi-hashmap.h" +#include "ns3/output-stream-wrapper.h" +#include "ns3/ndisc-cache.h" + +// #include "sixlow-ndisc-ra-options.h" + +namespace ns3 +{ + +class SixLowPanPrefix; +class SixLowPanContext; + +/** + * \infroup sixlowpan + * \class SixLowPanNdiscCache + * \brief Neighbor Discovery cache for 6LoWPAN ND. Keeps also RAs, prefixes and contexts. + */ +class SixLowPanNdiscCache : public NdiscCache +{ +public: + class SixLowPanEntry; + + class SixLowPanRaEntry; + + /** + * \brief Get the type ID + * \return type ID + */ + static TypeId GetTypeId (); + + /** + * \brief Constructor. + */ + SixLowPanNdiscCache (); + + /** + * \brief Destructor. + */ + ~SixLowPanNdiscCache (); + + /** + * \brief Lookup in the cache. + * \param dst destination address + * \return the entry if found, 0 otherwise + */ + SixLowPanNdiscCache::SixLowPanEntry* SixLowPanLookup (Ipv6Address dst); + + /** + * \brief Add an entry. + * \param to address to add + * \return an new Entry + */ + SixLowPanNdiscCache::SixLowPanEntry* SixLowPanAdd (Ipv6Address to); + + /** + * \brief Delete an entry. + * \param entry pointer to delete from the list. + */ + void SixLowPanRemove (SixLowPanNdiscCache::SixLowPanEntry* entry); + + /** + * \brief Flush the cache. + */ + virtual void Flush (); + + /** + * \brief Print the SixLowPanNdisc cache entries + * + * \param stream the ostream the SixLowPanNdisc cache entries is printed to + */ + virtual void PrintNdiscCache (Ptr stream); + + /** + * \class SixLowPanEntry + * \brief A record that holds information about an SixLowPanNdiscCache entry. + */ + class SixLowPanEntry : public NdiscCache::Entry + { + public: + /** + * \brief Constructor. + * \param nd The NdiscCache this entry belongs to. + */ + SixLowPanEntry (NdiscCache* nd); + + /** + * \brief Changes the state to this entry to REGISTERED. + * It starts the registered timer. + * \param time the lifetime in units of 60 seconds (from ARO) + */ + void MarkRegistered (uint16_t time); + + /** + * \brief Changes the state to this entry to TENTATIVE. + * It starts the tentative timer (20 seconds). + */ + void MarkTentative (); + + /** + * \brief Change the state to this entry to GARBAGE. + */ + void MarkGarbage (); + + /** + * \brief Is the entry REGISTERED. + * \return true if the type of entry is REGISTERED, false otherwise + */ + bool IsRegistered () const; + + /** + * \brief Is the entry TENTATIVE. + * \return true if the type of entry is TENTATIVE, false otherwise + */ + bool IsTentative () const; + + /** + * \brief Is the entry GARBAGE-COLLECTIBLE. + * \return true if the type of entry GARBAGE-COLLECTIBLE, false otherwise + */ + bool IsGarbage () const; + + /** + * \brief Function called when timer timeout. + */ + void FunctionTimeout (); + + /** + * \brief Get the EUI-64 of this entry. + * \return EUI-64 value + */ + Mac64Address GetEui64 () const; + + /** + * \brief Set the EUI-64. + * \param eui the EUI-64 value + */ + void SetEui64 (Mac64Address eui); + + private: + /** + * \brief The SixLowPanEntry type enumeration. + */ + enum SixLowPanNdiscCacheEntryType_e + { + REGISTERED, /**< Have an explicit registered lifetime */ + TENTATIVE, /**< Have a short lifetime, typically get converted to REGISTERED */ + GARBAGE /**< Allow for garbage collection when low on memory */ + }; + + /** + * \brief The EUI-64 value. + */ + Mac64Address m_eui64; + + /** + * \brief The state of the entry. + */ + SixLowPanNdiscCacheEntryType_e m_type; + + /** + * \brief Timer (used for REGISTERED entries). + */ + Timer m_registeredTimer; + + /** + * \brief Timer (used for TENTATIVE entries). + */ + Timer m_tentativeTimer; + }; + + /** + * \brief Lookup in the RA cache. + * \param border the Border Router address + * \return the entry if found, 0 otherwise + */ + SixLowPanNdiscCache::SixLowPanRaEntry* RaEntryLookup (Ipv6Address border); + + /** + * \brief Add an entry to the RA cache. + * \param border the Border Router address + * \return a new SixLowPanContext + */ + SixLowPanNdiscCache::SixLowPanRaEntry* AddRaEntry (Ipv6Address border); + + /** + * \brief Delete an entry from the RA cache. + * \param entry pointer to delete from the list. + */ + void RemoveRaEntry (SixLowPanNdiscCache::SixLowPanRaEntry* entry); + + /** + * \brief Flush the RA cache. + */ + void FlushRaCache (); + + /** + * \brief Print the RA cache entries + * + * \param stream the ostream the RA cache entries is printed to + */ + void PrintRaCache (Ptr stream); + + /** + * \brief Get list of RA received. + * \return list of RA + */ + std::map GetRaCache () const; + + /** + * \class SixLowPanRaEntry + * \brief RA advertised from routers for 6LoWPAN ND. + */ + class SixLowPanRaEntry + { + public: + /** + * \brief Constructor. + * \param nd The NdiscCache this ra entry belongs to. + */ + SixLowPanRaEntry (SixLowPanNdiscCache* nd); + + /** + * \brief Destructor. + */ + ~SixLowPanRaEntry (); + + /** + * \brief Get list of prefixes advertised for this interface. + * \return list of IPv6 prefixes + */ + std::map > GetPrefixes () const; + + /** + * \brief Add a prefix to advertise on interface. + * \param prefix prefix to advertise + */ + void AddPrefix (Ptr prefix); + + /** + * \brief Remove a prefix. + * \param prefix prefix to remove + */ + void RemovePrefix (Ptr prefix); + + /** + * \brief Get list of 6LoWPAN contexts advertised for this interface. + * \return list of 6LoWPAN contexts + */ + std::map > GetContexts () const; + + /** + * \brief Add a 6LoWPAN context to advertise on interface. + * \param context 6LoWPAN context to advertise + */ + void AddContext (Ptr context); + + /** + * \brief Remove a 6LoWPAN context. + * \param context 6LoWPAN context to remove + */ + void RemoveContext (Ptr context); + + /** + * \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 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 Set "other config" flag + * \param otherConfigFlag value + */ + void SetOtherConfigFlag (bool otherConfigFlag); + + /** + * \brief Get reachable time. + * \return reachable time + */ + uint32_t GetReachableTime () const; + + /** + * \brief Set reachable time. + * \param time reachable time + */ + void SetReachableTime (uint32_t itme); + + /** + * \brief Get router lifetime. + * \return router lifetime + */ + uint32_t GetRouterLifeTime () const; + + /** + * \brief Set router lifetime. + * \param time router lifetime + */ + void SetRouterLifeTime (uint32_t time); + + /** + * \brief Get retransmission timer. + * \return retransmission timer + */ + uint32_t GetRetransTimer () const; + + /** + * \brief Set retransmission timer. + * \param timer retransmission timer + */ + void SetRetransTimer (uint32_t timer); + + /** + * \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 version value (ABRO). + * \return the version value + */ + uint32_t GetVersion () const; + + /** + * \brief Set version value (ABRO). + * \param version the version value + */ + void SetVersion (uint32_t version); + + /** + * \brief Get valid lifetime value (ABRO). + * \return the valid lifetime (units of 60 seconds) + */ + uint16_t GetValidTime () const; + + /** + * \brief Set valid lifetime value (ABRO). + * \param time the valid lifetime (units of 60 seconds) + */ + void SetValidTime (uint16_t time); + + /** + * \brief Get Border Router address (ABRO). + * \return the Border Router address + */ + Ipv6Address GetBorderAddress () const; + + /** + * \brief Set Border Router address (ABRO). + * \param border the Border Router address + */ + void SetBorderAddress (Ipv6Address border); + + private: + /** + * \brief List of prefixes advertised. + */ + std::map > m_prefixes; + + /** + * \brief List of 6LoWPAN contexts advertised. + */ + std::map > m_contexts; + + /** + * \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 Flag to add HA (home agent) flag in RA. + */ + bool m_homeAgentFlag; + + /** + * \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 Router life time in seconds. + */ + uint32_t m_routerLifeTime; + + /** + * \brief Version value for ABRO. + */ + uint32_t m_version; + + /** + * \brief Valid lifetime value for ABRO (units of 60 seconds). + */ + uint16_t m_validTime; + + /** + * \brief Border Router address for ABRO. + */ + Ipv6Address m_border; + }; + + protected: + /** + * \brief Dispose this object. + */ + virtual void DoDispose (); + + private: + /** + * \brief RA entry container + */ + typedef std::map SixLowPanRaCache; + + /** + * \brief RA entry container iterator + */ + typedef std::map::iterator SixLowPanRaCacheI; + + /** + * \brief A list of RA entry. + */ + SixLowPanRaCache m_raCache; + + /** + * \brief 6LoWPAN Neighbor Discovery Cache container + */ + typedef sgi::hash_map SixLowPanCache; + + /** + * \brief 6LoWPAN Neighbor Discovery Cache container iterator + */ + typedef sgi::hash_map::iterator SixLowPanCacheI; + + /** + * \brief A list of Entry. + */ + SixLowPanCache m_sixlowNdCache; +}; + +} /* namespace ns3 */ + +#endif /* SIXLOW_NDISC_CACHE_H */ diff --git a/src/sixlowpan/model/sixlowpan-ndisc-ra-options.cc b/src/sixlowpan/model/sixlowpan-ndisc-ra-options.cc new file mode 100644 index 000000000..2e4bf5dad --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-ndisc-ra-options.cc @@ -0,0 +1,287 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#include +#include "ns3/simulator.h" + +#include "sixlowpan-ndisc-ra-options.h" + + +namespace ns3 +{ + +NS_LOG_COMPONENT_DEFINE ("SixLowPanNdiscRaOptions"); + +SixLowPanPrefix::SixLowPanPrefix () +{ + NS_LOG_FUNCTION (this); +} + +SixLowPanPrefix::SixLowPanPrefix (Ipv6Address prefix, uint8_t prefixLen, uint32_t prefTime, uint32_t validTime, uint8_t flags) + : m_prefix (prefix), + m_prefixLength (prefixLen), + m_preferredLifeTime (prefTime), + m_validLifeTime (validTime), + m_flags (flags) +{ + NS_LOG_FUNCTION (this << prefix << prefixLen << prefTime << validTime << flags); + + m_setValidTime = Simulator::Now (); + m_setPrefTime = Simulator::Now (); +} + +SixLowPanPrefix::~SixLowPanPrefix () +{ + NS_LOG_FUNCTION (this); +} + +Ipv6Address SixLowPanPrefix::GetPrefix () const +{ + NS_LOG_FUNCTION (this); + return m_prefix; +} + +void SixLowPanPrefix::SetPrefix (Ipv6Address prefix) +{ + NS_LOG_FUNCTION (this << prefix); + m_prefix = prefix; +} + +uint8_t SixLowPanPrefix::GetPrefixLength () const +{ + NS_LOG_FUNCTION (this); + return m_prefixLength; +} + +void SixLowPanPrefix::SetPrefixLength (uint8_t prefixLen) +{ + NS_LOG_FUNCTION (this << prefixLen); + m_prefixLength = prefixLen; +} + +uint32_t SixLowPanPrefix::GetValidLifeTime () const +{ + NS_LOG_FUNCTION (this); + double time = Simulator::Now ().GetSeconds () - m_setValidTime.GetSeconds (); + + return m_validLifeTime - static_cast (time); +} + +void SixLowPanPrefix::SetValidLifeTime (uint32_t validTime) +{ + NS_LOG_FUNCTION (this << validTime); + m_validLifeTime = validTime; + + m_setValidTime = Simulator::Now (); +} + +uint32_t SixLowPanPrefix::GetPreferredLifeTime () const +{ + NS_LOG_FUNCTION (this); + double time = Simulator::Now ().GetSeconds () - m_setPrefTime.GetSeconds (); + + return m_preferredLifeTime - static_cast (time); +} + +void SixLowPanPrefix::SetPreferredLifeTime (uint32_t prefTime) +{ + NS_LOG_FUNCTION (this << prefTime); + m_preferredLifeTime = prefTime; + + m_setPrefTime = Simulator::Now (); +} + +uint8_t SixLowPanPrefix::GetFlags () const +{ + NS_LOG_FUNCTION (this); + return m_flags; +} + +void SixLowPanPrefix::SetFlags (uint8_t flags) +{ + NS_LOG_FUNCTION (this << flags); + m_flags = flags; +} + +void SixLowPanPrefix::PrintPrefix (Ptr stream) +{ + NS_LOG_FUNCTION (this << stream); + std::ostream* os = stream->GetStream (); + + *os << " Prefix Length: " << GetPrefixLength (); + + if (GetFlags () & (1 << 7)) + { + *os << " On-link flag: true "; + } + else + { + *os << " On-link flag: false "; + } + if (GetFlags () & (1 << 6)) + { + *os << " Autonomous flag: true "; + } + else + { + *os << " Autonomous flag: false "; + } + if (GetFlags () & (1 << 5)) + { + *os << " Router address flag: true "; + } + else + { + *os << " Router address flag: false "; + } + + *os << " Valid Lifetime: " << GetValidLifeTime (); + *os << " Preferred Lifetime: " << GetPreferredLifeTime (); + *os << " Prefix: " << GetPrefix (); +} + +SixLowPanContext::SixLowPanContext () +{ + NS_LOG_FUNCTION (this); +} + +SixLowPanContext::SixLowPanContext (bool flagC, uint8_t cid, uint16_t time, Ipv6Prefix context) + : m_c (flagC), + m_cid (cid), + m_validTime (time), + m_context (context) +{ + NS_LOG_FUNCTION (this << flagC << static_cast (cid) << time << context); + + m_setTime = Simulator::Now (); +} + +SixLowPanContext::~SixLowPanContext () +{ + NS_LOG_FUNCTION (this); +} + +uint8_t SixLowPanContext::GetContextLen () const +{ + NS_LOG_FUNCTION (this); + return m_length; +} + +void SixLowPanContext::SetContextLen (uint8_t length) +{ + NS_LOG_FUNCTION (this << static_cast (length)); + m_length = length; +} + +bool SixLowPanContext::IsFlagC () const +{ + NS_LOG_FUNCTION (this); + return m_c; +} + +void SixLowPanContext::SetFlagC (bool c) +{ + NS_LOG_FUNCTION (this << c); + m_c = c; +} + +uint8_t SixLowPanContext::GetCid () const +{ + NS_LOG_FUNCTION (this); + return m_cid; +} + +void SixLowPanContext::SetCid (uint8_t cid) +{ + NS_LOG_FUNCTION (this << static_cast (cid)); + NS_ASSERT (cid <= 15); + m_cid = cid; +} + +uint16_t SixLowPanContext::GetValidTime () const +{ + NS_LOG_FUNCTION (this); + + double time = Simulator::Now ().GetMinutes () - m_setTime.GetMinutes (); + + return m_validTime - static_cast (time); +} + +void SixLowPanContext::SetValidTime (uint16_t time) +{ + NS_LOG_FUNCTION (this << time); + m_validTime = time; + + m_setTime = Simulator::Now (); + + Simulator::Schedule (Time (Minutes (time)), &SixLowPanContext::ValidTimeout, this); +} + +Ipv6Prefix SixLowPanContext::GetContextPrefix () const +{ + NS_LOG_FUNCTION (this); + return m_context; +} + +void SixLowPanContext::SetContextPrefix (Ipv6Prefix context) +{ + NS_LOG_FUNCTION (this << context); + m_context = context; +} + +void SixLowPanContext::PrintContext (Ptr stream) +{ + NS_LOG_FUNCTION (this << stream); + std::ostream* os = stream->GetStream (); + + *os << " Context Length: " << GetContextLen (); + + if (IsFlagC ()) + { + *os << " Compression flag: true "; + } + else + { + *os << " Compression flag: false "; + } + + *os << " Context Identifier: " << GetCid (); + *os << " Valid Lifetime: " << GetValidTime (); + *os << " Context Prefix: " << GetContextPrefix (); +} + +void SixLowPanContext::ValidTimeout () +{ + NS_LOG_FUNCTION_NOARGS (); + + m_c = false; + + Simulator::Schedule (Time (Seconds (2 * 1000 /*m_entry->GetRouterLifeTime ()*/)), &SixLowPanContext::RouterTimeout, this); +} /// \todo da finire!!! + +void SixLowPanContext::RouterTimeout () +{ + NS_LOG_FUNCTION_NOARGS (); + + //m_entry->RemoveContext (this); + return; +} /// \todo da finire!!! + +} /* namespace ns3 */ diff --git a/src/sixlowpan/model/sixlowpan-ndisc-ra-options.h b/src/sixlowpan/model/sixlowpan-ndisc-ra-options.h new file mode 100644 index 000000000..cef4468af --- /dev/null +++ b/src/sixlowpan/model/sixlowpan-ndisc-ra-options.h @@ -0,0 +1,302 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2015 Università di Firenze, Italy + * + * 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: Alessio Bonadio + */ + +#ifndef SIXLOW_NDISC_RA_OPTIONS_H +#define SIXLOW_NDISC_RA_OPTIONS_H + +#include + +#include "ns3/nstime.h" +#include "ns3/ipv6-address.h" +#include "ns3/simple-ref-count.h" +#include "ns3/output-stream-wrapper.h" + +namespace ns3 +{ + +/** + * \ingroup sixlowpan + * \class SixLowPanPrefix + * \brief Router prefix container for 6LoWPAN ND. + */ +class SixLowPanPrefix : public SimpleRefCount +{ +public: + /** + * \brief Constructor. + */ + SixLowPanPrefix (); + + /** + * \brief Constructor. + * \param prefix network prefix advertised + * \param prefixLen prefix length ( 0 < x <= 128) + * \param prefTime preferred life time in seconds (default 7 days) + * \param validTime valid life time in seconds (default 30 days) + * \param flags the flags (L = 128, A = 64, R = 32) + */ + SixLowPanPrefix (Ipv6Address prefix, uint8_t prefixLen, uint32_t prefTime, uint32_t validTime, uint8_t flags); + + /** + * \brief Destructor. + */ + ~SixLowPanPrefix (); + + /** + * \brief Get network prefix. + * \return network prefix + */ + Ipv6Address GetPrefix () const; + + /** + * \brief Set network prefix. + * \param network network prefix + */ + void SetPrefix (Ipv6Address prefix); + + /** + * \brief Get prefix length. + * \return prefix length + */ + uint8_t GetPrefixLength () const; + + /** + * \brief Set prefix length. + * \param prefixLen prefix length + */ + void SetPrefixLength (uint8_t prefixLen); + + /** + * \brief Get preferred lifetime. + * \return lifetime + */ + uint32_t GetPreferredLifeTime () const; + + /** + * \brief Set preferred lifetime. + * \param prefTime lifetime + */ + void SetPreferredLifeTime (uint32_t prefTime); + + /** + * \brief Get valid lifetime. + * \return lifetime + */ + uint32_t GetValidLifeTime () const; + + /** + * \brief Set valid lifetime. + * \param validTime lifetime + */ + void SetValidLifeTime (uint32_t validTime); + + /** + * \brief Get the flags. + * \return the flags (L = 128, A = 64, R = 32) + */ + uint8_t GetFlags () const; + + /** + * \brief Set the flags. + * \param flags the flags to set (L = 128, A = 64, R = 32) + */ + void SetFlags (uint8_t flags); + + /** + * \brief Print the prefix + * \param stream the ostream the prefix is printed to + */ + void PrintPrefix (Ptr stream); + +private: + /** + * \brief Network prefix. + */ + Ipv6Address m_prefix; + + /** + * \brief Prefix length. + */ + uint8_t m_prefixLength; + + /** + * \brief Preferred time. + */ + uint32_t m_preferredLifeTime; + + /** + * \brief Valid time. + */ + uint32_t m_validLifeTime; + + /** + * \brief Flags. + */ + uint8_t m_flags; + + /** + * \brief Prefix valid lifetime set time. + */ + Time m_setValidTime; + + /** + * \brief Prefix preferred lifetime set time. + */ + Time m_setPrefTime; +}; + +/** + * \ingroup sixlowpan + * \class SixLowPanContext + * \brief 6LoWPAN context container for 6LoWPAN ND. + */ +class SixLowPanContext : public SimpleRefCount +{ +public: + /** + * \brief Constructor. + */ + SixLowPanContext (); + + /** + * \brief Constructor. + * \param flagC compression flag + * \param cid context identifier ( 0 <= x <= 15) + * \param time valid lifetime of context (units of 60 seconds) + * \param context 6LoWPAN context advertised + */ + SixLowPanContext (bool flagC, uint8_t cid, uint16_t time, Ipv6Prefix context); + + /** + * \brief Destructor. + */ + ~SixLowPanContext (); + + /** + * \brief Get the context length. + * \return context length value + */ + uint8_t GetContextLen () const; + + /** + * \brief Set the context length. + * \param length the context length value + */ + void SetContextLen (uint8_t length); + + /** + * \brief Is compression flag ? + * \return true if context is valid for use in compression, false otherwise + */ + bool IsFlagC () const; + + /** + * \brief Set the compression flag. + * \param c the compression flag + */ + void SetFlagC (bool c); + + /** + * \brief Get the context identifier. + * \return context identifier value + */ + uint8_t GetCid () const; + + /** + * \brief Set the context identifier. + * \param cid the context identifier value + */ + void SetCid (uint8_t cid); + + /** + * \brief Get the valid lifetime. + * \return valid lifetime value (units of 60 seconds) + */ + uint16_t GetValidTime () const; + + /** + * \brief Set the valid lifetime. + * \param time the valid lifetime value (units of 60 seconds) + */ + void SetValidTime (uint16_t time); + + /** + * \brief Get the 6LoWPAN context prefix. + * \return context prefix value + */ + Ipv6Prefix GetContextPrefix () const; + + /** + * \brief Set the 6LoWPAN context prefix. + * \param prefix the context prefix value + */ + void SetContextPrefix (Ipv6Prefix context); + + /** + * \brief Print the 6LoWPAN context. + * \param stream the ostream the 6LoWPAN context is printed to + */ + void PrintContext (Ptr stream); + + /** + * \brief Function called when valid lifetime timeout. + */ + void ValidTimeout (); + + /** + * \brief Function called when router lifetime timeout. + */ + void RouterTimeout (); + +private: + /** + * \brief The context length value. + */ + uint8_t m_length; + + /** + * \brief The compression flag, indicates that this context is valid for use in compression. + */ + bool m_c; + + /** + * \brief The context identifier value. + */ + uint8_t m_cid; + + /** + * \brief The valid lifetime value (units of 60 seconds). + */ + uint16_t m_validTime; + + /** + * \brief The context prefix value. + */ + Ipv6Prefix m_context; + + /** + * \brief Context set time. + */ + Time m_setTime; +}; + +} /* namespace ns3 */ + +#endif /* SIXLOW_NDISC_RA_OPTIONS_H */ diff --git a/src/sixlowpan/model/sixlowpan-net-device.h b/src/sixlowpan/model/sixlowpan-net-device.h index 9c880e7df..f39e8338e 100644 --- a/src/sixlowpan/model/sixlowpan-net-device.h +++ b/src/sixlowpan/model/sixlowpan-net-device.h @@ -145,6 +145,21 @@ public: */ int64_t AssignStreams (int64_t stream); + /** + * \brief Make a link-local address from a MAC address. + * \param [in] addr The MAC address. + * \return The IPv6 link-local address. + */ + Ipv6Address MakeLinkLocalAddressFromMac (Address const &addr); + + /** + * \brief Make a global address from a MAC address. + * \param [in] addr the MAC address. + * \param [in] prefix The address prefix. + * \return The IPv6 address. + */ + Ipv6Address MakeGlobalAddressFromMac (Address const &addr, Ipv6Address prefix); + /** * TracedCallback signature for packet send/receive events. * @@ -272,21 +287,6 @@ private: */ TracedCallback, Ptr, uint32_t> m_dropTrace; - /** - * \brief Make a link-local address from a MAC address. - * \param [in] addr The MAC address. - * \return The IPv6 link-local address. - */ - Ipv6Address MakeLinkLocalAddressFromMac (Address const &addr); - - /** - * \brief Make a global address from a MAC address. - * \param [in] addr the MAC address. - * \param [in] prefix The address prefix. - * \return The IPv6 address. - */ - Ipv6Address MakeGlobalAddressFromMac (Address const &addr, Ipv6Address prefix); - /** * \brief Compress the headers according to HC1 compression. * \param [in] packet The packet to be compressed. diff --git a/src/sixlowpan/wscript b/src/sixlowpan/wscript index b1d4b706d..e142dbd98 100644 --- a/src/sixlowpan/wscript +++ b/src/sixlowpan/wscript @@ -6,6 +6,10 @@ def build(bld): module.source = [ 'model/sixlowpan-net-device.cc', 'model/sixlowpan-header.cc', + 'model/sixlowpan-ndisc-cache.cc', + 'model/sixlowpan-ndisc-ra-options.cc', + 'model/sixlowpan-nd-header.cc', + 'model/sixlowpan-nd-protocol.cc', 'helper/sixlowpan-helper.cc', ] @@ -22,6 +26,10 @@ def build(bld): headers.source = [ 'model/sixlowpan-net-device.h', 'model/sixlowpan-header.h', + 'model/sixlowpan-ndisc-cache.h', + 'model/sixlowpan-ndisc-ra-options.h', + 'model/sixlowpan-nd-header.h', + 'model/sixlowpan-nd-protocol.h', 'helper/sixlowpan-helper.h', ]