diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 276b8f011..37ba611f1 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -50,6 +50,7 @@ Bugs fixed - Bug 1870 - Remove unnecessary AsInt functions - Bug 1874 - Ipv4L3Protocol::ProcessFragment: addressCombination and idProto identifiers not properly computed - Bug 1882 - int64x64 tests trigger valgrind bug +- Bug 1883 - IPv6 don't consider the prefix and network when choosing output address Release 3.19 ============= diff --git a/src/applications/model/ping6.cc b/src/applications/model/ping6.cc index c9a120407..4e66fad67 100644 --- a/src/applications/model/ping6.cc +++ b/src/applications/model/ping6.cc @@ -171,13 +171,14 @@ void Ping6::Send () /* hack to have ifIndex in Ipv6RawSocketImpl * maybe add a SetIfIndex in Ipv6RawSocketImpl directly */ - Ipv6InterfaceAddress dstIa (m_peerAddress); for (uint32_t i = 0; i < GetNode ()->GetObject ()->GetNAddresses (m_ifIndex); i++) { - src = GetNode ()->GetObject ()->GetAddress (m_ifIndex, i).GetAddress (); - Ipv6InterfaceAddress srcIa (src); - if ( srcIa.GetScope() == dstIa.GetScope() ) + Ipv6InterfaceAddress srcIa; + srcIa = GetNode ()->GetObject ()->GetAddress (m_ifIndex, i); + + if (srcIa.IsInSameSubnet (m_peerAddress)) { + src = srcIa.GetAddress (); break; } } diff --git a/src/internet/model/ipv6-interface-address.cc b/src/internet/model/ipv6-interface-address.cc index f928efc09..f0551a976 100644 --- a/src/internet/model/ipv6-interface-address.cc +++ b/src/internet/model/ipv6-interface-address.cc @@ -137,6 +137,29 @@ Ipv6InterfaceAddress::Scope_e Ipv6InterfaceAddress::GetScope () const return m_scope; } +bool Ipv6InterfaceAddress::IsInSameSubnet (Ipv6Address b) const +{ + NS_LOG_FUNCTION_NOARGS (); + + Ipv6Address aAddr = m_address; + aAddr = aAddr.CombinePrefix (m_prefix); + Ipv6Address bAddr = b; + bAddr = bAddr.CombinePrefix (m_prefix); + + if (aAddr == bAddr) + { + return true; + } + + if ((bAddr.IsLinkLocalMulticast () && aAddr.IsLinkLocal ()) || + (aAddr.IsLinkLocalMulticast () && bAddr.IsLinkLocal ())) + { + return true; + } + + return false; +} + std::ostream& operator<< (std::ostream& os, const Ipv6InterfaceAddress &addr) { os << "address: " << addr.GetAddress () << addr.GetPrefix () << "; scope: "; diff --git a/src/internet/model/ipv6-interface-address.h b/src/internet/model/ipv6-interface-address.h index 50b5b5832..061dbb70f 100644 --- a/src/internet/model/ipv6-interface-address.h +++ b/src/internet/model/ipv6-interface-address.h @@ -133,6 +133,13 @@ public: */ Ipv6InterfaceAddress::Scope_e GetScope () const; + /** + * \brief Checks if the address is in the same subnet. + * \param b the address to check + * \return true if the address is in the same subnet. + */ + bool IsInSameSubnet (Ipv6Address b) const; + /** * \brief Set the latest DAD probe packet UID. * \param uid packet uid diff --git a/src/internet/model/ipv6-static-routing.cc b/src/internet/model/ipv6-static-routing.cc index 0c6938963..19fae9754 100644 --- a/src/internet/model/ipv6-static-routing.cc +++ b/src/internet/model/ipv6-static-routing.cc @@ -309,7 +309,7 @@ Ptr Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr if (mask.IsMatch (dst, entry)) { - NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen << ", metric " << metric); + NS_LOG_LOGIC ("Found global network route " << *j << ", mask length " << maskLen << ", metric " << metric); /* if interface is given, check the route will output on this interface */ if (!interface || interface == m_ipv6->GetNetDevice (j->GetInterface ())) @@ -798,27 +798,37 @@ Ipv6Address Ipv6StaticRouting::SourceAddressSelection (uint32_t interface, Ipv6A NS_LOG_FUNCTION (this << interface << dest); Ipv6Address ret; - /* first address of an IPv6 interface is link-local ones */ - ret = m_ipv6->GetAddress (interface, 0).GetAddress (); - - if (dest == Ipv6Address::GetAllNodesMulticast () || dest == Ipv6Address::GetAllRoutersMulticast () || dest == Ipv6Address::GetAllHostsMulticast ()) + if (dest.IsLinkLocal () || dest.IsLinkLocalMulticast ()) { - return ret; + for (uint32_t i = 0; i < m_ipv6->GetNAddresses (interface); i++) + { + Ipv6InterfaceAddress test = m_ipv6->GetAddress (interface, i); + if (test.GetScope () == Ipv6InterfaceAddress::LINKLOCAL) + { + return test.GetAddress (); + } + } + NS_ASSERT_MSG (false, "No link-local address found on interface " << interface); } - /* usually IPv6 interfaces have one link-local address and one global address */ - - for (uint32_t i = 1; i < m_ipv6->GetNAddresses (interface); i++) + for (uint32_t i = 0; i < m_ipv6->GetNAddresses (interface); i++) { Ipv6InterfaceAddress test = m_ipv6->GetAddress (interface, i); - Ipv6InterfaceAddress dst(dest); - if (test.GetScope() == dst.GetScope()) + if (test.GetScope () == Ipv6InterfaceAddress::GLOBAL) { - return test.GetAddress (); + if (test.IsInSameSubnet (dest)) + { + return test.GetAddress (); + } + else + { + ret = test.GetAddress (); + } } } + // no specific match found. Use a global address (any useful is fine). return ret; }