[ip6] simplify SelectSourceAddress() (#8615)

This commit updates `Ip6::SelectSourceAddress()`. A new version of
is added which as its input gets a destination `Ip6::Address`
instead of an `Ip6::MessageInfo`, and returns the selected source
address as an `Ip6::Address *`. This helps simplify its use (no need
to create or pass `MessageInfo` instances). This commit also moves
the implementation of `otIp6SelectSourceAddress()` from `ip6_api.cpp`
to `Ip6` class adding a version of `SelectSourceAddress()` which
updates a passed-in `MessageInfo`directly.
This commit is contained in:
Abtin Keshavarzian
2023-01-05 16:44:39 -08:00
committed by GitHub
parent 28b40106b1
commit b64fab65cc
4 changed files with 88 additions and 85 deletions
+1 -9
View File
@@ -223,15 +223,7 @@ bool otIp6IsAddressUnspecified(const otIp6Address *aAddress) { return AsCoreType
otError otIp6SelectSourceAddress(otInstance *aInstance, otMessageInfo *aMessageInfo)
{
Error error = kErrorNone;
const Ip6::Netif::UnicastAddress *netifAddr;
netifAddr = AsCoreType(aInstance).Get<Ip6::Ip6>().SelectSourceAddress(AsCoreType(aMessageInfo));
VerifyOrExit(netifAddr != nullptr, error = kErrorNotFound);
aMessageInfo->mSockAddr = netifAddr->GetAddress();
exit:
return error;
return AsCoreType(aInstance).Get<Ip6::Ip6>().SelectSourceAddress(AsCoreType(aMessageInfo));
}
#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_TMF_PROXY_MLR_ENABLE && OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
+67 -64
View File
@@ -215,25 +215,23 @@ exit:
return error;
}
Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
Error Ip6::AddTunneledMplOption(Message &aMessage, Header &aHeader)
{
Error error = kErrorNone;
Header tunnelHeader;
const Netif::UnicastAddress *source;
MessageInfo messageInfo(aMessageInfo);
Error error = kErrorNone;
Header tunnelHeader;
const Address *source;
// Use IP-in-IP encapsulation (RFC2473) and ALL_MPL_FORWARDERS address.
messageInfo.GetPeerAddr().SetToRealmLocalAllMplForwarders();
tunnelHeader.InitVersionTrafficClassFlow();
tunnelHeader.SetHopLimit(static_cast<uint8_t>(kDefaultHopLimit));
tunnelHeader.SetPayloadLength(aHeader.GetPayloadLength() + sizeof(tunnelHeader));
tunnelHeader.SetDestination(messageInfo.GetPeerAddr());
tunnelHeader.GetDestination().SetToRealmLocalAllMplForwarders();
tunnelHeader.SetNextHeader(kProtoIp6);
VerifyOrExit((source = SelectSourceAddress(messageInfo)) != nullptr, error = kErrorInvalidSourceAddress);
source = SelectSourceAddress(tunnelHeader.GetDestination());
VerifyOrExit(source != nullptr, error = kErrorInvalidSourceAddress);
tunnelHeader.SetSource(source->GetAddress());
tunnelHeader.SetSource(*source);
SuccessOrExit(error = AddMplOption(aMessage, tunnelHeader));
SuccessOrExit(error = aMessage.Prepend(tunnelHeader));
@@ -242,7 +240,7 @@ exit:
return error;
}
Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo)
Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader)
{
Error error = kErrorNone;
@@ -315,7 +313,7 @@ Error Ip6::InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMes
}
#endif
SuccessOrExit(error = AddTunneledMplOption(aMessage, aHeader, aMessageInfo));
SuccessOrExit(error = AddTunneledMplOption(aMessage, aHeader));
}
exit:
@@ -467,10 +465,10 @@ Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI
if (aMessageInfo.GetSockAddr().IsUnspecified() || aMessageInfo.GetSockAddr().IsMulticast())
{
const Netif::UnicastAddress *source = SelectSourceAddress(aMessageInfo);
const Address *source = SelectSourceAddress(aMessageInfo.GetPeerAddr());
VerifyOrExit(source != nullptr, error = kErrorInvalidSourceAddress);
header.SetSource(source->GetAddress());
header.SetSource(*source);
}
else
{
@@ -507,7 +505,7 @@ Error Ip6::SendDatagram(Message &aMessage, MessageInfo &aMessageInfo, uint8_t aI
}
#endif
SuccessOrExit(error = AddTunneledMplOption(aMessage, header, aMessageInfo));
SuccessOrExit(error = AddTunneledMplOption(aMessage, header));
}
aMessage.SetMulticastLoop(aMessageInfo.GetMulticastLoop());
@@ -1126,21 +1124,16 @@ exit:
Error Ip6::SendRaw(Message &aMessage, bool aAllowLoopBackToHost)
{
Error error = kErrorNone;
Header header;
MessageInfo messageInfo;
bool freed = false;
Error error = kErrorNone;
Header header;
bool freed = false;
SuccessOrExit(error = header.ParseFrom(aMessage));
VerifyOrExit(!header.GetSource().IsMulticast(), error = kErrorInvalidSourceAddress);
messageInfo.SetPeerAddr(header.GetSource());
messageInfo.SetSockAddr(header.GetDestination());
messageInfo.SetHopLimit(header.GetHopLimit());
if (header.GetDestination().IsMulticast())
{
SuccessOrExit(error = InsertMplOption(aMessage, header, messageInfo));
SuccessOrExit(error = InsertMplOption(aMessage, header));
}
error = HandleDatagram(aMessage, aAllowLoopBackToHost ? kFromHostAllowLoopBack : kFromHostDisallowLoopBack);
@@ -1379,95 +1372,105 @@ bool Ip6::ShouldForwardToThread(const MessageInfo &aMessageInfo, MessageOrigin a
return shouldForward;
}
const Netif::UnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
Error Ip6::SelectSourceAddress(MessageInfo &aMessageInfo) const
{
Address *destination = &aMessageInfo.GetPeerAddr();
uint8_t destinationScope = destination->GetScope();
const bool destinationIsRoutingLocator = Get<Mle::Mle>().IsRoutingLocator(*destination);
const Netif::UnicastAddress *rvalAddr = nullptr;
uint8_t rvalPrefixMatched = 0;
Error error = kErrorNone;
const Address *source;
source = SelectSourceAddress(aMessageInfo.GetPeerAddr());
VerifyOrExit(source != nullptr, error = kErrorNotFound);
aMessageInfo.SetSockAddr(*source);
exit:
return error;
}
const Address *Ip6::SelectSourceAddress(const Address &aDestination) const
{
uint8_t destScope = aDestination.GetScope();
bool destIsRloc = Get<Mle::Mle>().IsRoutingLocator(aDestination);
const Netif::UnicastAddress *bestAddr = nullptr;
uint8_t bestMatchLen = 0;
for (const Netif::UnicastAddress &addr : Get<ThreadNetif>().GetUnicastAddresses())
{
const Address *candidateAddr = &addr.GetAddress();
uint8_t candidatePrefixMatched;
uint8_t overrideScope;
uint8_t matchLen;
uint8_t overrideScope;
if (Get<Mle::Mle>().IsAnycastLocator(*candidateAddr))
if (Get<Mle::Mle>().IsAnycastLocator(addr.GetAddress()))
{
// Don't use anycast address as source address.
continue;
}
candidatePrefixMatched = destination->PrefixMatch(*candidateAddr);
matchLen = aDestination.PrefixMatch(addr.GetAddress());
if (candidatePrefixMatched >= addr.mPrefixLength)
if (matchLen >= addr.mPrefixLength)
{
candidatePrefixMatched = addr.mPrefixLength;
overrideScope = addr.GetScope();
matchLen = addr.mPrefixLength;
overrideScope = addr.GetScope();
}
else
{
overrideScope = destinationScope;
overrideScope = destScope;
}
if (rvalAddr == nullptr)
if (bestAddr == nullptr)
{
// Rule 0: Prefer any address
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else if (*candidateAddr == *destination)
else if (addr.GetAddress() == aDestination)
{
// Rule 1: Prefer same address
rvalAddr = &addr;
bestAddr = &addr;
ExitNow();
}
else if (addr.GetScope() < rvalAddr->GetScope())
else if (addr.GetScope() < bestAddr->GetScope())
{
// Rule 2: Prefer appropriate scope
if (addr.GetScope() >= overrideScope)
{
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else
{
continue;
}
}
else if (addr.GetScope() > rvalAddr->GetScope())
else if (addr.GetScope() > bestAddr->GetScope())
{
if (rvalAddr->GetScope() < overrideScope)
if (bestAddr->GetScope() < overrideScope)
{
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else
{
continue;
}
}
else if (addr.mPreferred && !rvalAddr->mPreferred)
else if (addr.mPreferred && !bestAddr->mPreferred)
{
// Rule 3: Avoid deprecated addresses
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else if (candidatePrefixMatched > rvalPrefixMatched)
else if (matchLen > bestMatchLen)
{
// Rule 6: Prefer matching label
// Rule 7: Prefer public address
// Rule 8: Use longest prefix matching
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else if ((candidatePrefixMatched == rvalPrefixMatched) &&
(destinationIsRoutingLocator == Get<Mle::Mle>().IsRoutingLocator(*candidateAddr)))
else if ((matchLen == bestMatchLen) && (destIsRloc == Get<Mle::Mle>().IsRoutingLocator(addr.GetAddress())))
{
// Additional rule: Prefer RLOC source for RLOC destination, EID source for anything else
rvalAddr = &addr;
rvalPrefixMatched = candidatePrefixMatched;
bestAddr = &addr;
bestMatchLen = matchLen;
}
else
{
@@ -1475,14 +1478,14 @@ const Netif::UnicastAddress *Ip6::SelectSourceAddress(MessageInfo &aMessageInfo)
}
// infer destination scope based on prefix match
if (rvalPrefixMatched >= rvalAddr->mPrefixLength)
if (bestMatchLen >= bestAddr->mPrefixLength)
{
destinationScope = rvalAddr->GetScope();
destScope = bestAddr->GetScope();
}
}
exit:
return rvalAddr;
return (bestAddr != nullptr) ? &bestAddr->GetAddress() : nullptr;
}
bool Ip6::IsOnLink(const Address &aAddress) const
+16 -5
View File
@@ -310,14 +310,25 @@ public:
void SetForwardingEnabled(bool aEnable) { mForwardingEnabled = aEnable; }
/**
* This method perform default source address selection.
* This method performs default source address selection.
*
* @param[in] aMessageInfo A reference to the message information.
* @param[in,out] aMessageInfo A reference to the message information.
*
* @retval kErrorNone Found a source address and updated SockAddr of @p aMessageInfo.
* @retval kErrorNotFound No source address was found and @p aMessageInfo is unchanged.
*
*/
Error SelectSourceAddress(MessageInfo &aMessageInfo) const;
/**
* This method performs default source address selection.
*
* @param[in] aDestination The destination address.
*
* @returns A pointer to the selected IPv6 source address or `nullptr` if no source address was found.
*
*/
const Netif::UnicastAddress *SelectSourceAddress(MessageInfo &aMessageInfo);
const Address *SelectSourceAddress(const Address &aDestination) const;
/**
* This method returns a reference to the send queue.
@@ -404,8 +415,8 @@ private:
void SendIcmpError(Message &aMessage, Icmp::Header::Type aIcmpType, Icmp::Header::Code aIcmpCode);
#endif
Error AddMplOption(Message &aMessage, Header &aHeader);
Error AddTunneledMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
Error InsertMplOption(Message &aMessage, Header &aHeader, MessageInfo &aMessageInfo);
Error AddTunneledMplOption(Message &aMessage, Header &aHeader);
Error InsertMplOption(Message &aMessage, Header &aHeader);
Error RemoveMplOption(Message &aMessage);
Error HandleOptions(Message &aMessage, Header &aHeader, bool aIsOutbound, bool &aReceive);
Error HandlePayload(Header &aIp6Header,
+4 -7
View File
@@ -780,14 +780,11 @@ bool Tcp::AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress,
if (aBindAddress)
{
MessageInfo peerInfo;
const Netif::UnicastAddress *netifAddress;
const Address *source;
peerInfo.Clear();
peerInfo.SetPeerAddr(aPeer.GetAddress());
netifAddress = Get<Ip6>().SelectSourceAddress(peerInfo);
VerifyOrExit(netifAddress != nullptr, success = false);
aToBind.GetAddress() = netifAddress->GetAddress();
source = Get<Ip6>().SelectSourceAddress(aPeer.GetAddress());
VerifyOrExit(source != nullptr, success = false);
aToBind.SetAddress(*source);
}
if (aBindPort)