mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 17:37:46 +00:00
[posix] add / delete route to NAT64 CIDR according to NAT64 translator state (#8505)
Adds a callback for platform getting adding / removing the NAT64 route when NAT64 translator is enabled / disabled. The cases of adding / removing routes to NAT64 CIDR: - NAT64 inactive -> active: - interface down: noop - interface up: add route - NAT64 active -> inactive: - interface down: noop - interface up: delete route - interface down -> up: - NAT64 enabled: add route - NAT64 disabled: noop - interface up -> down: - Noop, kernel will delete all routes on the interface
This commit is contained in:
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (268)
|
||||
#define OPENTHREAD_API_VERSION (269)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
@@ -196,6 +196,7 @@ enum
|
||||
OT_CHANGED_JOINER_STATE = 1 << 27, ///< Joiner state changed
|
||||
OT_CHANGED_ACTIVE_DATASET = 1 << 28, ///< Active Operational Dataset changed
|
||||
OT_CHANGED_PENDING_DATASET = 1 << 29, ///< Pending Operational Dataset changed
|
||||
OT_CHANGED_NAT64_TRANSLATOR_STATE = 1 << 30, ///< The state of NAT64 translator changed
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -95,6 +95,7 @@ enum Event : uint32_t
|
||||
kEventJoinerStateChanged = OT_CHANGED_JOINER_STATE, ///< Joiner state changed
|
||||
kEventActiveDatasetChanged = OT_CHANGED_ACTIVE_DATASET, ///< Active Dataset changed
|
||||
kEventPendingDatasetChanged = OT_CHANGED_PENDING_DATASET, ///< Pending Dataset changed
|
||||
kEventNat64TranslatorStateChanged = OT_CHANGED_NAT64_TRANSLATOR_STATE, ///< Nat64Translator state changed
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,9 +48,26 @@ namespace Nat64 {
|
||||
|
||||
RegisterLogModule("Nat64");
|
||||
|
||||
const char *StateToString(State aState)
|
||||
{
|
||||
static const char *const kStateString[] = {
|
||||
"Disabled",
|
||||
"NotRunning",
|
||||
"Idle",
|
||||
"Active",
|
||||
};
|
||||
|
||||
static_assert(0 == kStateDisabled, "kStateDisabled value is incorrect");
|
||||
static_assert(1 == kStateNotRunning, "kStateNotRunning value is incorrect");
|
||||
static_assert(2 == kStateIdle, "kStateIdle value is incorrect");
|
||||
static_assert(3 == kStateActive, "kStateActive value is incorrect");
|
||||
|
||||
return kStateString[aState];
|
||||
}
|
||||
|
||||
Translator::Translator(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mEnabled(false)
|
||||
, mState(State::kStateDisabled)
|
||||
, mMappingExpirerTimer(aInstance)
|
||||
{
|
||||
Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&mNextMappingId), sizeof(mNextMappingId));
|
||||
@@ -490,6 +507,8 @@ Error Translator::SetIp4Cidr(const Ip4::Cidr &aCidr)
|
||||
numberOfHosts);
|
||||
mIp4Cidr = aCidr;
|
||||
|
||||
UpdateState();
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
@@ -501,6 +520,8 @@ void Translator::SetNat64Prefix(const Ip6::Prefix &aNat64Prefix)
|
||||
LogInfo("IPv6 Prefix for NAT64 updated to %s", aNat64Prefix.ToString().AsCString());
|
||||
mNat64Prefix = aNat64Prefix;
|
||||
}
|
||||
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
void Translator::HandleMappingExpirerTimer(void)
|
||||
@@ -596,16 +617,31 @@ void Translator::ProtocolCounters::Count4To6Packet(uint8_t aProtocol, uint64_t a
|
||||
mTotal.m4To6Bytes += aPacketSize;
|
||||
}
|
||||
|
||||
State Translator::GetState(void) const
|
||||
void Translator::UpdateState(void)
|
||||
{
|
||||
State ret = kStateDisabled;
|
||||
State newState;
|
||||
|
||||
VerifyOrExit(mEnabled);
|
||||
VerifyOrExit(mIp4Cidr.mLength > 0 && mNat64Prefix.IsValidNat64(), ret = kStateNotRunning);
|
||||
ret = kStateActive;
|
||||
if (mEnabled)
|
||||
{
|
||||
if (mIp4Cidr.mLength > 0 && mNat64Prefix.IsValidNat64())
|
||||
{
|
||||
newState = kStateActive;
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = kStateNotRunning;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newState = kStateDisabled;
|
||||
}
|
||||
|
||||
SuccessOrExit(Get<Notifier>().Update(mState, newState, kEventNat64TranslatorStateChanged));
|
||||
LogInfo("NAT64 translator is now %s", StateToString(mState));
|
||||
|
||||
exit:
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
void Translator::SetEnabled(bool aEnabled)
|
||||
@@ -618,7 +654,7 @@ void Translator::SetEnabled(bool aEnabled)
|
||||
ReleaseMappings(mActiveAddressMappings);
|
||||
}
|
||||
|
||||
LogInfo("NAT64 translator %s", aEnabled ? "enabled" : "disabled");
|
||||
UpdateState();
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
@@ -56,6 +56,16 @@ enum State : uint8_t
|
||||
kStateActive = OT_NAT64_STATE_ACTIVE, ///< The component is running.
|
||||
};
|
||||
|
||||
/**
|
||||
* This function converts a `State` into a string.
|
||||
*
|
||||
* @param[in] aState A state.
|
||||
*
|
||||
* @returns A string representation of @p aState.
|
||||
*
|
||||
*/
|
||||
const char *StateToString(State aState);
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
|
||||
/**
|
||||
@@ -166,7 +176,7 @@ public:
|
||||
* @retval kNat64StateActive The translator is translating packets.
|
||||
*
|
||||
*/
|
||||
State GetState(void) const;
|
||||
State GetState(void) const { return mState; }
|
||||
|
||||
/**
|
||||
* This method translates an IPv4 datagram to an IPv6 datagram and sends it via Thread interface.
|
||||
@@ -364,7 +374,10 @@ private:
|
||||
|
||||
using MappingTimer = TimerMilliIn<Translator, &Translator::HandleMappingExpirerTimer>;
|
||||
|
||||
bool mEnabled;
|
||||
void UpdateState(void);
|
||||
|
||||
bool mEnabled;
|
||||
State mState;
|
||||
|
||||
uint64_t mNextMappingId;
|
||||
|
||||
|
||||
@@ -618,8 +618,7 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
|
||||
static otError DeleteRoute(const otIp6Prefix &aPrefix)
|
||||
template <size_t N> otError DeleteRoute(const uint8_t (&aAddress)[N], uint8_t aPrefixLen)
|
||||
{
|
||||
constexpr unsigned int kBufSize = 512;
|
||||
struct
|
||||
@@ -628,10 +627,10 @@ static otError DeleteRoute(const otIp6Prefix &aPrefix)
|
||||
struct rtmsg msg;
|
||||
char buf[kBufSize];
|
||||
} req{};
|
||||
unsigned char data[sizeof(in6_addr)];
|
||||
char addrBuf[OT_IP6_ADDRESS_STRING_SIZE];
|
||||
unsigned int netifIdx = otSysGetThreadNetifIndex();
|
||||
otError error = OT_ERROR_NONE;
|
||||
unsigned int netifIdx = otSysGetThreadNetifIndex();
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
static_assert(N == sizeof(in6_addr) || N == sizeof(in_addr), "aAddress should be 4 octets or 16 octets");
|
||||
|
||||
VerifyOrExit(netifIdx > 0, error = OT_ERROR_INVALID_STATE);
|
||||
VerifyOrExit(sNetlinkFd >= 0, error = OT_ERROR_INVALID_STATE);
|
||||
@@ -643,9 +642,9 @@ static otError DeleteRoute(const otIp6Prefix &aPrefix)
|
||||
req.header.nlmsg_pid = 0;
|
||||
req.header.nlmsg_seq = ++sNetlinkSequence;
|
||||
|
||||
req.msg.rtm_family = AF_INET6;
|
||||
req.msg.rtm_family = (N == sizeof(in6_addr) ? AF_INET6 : AF_INET);
|
||||
req.msg.rtm_src_len = 0;
|
||||
req.msg.rtm_dst_len = aPrefix.mLength;
|
||||
req.msg.rtm_dst_len = aPrefixLen;
|
||||
req.msg.rtm_tos = 0;
|
||||
req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||
req.msg.rtm_type = RTN_UNICAST;
|
||||
@@ -653,9 +652,7 @@ static otError DeleteRoute(const otIp6Prefix &aPrefix)
|
||||
req.msg.rtm_protocol = RTPROT_BOOT;
|
||||
req.msg.rtm_flags = 0;
|
||||
|
||||
otIp6AddressToString(&aPrefix.mPrefix, addrBuf, OT_IP6_ADDRESS_STRING_SIZE);
|
||||
inet_pton(AF_INET6, addrBuf, data);
|
||||
AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, data, sizeof(data));
|
||||
AddRtAttr(reinterpret_cast<nlmsghdr *>(&req), sizeof(req), RTA_DST, &aAddress, sizeof(aAddress));
|
||||
AddRtAttrUint32(&req.header, sizeof(req), RTA_OIF, netifIdx);
|
||||
|
||||
if (send(sNetlinkFd, &req, sizeof(req), 0) < 0)
|
||||
@@ -668,10 +665,16 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
|
||||
static otError AddRoute(const otIp6Prefix &aPrefix, uint32_t aPriority)
|
||||
{
|
||||
return AddRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength, aPriority);
|
||||
}
|
||||
|
||||
static otError DeleteRoute(const otIp6Prefix &aPrefix)
|
||||
{
|
||||
return DeleteRoute(aPrefix.mPrefix.mFields.m8, aPrefix.mLength);
|
||||
}
|
||||
#endif // OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE || OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_INSTALL_OMR_ROUTES_ENABLE
|
||||
@@ -855,9 +858,14 @@ exit:
|
||||
#endif // OPENTHREAD_POSIX_CONFIG_INSTALL_EXTERNAL_ROUTES_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
static otError AddIp4Route(const otIp4Cidr &aCidr, uint32_t aPriority)
|
||||
static otError AddIp4Route(const otIp4Cidr &aIp4Cidr, uint32_t aPriority)
|
||||
{
|
||||
return AddRoute(aCidr.mAddress.mFields.m8, aCidr.mLength, aPriority);
|
||||
return AddRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength, aPriority);
|
||||
}
|
||||
|
||||
static otError DeleteIp4Route(const otIp4Cidr &aIp4Cidr)
|
||||
{
|
||||
return DeleteRoute(aIp4Cidr.mAddress.mFields.m8, aIp4Cidr.mLength);
|
||||
}
|
||||
#endif
|
||||
#endif // defined(__linux__)
|
||||
@@ -874,6 +882,28 @@ static void processAddressChange(const otIp6AddressInfo *aAddressInfo, bool aIsA
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
void processNat64StateChange(otNat64State aNewState)
|
||||
{
|
||||
// If the interface is not up and we are enabling NAT64, the route will be added when we bring up the route.
|
||||
// Also, the route will be deleted by the kernel when we shutting down the interface.
|
||||
// We should try to add route first, since otNat64SetEnabled never fails.
|
||||
if (otIp6IsEnabled(gInstance))
|
||||
{
|
||||
if (aNewState == OT_NAT64_STATE_ACTIVE)
|
||||
{
|
||||
AddIp4Route(gNat64Cidr, kNat64RoutePriority);
|
||||
otLogInfoPlat("[netif] Adding route for NAT64");
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteIp4Route(gNat64Cidr);
|
||||
otLogInfoPlat("[netif] Deleting route for NAT64");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
|
||||
void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
|
||||
{
|
||||
if (OT_CHANGED_THREAD_NETIF_STATE & aFlags)
|
||||
@@ -892,6 +922,12 @@ void platformNetifStateChange(otInstance *aInstance, otChangedFlags aFlags)
|
||||
ot::Posix::UpdateIpSets(aInstance);
|
||||
#endif
|
||||
}
|
||||
#if defined(__linux__) && OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
if (OT_CHANGED_NAT64_TRANSLATOR_STATE & aFlags)
|
||||
{
|
||||
processNat64StateChange(otNat64GetTranslatorState(aInstance));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void processReceive(otMessage *aMessage, void *aContext)
|
||||
@@ -1161,7 +1197,6 @@ static void processNetifLinkEvent(otInstance *aInstance, struct nlmsghdr *aNetli
|
||||
if (isUp && gNat64Cidr.mLength > 0)
|
||||
{
|
||||
SuccessOrExit(error = otNat64SetIp4Cidr(gInstance, &gNat64Cidr));
|
||||
AddIp4Route(gNat64Cidr, kNat64RoutePriority);
|
||||
otLogInfoPlat("[netif] Succeeded to enable NAT64");
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user