Bug 1883 - IPv6 don't consider the prefix and network when choosing output address

This commit is contained in:
Tommaso Pecorella
2014-03-15 15:35:58 +01:00
parent fa320437c0
commit a2e81e7341
5 changed files with 58 additions and 16 deletions

View File

@@ -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
=============

View File

@@ -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<Ipv6> ()->GetNAddresses (m_ifIndex); i++)
{
src = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, i).GetAddress ();
Ipv6InterfaceAddress srcIa (src);
if ( srcIa.GetScope() == dstIa.GetScope() )
Ipv6InterfaceAddress srcIa;
srcIa = GetNode ()->GetObject<Ipv6> ()->GetAddress (m_ifIndex, i);
if (srcIa.IsInSameSubnet (m_peerAddress))
{
src = srcIa.GetAddress ();
break;
}
}

View File

@@ -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: ";

View File

@@ -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

View File

@@ -309,7 +309,7 @@ Ptr<Ipv6Route> Ipv6StaticRouting::LookupStatic (Ipv6Address dst, Ptr<NetDevice>
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;
}