[posix] ignore required anycast address (#9717)

Ignore Required Anycast address when it is added to or deleted from
wpan0 interface in openthread.
This commit is contained in:
SherySheng
2023-12-26 07:47:47 -08:00
committed by GitHub
parent 1e82c4e962
commit 8167fb3626
3 changed files with 57 additions and 7 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (384)
#define OPENTHREAD_API_VERSION (385)
/**
* @addtogroup api-instance
+7 -6
View File
@@ -52,12 +52,13 @@ extern "C" {
*
*/
#define OT_IP6_PREFIX_SIZE 8 ///< Size of an IPv6 prefix (bytes)
#define OT_IP6_PREFIX_BITSIZE (OT_IP6_PREFIX_SIZE * 8) ///< Size of an IPv6 prefix (bits)
#define OT_IP6_IID_SIZE 8 ///< Size of an IPv6 Interface Identifier (bytes)
#define OT_IP6_ADDRESS_SIZE 16 ///< Size of an IPv6 address (bytes)
#define OT_IP6_HEADER_SIZE 40 ///< Size of an IPv6 header (bytes)
#define OT_IP6_HEADER_PROTO_OFFSET 6 ///< Offset of the proto field in the IPv6 header (bytes)
#define OT_IP6_PREFIX_SIZE 8 ///< Size of an IPv6 prefix (bytes)
#define OT_IP6_PREFIX_BITSIZE (OT_IP6_PREFIX_SIZE * 8) ///< Size of an IPv6 prefix (bits)
#define OT_IP6_IID_SIZE 8 ///< Size of an IPv6 Interface Identifier (bytes)
#define OT_IP6_ADDRESS_SIZE 16 ///< Size of an IPv6 address (bytes)
#define OT_IP6_ADDRESS_BITSIZE (OT_IP6_ADDRESS_SIZE * 8) ///< Size of an IPv6 address (bits)
#define OT_IP6_HEADER_SIZE 40 ///< Size of an IPv6 header (bytes)
#define OT_IP6_HEADER_PROTO_OFFSET 6 ///< Offset of the proto field in the IPv6 header (bytes)
/**
* @struct otIp6InterfaceIdentifier
+49
View File
@@ -1080,6 +1080,46 @@ exit:
}
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_DHCP6_PD_ENABLE
#ifdef __linux__
/**
* Returns whether the address is a required anycast address (RFC2373, 2.6.1).
*
*/
static bool isRequiredAnycast(const uint8_t *aAddress, uint8_t aPrefixLength)
{
bool isRequiredAnycast = false;
uint8_t firstBytePos = aPrefixLength / 8;
uint8_t remainingBits = aPrefixLength % 8;
if (aPrefixLength == OT_IP6_ADDRESS_BITSIZE)
{
ExitNow();
}
if (remainingBits != 0)
{
if ((aAddress[firstBytePos] & ((1 << remainingBits) - 1)) != 0)
{
ExitNow();
}
firstBytePos++;
}
for (int i = firstBytePos; i < OT_IP6_ADDRESS_SIZE; ++i)
{
if (aAddress[i] != 0)
{
ExitNow();
}
}
isRequiredAnycast = true;
exit:
return isRequiredAnycast;
}
#endif // __linux__
static void processTransmit(otInstance *aInstance)
{
otMessage *message = nullptr;
@@ -1213,6 +1253,15 @@ static void processNetifAddrEvent(otInstance *aInstance, struct nlmsghdr *aNetli
addr6.sin6_family = AF_INET6;
memcpy(&addr6.sin6_addr, RTA_DATA(rta), sizeof(addr6.sin6_addr));
// Linux allows adding an IPv6 required anycast address to an interface,
// which blocks openthread deriving an address by SLAAC and will cause routing issues.
// Ignore the required anycast addresses here to allow OpenThread stack generate one when necessary,
// and Linux will prefer the non-required anycast address on the interface.
if (isRequiredAnycast(addr.GetBytes(), ifaddr->ifa_prefixlen))
{
continue;
}
if (aNetlinkMessage->nlmsg_type == RTM_NEWADDR)
{
if (!addr.IsMulticast())