mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[posix] implement address labeling for mesh-local addresses (#13101)
Ideally, the mesh-local address (ML-EID) is only used when communicating with devices in the Thread mesh. The mesh-local address must not be used when communicating with other devices on the infrastructure link or outside the Thread mesh. This commit addresses this by implementing address labeling: 1. Modifying `UpdateUnicastLinux` in `src/posix/platform/netif.cpp` to stop marking mesh-local addresses as deprecated. They are now added as preferred addresses. 2. Implementing `AddAddressLabel` and `DeleteAddressLabel` to manage address labels via netlink (RTM_NEWADDRLABEL/RTM_DELADDRLABEL). 3. Calling `AddAddressLabel` when a mesh-local address is added to assign a specific label (99) to the Mesh-Local Prefix. This ensures that the kernel prefers the ML-EID for destinations sharing the same label (i.e., within the Thread mesh), while avoiding its use for external traffic where other addresses with standard labels would be a better match. Issue: 8443
This commit is contained in:
@@ -37,7 +37,7 @@ COPY . openthread
|
||||
RUN set -x \
|
||||
&& cd openthread \
|
||||
&& ./script/bootstrap \
|
||||
&& mkdir build \
|
||||
&& mkdir -p build \
|
||||
&& cd build \
|
||||
&& cmake -GNinja -DOT_COMMISSIONER=ON -DOT_JOINER=ON -DOT_PLATFORM=simulation .. \
|
||||
&& ninja
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
#include <ifaddrs.h>
|
||||
#ifdef __linux__
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if_addrlabel.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/netlink.h>
|
||||
@@ -205,7 +206,14 @@ using namespace ot::Posix::Ip6Utils;
|
||||
#endif // OPENTHREAD_POSIX_TUN_DEVICE
|
||||
|
||||
#ifdef __linux__
|
||||
static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
|
||||
static constexpr uint32_t kMeshLocalAddrLabel = 99;
|
||||
static uint32_t sNetlinkSequence = 0; ///< Netlink message sequence.
|
||||
static otMeshLocalPrefix sLabeledMeshLocalPrefix;
|
||||
static bool sIsMeshLocalPrefixLabeled = false;
|
||||
|
||||
static void AddAddressLabel(const uint8_t *aAddress, uint8_t aPrefixLen, uint32_t aLabel);
|
||||
static void DeleteAddressLabel(const uint8_t *aAddress, uint8_t aPrefixLen);
|
||||
static void UpdateMeshLocalPrefixLabel(otInstance *aInstance);
|
||||
#endif
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
|
||||
@@ -469,7 +477,7 @@ static void UpdateUnicastLinux(otInstance *aInstance, const otIp6AddressInfo &aA
|
||||
|
||||
AddRtAttr(&req.nh, sizeof(req), IFA_LOCAL, aAddressInfo.mAddress, sizeof(*aAddressInfo.mAddress));
|
||||
|
||||
if (!aAddressInfo.mPreferred || aAddressInfo.mMeshLocal || aAddressInfo.mScope == kLinkLocalScope)
|
||||
if (!aAddressInfo.mPreferred || aAddressInfo.mScope == kLinkLocalScope)
|
||||
{
|
||||
struct ifa_cacheinfo cacheinfo;
|
||||
|
||||
@@ -772,6 +780,129 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static void AddAddressLabel(const uint8_t *aAddress, uint8_t aPrefixLen, uint32_t aLabel)
|
||||
{
|
||||
constexpr unsigned int kBufSize = 128;
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr header;
|
||||
struct ifaddrlblmsg msg;
|
||||
char buf[kBufSize];
|
||||
} req{};
|
||||
unsigned int netifIdx = otSysGetThreadNetifIndex();
|
||||
char addrStrBuf[INET6_ADDRSTRLEN];
|
||||
|
||||
VerifyOrExit(netifIdx > 0);
|
||||
VerifyOrExit(sNetlinkFd >= 0);
|
||||
|
||||
req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL;
|
||||
|
||||
req.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrlblmsg));
|
||||
req.header.nlmsg_type = RTM_NEWADDRLABEL;
|
||||
req.header.nlmsg_pid = 0;
|
||||
req.header.nlmsg_seq = ++sNetlinkSequence;
|
||||
|
||||
req.msg.ifal_family = AF_INET6;
|
||||
req.msg.ifal_prefixlen = aPrefixLen;
|
||||
req.msg.ifal_flags = 0;
|
||||
req.msg.ifal_index = netifIdx;
|
||||
req.msg.ifal_seq = 0;
|
||||
|
||||
AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), IFAL_ADDRESS, aAddress, 16);
|
||||
AddRtAttrUint32(&req.header, sizeof(req), IFAL_LABEL, aLabel);
|
||||
|
||||
inet_ntop(AF_INET6, aAddress, addrStrBuf, sizeof(addrStrBuf));
|
||||
|
||||
if (send(sNetlinkFd, &req, req.header.nlmsg_len, 0) < 0)
|
||||
{
|
||||
LogWarn("Failed to send request#%u to add address label %s/%u: %s", sNetlinkSequence, addrStrBuf, aPrefixLen,
|
||||
strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo("Sent request#%u to add address label %s/%u with label %u", sNetlinkSequence, addrStrBuf, aPrefixLen,
|
||||
aLabel);
|
||||
}
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static void DeleteAddressLabel(const uint8_t *aAddress, uint8_t aPrefixLen)
|
||||
{
|
||||
constexpr unsigned int kBufSize = 128;
|
||||
struct
|
||||
{
|
||||
struct nlmsghdr header;
|
||||
struct ifaddrlblmsg msg;
|
||||
char buf[kBufSize];
|
||||
} req{};
|
||||
unsigned int netifIdx = otSysGetThreadNetifIndex();
|
||||
char addrStrBuf[INET6_ADDRSTRLEN];
|
||||
|
||||
VerifyOrExit(netifIdx > 0);
|
||||
VerifyOrExit(sNetlinkFd >= 0);
|
||||
|
||||
req.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
|
||||
req.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrlblmsg));
|
||||
req.header.nlmsg_type = RTM_DELADDRLABEL;
|
||||
req.header.nlmsg_pid = 0;
|
||||
req.header.nlmsg_seq = ++sNetlinkSequence;
|
||||
|
||||
req.msg.ifal_family = AF_INET6;
|
||||
req.msg.ifal_prefixlen = aPrefixLen;
|
||||
req.msg.ifal_flags = 0;
|
||||
req.msg.ifal_index = netifIdx;
|
||||
req.msg.ifal_seq = 0;
|
||||
|
||||
AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), IFAL_ADDRESS, aAddress, 16);
|
||||
|
||||
inet_ntop(AF_INET6, aAddress, addrStrBuf, sizeof(addrStrBuf));
|
||||
|
||||
if (send(sNetlinkFd, &req, req.header.nlmsg_len, 0) < 0)
|
||||
{
|
||||
LogWarn("Failed to send request#%u to delete address label %s/%u: %s", sNetlinkSequence, addrStrBuf, aPrefixLen,
|
||||
strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo("Sent request#%u to delete address label %s/%u", sNetlinkSequence, addrStrBuf, aPrefixLen);
|
||||
}
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
static void UpdateMeshLocalPrefixLabel(otInstance *aInstance)
|
||||
{
|
||||
const otMeshLocalPrefix *prefix = otIp6IsEnabled(aInstance) ? otThreadGetMeshLocalPrefix(aInstance) : nullptr;
|
||||
otIp6Address address;
|
||||
|
||||
VerifyOrExit(prefix == nullptr || !sIsMeshLocalPrefixLabeled ||
|
||||
memcmp(&sLabeledMeshLocalPrefix, prefix, sizeof(otMeshLocalPrefix)) != 0);
|
||||
|
||||
if (sIsMeshLocalPrefixLabeled)
|
||||
{
|
||||
memset(&address, 0, sizeof(address));
|
||||
memcpy(address.mFields.m8, sLabeledMeshLocalPrefix.m8, sizeof(sLabeledMeshLocalPrefix));
|
||||
DeleteAddressLabel(address.mFields.m8, 64);
|
||||
sIsMeshLocalPrefixLabeled = false;
|
||||
}
|
||||
|
||||
if (prefix != nullptr)
|
||||
{
|
||||
memset(&address, 0, sizeof(address));
|
||||
memcpy(address.mFields.m8, prefix->m8, sizeof(*prefix));
|
||||
AddAddressLabel(address.mFields.m8, 64, kMeshLocalAddrLabel);
|
||||
sLabeledMeshLocalPrefix = *prefix;
|
||||
sIsMeshLocalPrefixLabeled = true;
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
|
||||
static otError AddRoute(const otIp6Prefix &aPrefix, uint32_t aPriority)
|
||||
{
|
||||
@@ -1059,6 +1190,12 @@ void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
|
||||
{
|
||||
UpdateLink(aInstance);
|
||||
}
|
||||
#ifdef __linux__
|
||||
if ((OT_CHANGED_THREAD_NETIF_STATE | OT_CHANGED_THREAD_ML_ADDR) & aFlags)
|
||||
{
|
||||
UpdateMeshLocalPrefixLabel(aInstance);
|
||||
}
|
||||
#endif
|
||||
if (OT_CHANGED_THREAD_NETDATA & aFlags)
|
||||
{
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE && defined(__linux__)
|
||||
|
||||
Reference in New Issue
Block a user