mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 18:37:45 +00:00
[nexus] add test for nat64 translator (#11882)
This commit introduces a new Nexus test to validate the functionality of the NAT64 translator. The test is divided into two main parts: - `TestNat64StateChanges`: Verifies the state management of the translator. It checks that the translator transitions correctly between `kStateDisabled`, `kStateNotRunning`, and `kStateActive` when the feature is enabled/disabled or when the IPv4 CIDR and NAT64 prefix are configured or cleared. This test also confirms that state change notifications are properly signaled. - `TestNat64Mapping`: Validates the address mapping and translation logic. It ensures that address mappings are correctly created for new IPv6-to-IPv4 traffic, reused for subsequent packets from the same IPv6 source, and eventually expire and are removed after a period of inactivity. It also verifies that the mapping table is cleared when the configured IPv4 CIDR is changed.
This commit is contained in:
@@ -116,4 +116,5 @@ ot_nexus_test(dtls)
|
||||
ot_nexus_test(form_join)
|
||||
ot_nexus_test(full_network_reset)
|
||||
ot_nexus_test(large_network)
|
||||
ot_nexus_test(nat64_translator)
|
||||
ot_nexus_test(trel)
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
#define OPENTHREAD_CONFIG_MULTICAST_DNS_PUBLIC_API_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_NAT64_BORDER_ROUTING_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE 1
|
||||
#define OPENTHREAD_CONFIG_NAT64_IDLE_TIMEOUT_SECONDS 120
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_INFO_SET_API_ENABLE OPENTHREAD_FTD
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_MODEL "Nexus Simulation"
|
||||
#define OPENTHREAD_CONFIG_NET_DIAG_VENDOR_NAME "OpenThread by Google Nest"
|
||||
|
||||
@@ -0,0 +1,611 @@
|
||||
/*
|
||||
* Copyright (c) 2025, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform/nexus_core.hpp"
|
||||
#include "platform/nexus_node.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Nexus {
|
||||
|
||||
static bool sNotifierCallbackInvoked = false;
|
||||
static otChangedFlags sNotifierEvents = 0;
|
||||
|
||||
void HandleNotifierEvent(otChangedFlags aFlags, void *aContext)
|
||||
{
|
||||
VerifyOrQuit(aContext == nullptr);
|
||||
|
||||
sNotifierCallbackInvoked = true;
|
||||
sNotifierEvents = aFlags;
|
||||
}
|
||||
|
||||
void TestNat64StateChanges(void)
|
||||
{
|
||||
Core nexus;
|
||||
Node &node = nexus.CreateNode();
|
||||
Ip6::Prefix prefix, testPrefix;
|
||||
Ip4::Cidr cidr, testCidr;
|
||||
Nat64::Translator::AddressMappingIterator iterator;
|
||||
Nat64::Translator::AddressMapping mapping;
|
||||
|
||||
Log("------------------------------------------------------------------------------------------------------");
|
||||
Log("TestNat64StateChanges");
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
node.Form();
|
||||
nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
|
||||
VerifyOrQuit(node.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
node.Get<Instance>().SetLogLevel(kLogLevelInfo);
|
||||
|
||||
SuccessOrQuit(node.Get<Notifier>().RegisterCallback(HandleNotifierEvent, nullptr));
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check NAT64 Translator's initial state");
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateDisabled);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr) == kErrorNotFound);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix) == kErrorNotFound);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Enable NAT64");
|
||||
|
||||
node.Get<Nat64::Translator>().SetEnabled(true);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateNotRunning);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr) == kErrorNotFound);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix) == kErrorNotFound);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set an invalid CIDR");
|
||||
|
||||
testCidr.Clear();
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().SetIp4Cidr(testCidr) == kErrorInvalidArgs);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateNotRunning);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr) == kErrorNotFound);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set a valid CIDR");
|
||||
|
||||
SuccessOrQuit(testCidr.FromString("192.168.100.0/8"));
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().SetIp4Cidr(testCidr));
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateNotRunning);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix) == kErrorNotFound);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set a IPv6 NAT64 prefix");
|
||||
|
||||
SuccessOrQuit(testPrefix.FromString("fd01::/96"));
|
||||
node.Get<Nat64::Translator>().SetNat64Prefix(testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check that NAT64 is now active");
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Disable and re-enable NAT64");
|
||||
|
||||
nexus.AdvanceTime(1000);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
sNotifierCallbackInvoked = false;
|
||||
|
||||
node.Get<Nat64::Translator>().SetEnabled(false);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateDisabled);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
// Re-enable
|
||||
|
||||
sNotifierCallbackInvoked = false;
|
||||
|
||||
node.Get<Nat64::Translator>().SetEnabled(true);
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set the NAT64 prefix to the same value");
|
||||
|
||||
nexus.AdvanceTime(1000);
|
||||
|
||||
node.Get<Nat64::Translator>().SetNat64Prefix(testPrefix);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Clear NAT64 prefix and ensure NAT64 is stopped");
|
||||
|
||||
nexus.AdvanceTime(1000);
|
||||
|
||||
sNotifierCallbackInvoked = false;
|
||||
node.Get<Nat64::Translator>().ClearNat64Prefix();
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateNotRunning);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix) == kErrorNotFound);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Change NAT64 prefix and ensure NAT64 is again active");
|
||||
|
||||
sNotifierCallbackInvoked = false;
|
||||
|
||||
SuccessOrQuit(testPrefix.FromString("fd02::/96"));
|
||||
node.Get<Nat64::Translator>().SetNat64Prefix(testPrefix);
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Clear the configured CIDR and ensure NAT64 is stopped");
|
||||
|
||||
nexus.AdvanceTime(1000);
|
||||
|
||||
sNotifierCallbackInvoked = false;
|
||||
node.Get<Nat64::Translator>().ClearIp4Cidr();
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateNotRunning);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr) == kErrorNotFound);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Set the CIDR again and ensure NAT64 becomes active");
|
||||
|
||||
sNotifierCallbackInvoked = false;
|
||||
|
||||
SuccessOrQuit(testCidr.FromString("192.168.200.1/32"));
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().SetIp4Cidr(testCidr));
|
||||
|
||||
nexus.AdvanceTime(1);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp6Prefix(prefix));
|
||||
VerifyOrQuit(prefix == testPrefix);
|
||||
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().GetIp4Cidr(cidr));
|
||||
VerifyOrQuit(cidr == testCidr);
|
||||
|
||||
VerifyOrQuit(sNotifierCallbackInvoked);
|
||||
VerifyOrQuit(sNotifierEvents & kEventNat64TranslatorStateChanged);
|
||||
|
||||
Log("End of TestNat64StateChanges");
|
||||
}
|
||||
|
||||
Message *PrepareMessage(Node &aNode,
|
||||
const Ip6::Address &aSrcIp6Address,
|
||||
const Ip4::Address &aDstIp4Address,
|
||||
uint16_t aSrcPort = 1234,
|
||||
uint16_t aDstPort = 1235,
|
||||
uint16_t aPayloadLen = 10)
|
||||
{
|
||||
Message *message = nullptr;
|
||||
Ip6::Prefix nat64Prefix;
|
||||
Ip6::Header ip6Header;
|
||||
Ip6::Udp::Header udpHeader;
|
||||
|
||||
message = aNode.Get<MessagePool>().Allocate(Message::kTypeIp6);
|
||||
VerifyOrQuit(message != nullptr);
|
||||
|
||||
ip6Header.Clear();
|
||||
ip6Header.InitVersionTrafficClassFlow();
|
||||
|
||||
ip6Header.SetSource(aSrcIp6Address);
|
||||
|
||||
SuccessOrQuit(aNode.Get<Nat64::Translator>().GetIp6Prefix(nat64Prefix));
|
||||
ip6Header.GetDestination().SynthesizeFromIp4Address(nat64Prefix, aDstIp4Address);
|
||||
|
||||
ip6Header.SetNextHeader(Ip6::kProtoUdp);
|
||||
ip6Header.SetPayloadLength(sizeof(Ip6::Udp::Header) + aPayloadLen);
|
||||
|
||||
SuccessOrQuit(message->Append(ip6Header));
|
||||
|
||||
udpHeader.Clear();
|
||||
udpHeader.SetSourcePort(aSrcPort);
|
||||
udpHeader.SetDestinationPort(aDstPort);
|
||||
udpHeader.SetLength(aPayloadLen);
|
||||
|
||||
SuccessOrQuit(message->Append(udpHeader));
|
||||
|
||||
for (uint16_t i = 0; i < aPayloadLen; i++)
|
||||
{
|
||||
SuccessOrQuit(message->Append<uint8_t>(static_cast<uint8_t>(i & 0xff)));
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
void LogAddressMapping(const Nat64::Translator::AddressMapping &aMapping)
|
||||
{
|
||||
Log("Mapping: %s -> %s, remaining-time:%lu", AsCoreType(&aMapping.mIp6).ToString().AsCString(),
|
||||
AsCoreType(&aMapping.mIp4).ToString().AsCString(), ToUlong(aMapping.mRemainingTimeMs));
|
||||
}
|
||||
|
||||
void TestNat64Mapping(void)
|
||||
{
|
||||
static constexpr uint32_t kExpireTimeout = 250 * Time::kOneSecondInMsec;
|
||||
|
||||
static constexpr uint16_t kSrcPort = 55387;
|
||||
static constexpr uint16_t kDstPort = 55388;
|
||||
static constexpr uint16_t kPayloadLength = 32;
|
||||
|
||||
Core nexus;
|
||||
Node &node = nexus.CreateNode();
|
||||
Ip6::Prefix prefix;
|
||||
Ip4::Cidr cidr;
|
||||
Nat64::Translator::AddressMappingIterator iterator;
|
||||
Nat64::Translator::AddressMapping mapping;
|
||||
OwnedPtr<Message> message;
|
||||
Nat64::Translator::Result result;
|
||||
Ip6::Address ip6Addr;
|
||||
Ip6::Address ip6Addr2;
|
||||
Ip4::Address ip4Addr;
|
||||
Ip4::Headers ip4Headers;
|
||||
uint16_t count;
|
||||
|
||||
Log("------------------------------------------------------------------------------------------------------");
|
||||
Log("TestNat64Mapping");
|
||||
|
||||
nexus.AdvanceTime(0);
|
||||
|
||||
node.Form();
|
||||
nexus.AdvanceTime(50 * Time::kOneSecondInMsec);
|
||||
VerifyOrQuit(node.Get<Mle::Mle>().IsLeader());
|
||||
|
||||
node.Get<Instance>().SetLogLevel(kLogLevelInfo);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Enable NAT64 translator");
|
||||
|
||||
SuccessOrQuit(prefix.FromString("fd01::/96"));
|
||||
SuccessOrQuit(cidr.FromString("192.168.100.0/24"));
|
||||
|
||||
node.Get<Nat64::Translator>().SetNat64Prefix(prefix);
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().SetIp4Cidr(cidr));
|
||||
|
||||
node.Get<Nat64::Translator>().SetEnabled(true);
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Translate an IPv6 message");
|
||||
|
||||
SuccessOrQuit(ip6Addr.FromString("fd02::1"));
|
||||
SuccessOrQuit(ip4Addr.FromString("200.100.1.1"));
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr, ip4Addr, kSrcPort, kDstPort, kPayloadLength));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check the created Address Mapping");
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
SuccessOrQuit(iterator.GetNext(mapping));
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Translate another IPv6 message from the same IPv6 sender to a new IPv4 dest");
|
||||
|
||||
SuccessOrQuit(ip4Addr.FromString("200.100.1.2"));
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr, ip4Addr, kSrcPort, kDstPort, kPayloadLength * 2));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength * 2);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Ensure the previous Address Mapping is reused");
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
SuccessOrQuit(iterator.GetNext(mapping));
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Translate a new IPv6 message from a new IPv6 address");
|
||||
|
||||
nexus.AdvanceTime(30 * 1000);
|
||||
|
||||
SuccessOrQuit(ip6Addr2.FromString("fd02::2"));
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr2, ip4Addr, kSrcPort, kDstPort, kPayloadLength));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Ensure a new Address Mapping is created");
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
|
||||
for (count = 0; iterator.GetNext(mapping) == kErrorNone; count++)
|
||||
{
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
if (AsCoreType(&mapping.mIp6) == ip6Addr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr2);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
}
|
||||
|
||||
VerifyOrQuit(count == 2);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Translate another IPv6 message from with previous used addresses");
|
||||
|
||||
SuccessOrQuit(ip4Addr.FromString("200.100.1.5"));
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr, ip4Addr, kSrcPort, kDstPort, kPayloadLength));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Ensure the previous Address Mapping is reused");
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
|
||||
for (count = 0; iterator.GetNext(mapping) == kErrorNone; count++)
|
||||
{
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
if (AsCoreType(&mapping.mIp6) == ip6Addr2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
}
|
||||
|
||||
VerifyOrQuit(count == 2);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr2, ip4Addr, kSrcPort, kDstPort, kPayloadLength));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
|
||||
for (count = 0; iterator.GetNext(mapping) == kErrorNone; count++)
|
||||
{
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
if (AsCoreType(&mapping.mIp6) == ip6Addr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr2);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
}
|
||||
|
||||
VerifyOrQuit(count == 2);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Check Address Mapping expiration and removal");
|
||||
|
||||
nexus.AdvanceTime(kExpireTimeout);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Translate a new IPv6 message and check that a new Address Mapping is created");
|
||||
|
||||
message.Reset(PrepareMessage(node, ip6Addr, ip4Addr, kSrcPort, kDstPort, kPayloadLength));
|
||||
|
||||
result = node.Get<Nat64::Translator>().TranslateFromIp6(*message);
|
||||
VerifyOrQuit(result == Nat64::Translator::kForward);
|
||||
|
||||
SuccessOrQuit(ip4Headers.ParseFrom(*message));
|
||||
VerifyOrQuit(ip4Headers.GetDestinationAddress() == ip4Addr);
|
||||
VerifyOrQuit(ip4Headers.IsUdp());
|
||||
VerifyOrQuit(ip4Headers.GetSourcePort() == kSrcPort);
|
||||
VerifyOrQuit(ip4Headers.GetDestinationPort() == kDstPort);
|
||||
VerifyOrQuit(ip4Headers.GetUdpHeader().GetLength() == kPayloadLength);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
SuccessOrQuit(iterator.GetNext(mapping));
|
||||
LogAddressMapping(mapping);
|
||||
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp6) == ip6Addr);
|
||||
VerifyOrQuit(AsCoreType(&mapping.mIp4) == ip4Headers.GetSourceAddress());
|
||||
VerifyOrQuit(mapping.mRemainingTimeMs > 0);
|
||||
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Log("Change the CIDR and check that mapping list is cleared");
|
||||
|
||||
SuccessOrQuit(cidr.FromString("192.168.200.0/24"));
|
||||
SuccessOrQuit(node.Get<Nat64::Translator>().SetIp4Cidr(cidr));
|
||||
|
||||
VerifyOrQuit(node.Get<Nat64::Translator>().GetState() == Nat64::kStateActive);
|
||||
|
||||
iterator.Init(node.GetInstance());
|
||||
VerifyOrQuit(iterator.GetNext(mapping) == kErrorNotFound);
|
||||
}
|
||||
|
||||
} // namespace Nexus
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ot::Nexus::TestNat64StateChanges();
|
||||
ot::Nexus::TestNat64Mapping();
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user