mirror of
https://github.com/espressif/openthread.git
synced 2026-09-07 09:40:12 +00:00
[nat64] implement CLI functions for NAT64 (#8058)
This commit introduces `nat64` command and 4 new subcommands
(`configuredcidr`, `configuredprefix`, `mappings`, `counters`)
nat64 cidr -- Get the configured CIDR for NAT64 translator.
nat64 mappings -- Get the mappings of NAT64 translator.
nat64 counters -- Get the packet counters and error counters of NAT64
translator.
This commit also introduces related API for the above commands, and
`otIp4AddressToString` & `otIp4CidrToString` for the CLI to format the
IPv4 address and CIDR.
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 (241)
|
||||
#define OPENTHREAD_API_VERSION (242)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+185
-1
@@ -88,13 +88,151 @@ typedef struct otIp4Cidr
|
||||
uint8_t mLength;
|
||||
} otIp4Cidr;
|
||||
|
||||
/**
|
||||
* Represents the counters for NAT64.
|
||||
*
|
||||
*/
|
||||
typedef struct otNat64Counters
|
||||
{
|
||||
uint64_t m4To6Packets; ///< Number of packets translated from IPv4 to IPv6.
|
||||
uint64_t m4To6Bytes; ///< Sum of size of packets translated from IPv4 to IPv6.
|
||||
uint64_t m6To4Packets; ///< Number of packets translated from IPv6 to IPv4.
|
||||
uint64_t m6To4Bytes; ///< Sum of size of packets translated from IPv6 to IPv4.
|
||||
} otNat64Counters;
|
||||
|
||||
/**
|
||||
* Represents the counters for the protocols supported by NAT64.
|
||||
*
|
||||
*/
|
||||
typedef struct otNat64ProtocolCounters
|
||||
{
|
||||
otNat64Counters mTotal; ///< Counters for sum of all protocols.
|
||||
otNat64Counters mIcmp; ///< Counters for ICMP and ICMPv6.
|
||||
otNat64Counters mUdp; ///< Counters for UDP.
|
||||
otNat64Counters mTcp; ///< Counters for TCP.
|
||||
} otNat64ProtocolCounters;
|
||||
|
||||
/**
|
||||
* Packet drop reasons.
|
||||
*
|
||||
*/
|
||||
typedef enum otNat64DropReason
|
||||
{
|
||||
OT_NAT64_DROP_REASON_UNKNOWN = 0, ///< Packet drop for unknown reasons.
|
||||
OT_NAT64_DROP_REASON_ILLEGAL_PACKET, ///< Packet drop due to failed to parse the datagram.
|
||||
OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO, ///< Packet drop due to unsupported IP protocol.
|
||||
OT_NAT64_DROP_REASON_NO_MAPPING, ///< Packet drop due to no mappings found or mapping pool exhausted.
|
||||
//---
|
||||
OT_NAT64_DROP_REASON_COUNT,
|
||||
} otNat64DropReason;
|
||||
|
||||
/**
|
||||
* Represents the counters of dropped packets due to errors when handling NAT64 packets.
|
||||
*
|
||||
*/
|
||||
typedef struct otNat64ErrorCounters
|
||||
{
|
||||
uint64_t mCount4To6[OT_NAT64_DROP_REASON_COUNT]; ///< Errors translating IPv4 packets.
|
||||
uint64_t mCount6To4[OT_NAT64_DROP_REASON_COUNT]; ///< Errors translating IPv6 packets.
|
||||
} otNat64ErrorCounters;
|
||||
|
||||
/**
|
||||
* Gets NAT64 translator counters.
|
||||
*
|
||||
* The counter is counted since the instance initialized.
|
||||
*
|
||||
* Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[out] aCounters A pointer to an `otNat64Counters` where the counters of NAT64 translator will be placed.
|
||||
*
|
||||
*/
|
||||
void otNat64GetCounters(otInstance *aInstance, otNat64ProtocolCounters *aCounters);
|
||||
|
||||
/**
|
||||
* Gets the NAT64 translator error counters.
|
||||
*
|
||||
* The counters are initialized to zero when the OpenThread instance is initialized.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[out] aCounters A pointer to an `otNat64Counters` where the counters of NAT64 translator will be placed.
|
||||
*
|
||||
*/
|
||||
void otNat64GetErrorCounters(otInstance *aInstance, otNat64ErrorCounters *aCounters);
|
||||
|
||||
/**
|
||||
* Represents an address mapping record for NAT64.
|
||||
*
|
||||
* @note The counters will be reset for each mapping session even for the same address pair. Applications can use `mId`
|
||||
* to identify different sessions to calculate the packets correctly.
|
||||
*
|
||||
*/
|
||||
typedef struct otNat64AddressMapping
|
||||
{
|
||||
uint64_t mId; ///< The unique id for a mapping session.
|
||||
|
||||
otIp4Address mIp4; ///< The IPv4 address of the mapping.
|
||||
otIp6Address mIp6; ///< The IPv6 address of the mapping.
|
||||
uint32_t mRemainingTimeMs; ///< Remaining time before expiry in milliseconds.
|
||||
|
||||
otNat64ProtocolCounters mCounters;
|
||||
} otNat64AddressMapping;
|
||||
|
||||
/**
|
||||
* Used to iterate through NAT64 address mappings.
|
||||
*
|
||||
* The fields in this type are opaque (intended for use by OpenThread core only) and therefore should not be
|
||||
* accessed or used by caller.
|
||||
*
|
||||
* Before using an iterator, it MUST be initialized using `otNat64AddressMappingIteratorInit()`.
|
||||
*
|
||||
*/
|
||||
typedef struct otNat64AddressMappingIterator
|
||||
{
|
||||
void *mPtr;
|
||||
} otNat64AddressMappingIterator;
|
||||
|
||||
/**
|
||||
* Initializes an `otNat64AddressMappingIterator`.
|
||||
*
|
||||
* An iterator MUST be initialized before it is used.
|
||||
*
|
||||
* An iterator can be initialized again to restart from the beginning of the mapping info.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance.
|
||||
* @param[out] aIterator A pointer to the iterator to initialize.
|
||||
*
|
||||
*/
|
||||
void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMappingIterator *aIterator);
|
||||
|
||||
/**
|
||||
* Gets the next AddressMapping info (using an iterator).
|
||||
*
|
||||
* Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in,out] aIterator A pointer to the iterator. On success the iterator will be updated to point to next
|
||||
* NAT64 address mapping record. To get the first entry the iterator should be set to
|
||||
* OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
|
||||
* @param[out] aMapping A pointer to an `otNat64AddressMapping` where information of next NAT64 address
|
||||
* mapping record is placed (on success).
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully found the next NAT64 address mapping info (@p aMapping was successfully
|
||||
* updated).
|
||||
* @retval OT_ERROR_NOT_FOUND No subsequent NAT64 address mapping info was found.
|
||||
*
|
||||
*/
|
||||
otError otNat64GetNextAddressMapping(otInstance * aInstance,
|
||||
otNat64AddressMappingIterator *aIterator,
|
||||
otNat64AddressMapping * aMapping);
|
||||
|
||||
/**
|
||||
* Allocate a new message buffer for sending an IPv4 message to the NAT64 translator.
|
||||
*
|
||||
* Message buffers allocated by this function will have 20 bytes (difference between the size of IPv6 headers
|
||||
* and IPv4 header sizes) reserved.
|
||||
*
|
||||
* This function is available only when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
* Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
*
|
||||
* @note If @p aSettings is `NULL`, the link layer security is enabled and the message priority is set to
|
||||
* OT_MESSAGE_PRIORITY_NORMAL by default.
|
||||
@@ -174,6 +312,17 @@ typedef void (*otNat64ReceiveIp4Callback)(otMessage *aMessage, void *aContext);
|
||||
*/
|
||||
void otNat64SetReceiveIp4Callback(otInstance *aInstance, otNat64ReceiveIp4Callback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Gets the IPv4 CIDR configured in the NAT64 translator.
|
||||
*
|
||||
* Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[out] aCidr A pointer to an otIp4Cidr. Where the CIDR will be filled.
|
||||
*
|
||||
*/
|
||||
otError otNat64GetCidr(otInstance *aInstance, otIp4Cidr *aCidr);
|
||||
|
||||
/**
|
||||
* Test if two IPv4 addresses are the same.
|
||||
*
|
||||
@@ -200,6 +349,41 @@ bool otIp4IsAddressEqual(const otIp4Address *aFirst, const otIp4Address *aSecond
|
||||
*/
|
||||
void otIp4ExtractFromIp6Address(uint8_t aPrefixLength, const otIp6Address *aIp6Address, otIp4Address *aIp4Address);
|
||||
|
||||
#define OT_IP4_ADDRESS_STRING_SIZE 17 ///< Length of 000.000.000.000 plus a suffix NUL
|
||||
|
||||
/**
|
||||
* Converts the address to a string.
|
||||
*
|
||||
* The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
|
||||
*
|
||||
* If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
|
||||
* truncated but the outputted string is always null-terminated.
|
||||
*
|
||||
* @param[in] aAddress A pointer to an IPv4 address (MUST NOT be NULL).
|
||||
* @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`).
|
||||
* @param[in] aSize The size of @p aBuffer (in bytes).
|
||||
*
|
||||
*/
|
||||
void otIp4AddressToString(const otIp4Address *aAddress, char *aBuffer, uint16_t aSize);
|
||||
|
||||
#define OT_IP4_CIDR_STRING_SIZE 20 ///< Length of 000.000.000.000/00 plus a suffix NUL
|
||||
|
||||
/**
|
||||
* Converts the IPv4 CIDR to a string.
|
||||
*
|
||||
* The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
|
||||
* "127.0.0.1/32").
|
||||
*
|
||||
* If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
|
||||
* truncated but the outputted string is always null-terminated.
|
||||
*
|
||||
* @param[in] aCidr A pointer to an IPv4 CIDR (MUST NOT be NULL).
|
||||
* @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`).
|
||||
* @param[in] aSize The size of @p aBuffer (in bytes).
|
||||
*
|
||||
*/
|
||||
void otIp4CidrToString(const otIp4Cidr *aCidr, char *aBuffer, uint16_t aSize);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
|
||||
@@ -70,6 +70,7 @@ Done
|
||||
- [mlr](#mlr-reg-ipaddr--timeout)
|
||||
- [mode](#mode)
|
||||
- [multiradio](#multiradio)
|
||||
- [nat64](#nat64-cidr)
|
||||
- [neighbor](#neighbor-list)
|
||||
- [netdata](README_NETDATA.md)
|
||||
- [netstat](#netstat)
|
||||
@@ -1835,6 +1836,61 @@ This command is only available when device supports more than one radio link.
|
||||
Done
|
||||
```
|
||||
|
||||
### nat64 cidr
|
||||
|
||||
Gets the IPv4 configured CIDR in the NAT64 translator.
|
||||
|
||||
This command is only available when device enables NAT64 translator.
|
||||
|
||||
```bash
|
||||
> nat64 cidr
|
||||
192.168.64.0/24
|
||||
Done
|
||||
```
|
||||
|
||||
### nat64 mappings
|
||||
|
||||
Get the NAT64 translator mappings.
|
||||
|
||||
This command is only available when device enables NAT64 translator.
|
||||
|
||||
```bash
|
||||
> nat64 mappings
|
||||
| | Address | | 4 to 6 | 6 to 4 |
|
||||
+----------+---------------------------+--------+--------------+--------------+
|
||||
| ID | IPv6 | IPv4 | Expiry | Pkts | Bytes | Pkts | Bytes |
|
||||
+----------+------------+--------------+--------+------+-------+------+-------+
|
||||
| 00021cb9 | fdc7::df79 | 192.168.64.2 | 7196s | 6 | 456 | 11 | 1928 |
|
||||
| | TCP | 0 | 0 | 0 | 0 |
|
||||
| | UDP | 1 | 136 | 16 | 1608 |
|
||||
| | ICMP | 5 | 320 | 5 | 320 |
|
||||
```
|
||||
|
||||
### nat64 counters
|
||||
|
||||
Get the NAT64 translator packet and error counters.
|
||||
|
||||
This command is only available when device enables NAT64 translator.
|
||||
|
||||
```bash
|
||||
> nat64 counters
|
||||
| | 4 to 6 | 6 to 4 |
|
||||
+---------------+-------------------------+-------------------------+
|
||||
| Protocol | Pkts | Bytes | Pkts | Bytes |
|
||||
+---------------+----------+--------------+----------+--------------+
|
||||
| Total | 11 | 704 | 11 | 704 |
|
||||
| TCP | 0 | 0 | 0 | 0 |
|
||||
| UDP | 0 | 0 | 0 | 0 |
|
||||
| ICMP | 11 | 704 | 11 | 704 |
|
||||
| Errors | Pkts | Pkts |
|
||||
+---------------+-------------------------+-------------------------+
|
||||
| Total | 8 | 4 |
|
||||
| Illegal Pkt | 0 | 0 |
|
||||
| Unsup Proto | 0 | 0 |
|
||||
| No Mapping | 2 | 0 |
|
||||
Done
|
||||
```
|
||||
|
||||
### neighbor list
|
||||
|
||||
List RLOC16 of neighbors.
|
||||
|
||||
+213
@@ -84,6 +84,9 @@
|
||||
#if OPENTHREAD_CONFIG_RADIO_LINK_TREL_ENABLE
|
||||
#include <openthread/trel.h>
|
||||
#endif
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
#include <openthread/nat64.h>
|
||||
#endif
|
||||
|
||||
#include "common/new.hpp"
|
||||
#include "common/string.hpp"
|
||||
@@ -708,6 +711,213 @@ exit:
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_BORDER_ROUTING_ENABLE
|
||||
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
template <> otError Interpreter::Process<Cmd("nat64")>(Arg aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (aArgs[0].IsEmpty())
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_COMMAND);
|
||||
}
|
||||
/**
|
||||
* @cli nat64 cidr
|
||||
* @code
|
||||
* nat64 cidr
|
||||
* 192.168.64.0/24
|
||||
* Done
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otNat64GetCidr
|
||||
*
|
||||
*/
|
||||
else if (aArgs[0] == "cidr")
|
||||
{
|
||||
otIp4Cidr cidr;
|
||||
char cidrString[OT_IP4_CIDR_STRING_SIZE];
|
||||
|
||||
SuccessOrExit(error = otNat64GetCidr(GetInstancePtr(), &cidr));
|
||||
otIp4CidrToString(&cidr, cidrString, sizeof(cidrString));
|
||||
OutputLine("%s", cidrString);
|
||||
}
|
||||
/**
|
||||
* @cli nat64 mappings
|
||||
* @code
|
||||
* nat64 mappings
|
||||
* | | Address | | 4 to 6 | 6 to 4 |
|
||||
* +----------+---------------------------+--------+--------------+--------------+
|
||||
* | ID | IPv6 | IPv4 | Expiry | Pkts | Bytes | Pkts | Bytes |
|
||||
* +----------+------------+--------------+--------+------+-------+------+-------+
|
||||
* | 00021cb9 | fdc7::df79 | 192.168.64.2 | 7196s | 6 | 456 | 11 | 1928 |
|
||||
* | | TCP | 0 | 0 | 0 | 0 |
|
||||
* | | UDP | 1 | 136 | 16 | 1608 |
|
||||
* | | ICMP | 5 | 320 | 5 | 320 |
|
||||
* @endcode
|
||||
* @par api_copy
|
||||
* #otNat64GetNextAddressMapping
|
||||
*
|
||||
*/
|
||||
else if (aArgs[0] == "mappings")
|
||||
{
|
||||
otNat64AddressMappingIterator iterator;
|
||||
otNat64AddressMapping mapping;
|
||||
|
||||
static const char *const kNat64StatusLevel1Title[] = {"", "Address", "", "4 to 6", "6 to 4"};
|
||||
|
||||
static const uint8_t kNat64StatusLevel1ColumnWidths[] = {
|
||||
18, 61, 8, 25, 25,
|
||||
};
|
||||
|
||||
static const char *const kNat64StatusTableHeader[] = {
|
||||
"ID", "IPv6", "IPv4", "Expiry", "Pkts", "Bytes", "Pkts", "Bytes",
|
||||
};
|
||||
|
||||
static const uint8_t kNat64StatusTableColumnWidths[] = {
|
||||
18, 42, 18, 8, 10, 14, 10, 14,
|
||||
};
|
||||
|
||||
OutputTableHeader(kNat64StatusLevel1Title, kNat64StatusLevel1ColumnWidths);
|
||||
OutputTableHeader(kNat64StatusTableHeader, kNat64StatusTableColumnWidths);
|
||||
|
||||
otNat64InitAddressMappingIterator(GetInstancePtr(), &iterator);
|
||||
while (otNat64GetNextAddressMapping(GetInstancePtr(), &iterator, &mapping) == OT_ERROR_NONE)
|
||||
{
|
||||
char ip4AddressString[OT_IP4_ADDRESS_STRING_SIZE];
|
||||
char ip6AddressString[OT_IP6_PREFIX_STRING_SIZE];
|
||||
|
||||
otIp6AddressToString(&mapping.mIp6, ip6AddressString, sizeof(ip6AddressString));
|
||||
otIp4AddressToString(&mapping.mIp4, ip4AddressString, sizeof(ip4AddressString));
|
||||
|
||||
OutputFormat("| %016llx ", mapping.mId);
|
||||
OutputFormat("| %40s ", ip6AddressString);
|
||||
OutputFormat("| %16s ", ip4AddressString);
|
||||
OutputFormat("| %5llus ", mapping.mRemainingTimeMs / 1000);
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mTotal.m4To6Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mTotal.m4To6Bytes);
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mTotal.m6To4Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mTotal.m6To4Bytes);
|
||||
|
||||
OutputLine("|");
|
||||
|
||||
OutputFormat("| %016s ", "");
|
||||
OutputFormat("| %68s ", "TCP");
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mTcp.m4To6Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mTcp.m4To6Bytes);
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mTcp.m6To4Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mTcp.m6To4Bytes);
|
||||
OutputLine("|");
|
||||
|
||||
OutputFormat("| %016s ", "");
|
||||
OutputFormat("| %68s ", "UDP");
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mUdp.m4To6Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mUdp.m4To6Bytes);
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mUdp.m6To4Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mUdp.m6To4Bytes);
|
||||
OutputLine("|");
|
||||
|
||||
OutputFormat("| %016s ", "");
|
||||
OutputFormat("| %68s ", "ICMP");
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mIcmp.m4To6Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mIcmp.m4To6Bytes);
|
||||
OutputFormat("| %8llu ", mapping.mCounters.mIcmp.m6To4Packets);
|
||||
OutputFormat("| %12llu ", mapping.mCounters.mIcmp.m6To4Bytes);
|
||||
OutputLine("|");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @cli nat64 counters
|
||||
* @code
|
||||
* nat64 counters
|
||||
* | | 4 to 6 | 6 to 4 |
|
||||
* +---------------+-------------------------+-------------------------+
|
||||
* | Protocol | Pkts | Bytes | Pkts | Bytes |
|
||||
* +---------------+----------+--------------+----------+--------------+
|
||||
* | Total | 11 | 704 | 11 | 704 |
|
||||
* | TCP | 0 | 0 | 0 | 0 |
|
||||
* | UDP | 0 | 0 | 0 | 0 |
|
||||
* | ICMP | 11 | 704 | 11 | 704 |
|
||||
* | Errors | Pkts | Pkts |
|
||||
* +---------------+-------------------------+-------------------------+
|
||||
* | Total | 8 | 4 |
|
||||
* | Illegal Pkt | 0 | 0 |
|
||||
* | Unsup Proto | 0 | 0 |
|
||||
* | No Mapping | 2 | 0 |
|
||||
* Done
|
||||
* @endcode
|
||||
* @par
|
||||
* Gets the NAT64 translator packet and error counters.
|
||||
* @par
|
||||
* Available when `OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE` is enabled.
|
||||
* @sa otNat64GetCounters
|
||||
* @sa otNat64GetErrorCounters
|
||||
*
|
||||
*/
|
||||
else if (aArgs[0] == "counters")
|
||||
{
|
||||
static const char *const kNat64CounterTableHeader[] = {
|
||||
"",
|
||||
"4 to 6",
|
||||
"6 to 4",
|
||||
};
|
||||
static const uint8_t kNat64CounterTableHeaderColumns[] = {15, 25, 25};
|
||||
static const char *const kNat64CounterTableSubHeader[] = {
|
||||
"Protocol", "Pkts", "Bytes", "Pkts", "Bytes",
|
||||
};
|
||||
static const uint8_t kNat64CounterTableSubHeaderColumns[] = {
|
||||
15, 10, 14, 10, 14,
|
||||
};
|
||||
static const char *const kNat64CounterTableErrorSubHeader[] = {
|
||||
"Errors",
|
||||
"Pkts",
|
||||
"Pkts",
|
||||
};
|
||||
static const uint8_t kNat64CounterTableErrorSubHeaderColumns[] = {
|
||||
15,
|
||||
25,
|
||||
25,
|
||||
};
|
||||
static const char *const kNat64CounterErrorType[] = {
|
||||
"Unknown",
|
||||
"Illegal Pkt",
|
||||
"Unsup Proto",
|
||||
"No Mapping",
|
||||
};
|
||||
|
||||
otNat64ProtocolCounters counters;
|
||||
otNat64ErrorCounters errorCounters;
|
||||
|
||||
OutputTableHeader(kNat64CounterTableHeader, kNat64CounterTableHeaderColumns);
|
||||
OutputTableHeader(kNat64CounterTableSubHeader, kNat64CounterTableSubHeaderColumns);
|
||||
|
||||
otNat64GetCounters(GetInstancePtr(), &counters);
|
||||
otNat64GetErrorCounters(GetInstancePtr(), &errorCounters);
|
||||
|
||||
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "Total", counters.mTotal.m4To6Packets,
|
||||
counters.mTotal.m4To6Bytes, counters.mTotal.m6To4Packets, counters.mTotal.m6To4Bytes);
|
||||
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "TCP", counters.mTcp.m4To6Packets,
|
||||
counters.mTcp.m4To6Bytes, counters.mTcp.m6To4Packets, counters.mTcp.m6To4Bytes);
|
||||
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "UDP", counters.mUdp.m4To6Packets,
|
||||
counters.mUdp.m4To6Bytes, counters.mUdp.m6To4Packets, counters.mUdp.m6To4Bytes);
|
||||
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "ICMP", counters.mIcmp.m4To6Packets,
|
||||
counters.mIcmp.m4To6Bytes, counters.mIcmp.m6To4Packets, counters.mIcmp.m6To4Bytes);
|
||||
|
||||
OutputTableHeader(kNat64CounterTableErrorSubHeader, kNat64CounterTableErrorSubHeaderColumns);
|
||||
for (uint8_t i = 0; i < OT_NAT64_DROP_REASON_COUNT; i++)
|
||||
{
|
||||
OutputLine("| %13s | %23llu | %23llu |", kNat64CounterErrorType[i], errorCounters.mCount4To6[i],
|
||||
errorCounters.mCount6To4[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = OT_ERROR_INVALID_COMMAND);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
|
||||
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
template <> otError Interpreter::Process<Cmd("bbr")>(Arg aArgs[])
|
||||
{
|
||||
@@ -6437,6 +6647,9 @@ otError Interpreter::ProcessCommand(Arg aArgs[])
|
||||
#endif
|
||||
CmdEntry("mode"),
|
||||
CmdEntry("multiradio"),
|
||||
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
CmdEntry("nat64"),
|
||||
#endif
|
||||
#if OPENTHREAD_FTD
|
||||
CmdEntry("neighbor"),
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,38 @@ void otNat64SetReceiveIp4Callback(otInstance *aInstance, otNat64ReceiveIp4Callba
|
||||
{
|
||||
AsCoreType(aInstance).Get<Ip6::Ip6>().SetNat64ReceiveIp4DatagramCallback(aCallback, aContext);
|
||||
}
|
||||
|
||||
void otNat64InitAddressMappingIterator(otInstance *aInstance, otNat64AddressMappingIterator *aIterator)
|
||||
{
|
||||
AssertPointerIsNotNull(aIterator);
|
||||
|
||||
AsCoreType(aInstance).Get<Nat64::Translator>().InitAddressMappingIterator(*aIterator);
|
||||
}
|
||||
|
||||
otError otNat64GetNextAddressMapping(otInstance * aInstance,
|
||||
otNat64AddressMappingIterator *aIterator,
|
||||
otNat64AddressMapping * aMapping)
|
||||
{
|
||||
AssertPointerIsNotNull(aIterator);
|
||||
AssertPointerIsNotNull(aMapping);
|
||||
|
||||
return AsCoreType(aInstance).Get<Nat64::Translator>().GetNextAddressMapping(*aIterator, *aMapping);
|
||||
}
|
||||
|
||||
void otNat64GetCounters(otInstance *aInstance, otNat64ProtocolCounters *aCounters)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Nat64::Translator>().GetCounters(AsCoreType(aCounters));
|
||||
}
|
||||
|
||||
void otNat64GetErrorCounters(otInstance *aInstance, otNat64ErrorCounters *aCounters)
|
||||
{
|
||||
AsCoreType(aInstance).Get<Nat64::Translator>().GetErrorCounters(AsCoreType(aCounters));
|
||||
}
|
||||
|
||||
otError otNat64GetCidr(otInstance *aInstance, otIp4Cidr *aCidr)
|
||||
{
|
||||
return AsCoreType(aInstance).Get<Nat64::Translator>().GetIp4Cidr(AsCoreType(aCidr));
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
|
||||
bool otIp4IsAddressEqual(const otIp4Address *aFirst, const otIp4Address *aSecond)
|
||||
@@ -77,3 +109,17 @@ void otIp4ExtractFromIp6Address(uint8_t aPrefixLength, const otIp6Address *aIp6A
|
||||
{
|
||||
AsCoreType(aIp4Address).ExtractFromIp6Address(aPrefixLength, AsCoreType(aIp6Address));
|
||||
}
|
||||
|
||||
void otIp4AddressToString(const otIp4Address *aAddress, char *aBuffer, uint16_t aSize)
|
||||
{
|
||||
AssertPointerIsNotNull(aBuffer);
|
||||
|
||||
AsCoreType(aAddress).ToString(aBuffer, aSize);
|
||||
}
|
||||
|
||||
void otIp4CidrToString(const otIp4Cidr *aCidr, char *aBuffer, uint16_t aSize)
|
||||
{
|
||||
AssertPointerIsNotNull(aBuffer);
|
||||
|
||||
AsCoreType(aCidr).ToString(aBuffer, aSize);
|
||||
}
|
||||
|
||||
@@ -127,20 +127,44 @@ void Address::SynthesizeFromCidrAndHost(const Cidr &aCidr, const uint32_t aHost)
|
||||
mFields.m32 = (aCidr.mAddress.mFields.m32 & aCidr.SubnetMask()) | (HostSwap32(aHost) & aCidr.HostMask());
|
||||
}
|
||||
|
||||
void Address::ToString(StringWriter &aWriter) const
|
||||
{
|
||||
aWriter.Append("%d.%d.%d.%d", mFields.m8[0], mFields.m8[1], mFields.m8[2], mFields.m8[3]);
|
||||
}
|
||||
|
||||
void Address::ToString(char *aBuffer, uint16_t aSize) const
|
||||
{
|
||||
StringWriter writer(aBuffer, aSize);
|
||||
|
||||
ToString(writer);
|
||||
}
|
||||
|
||||
Address::InfoString Address::ToString(void) const
|
||||
{
|
||||
InfoString string;
|
||||
|
||||
string.Append("%d.%d.%d.%d", mFields.m8[0], mFields.m8[1], mFields.m8[2], mFields.m8[3]);
|
||||
ToString(string);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
void Cidr::ToString(StringWriter &aWriter) const
|
||||
{
|
||||
aWriter.Append("%s/%d", AsCoreType(&mAddress).ToString().AsCString(), mLength);
|
||||
}
|
||||
|
||||
void Cidr::ToString(char *aBuffer, uint16_t aSize) const
|
||||
{
|
||||
StringWriter writer(aBuffer, aSize);
|
||||
|
||||
ToString(writer);
|
||||
}
|
||||
|
||||
Cidr::InfoString Cidr::ToString(void) const
|
||||
{
|
||||
InfoString string;
|
||||
|
||||
string.Append("%s/%d", AsCoreType(&mAddress).ToString().AsCString(), mLength);
|
||||
ToString(string);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,20 @@ public:
|
||||
*/
|
||||
Error FromString(const char *aString);
|
||||
|
||||
/**
|
||||
* This method converts the address to a string.
|
||||
*
|
||||
* The string format uses quad-dotted notation of four bytes in the address (e.g., "127.0.0.1").
|
||||
*
|
||||
* If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
|
||||
* truncated but the outputted string is always null-terminated.
|
||||
*
|
||||
* @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`).
|
||||
* @param[in] aSize The size of @p aBuffer (in bytes).
|
||||
*
|
||||
*/
|
||||
void ToString(char *aBuffer, uint16_t aSize) const;
|
||||
|
||||
/**
|
||||
* This method converts the IPv4 address to a string.
|
||||
*
|
||||
@@ -170,6 +184,9 @@ public:
|
||||
*
|
||||
*/
|
||||
InfoString ToString(void) const;
|
||||
|
||||
private:
|
||||
void ToString(StringWriter &aWriter) const;
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
@@ -189,6 +206,21 @@ public:
|
||||
*/
|
||||
typedef String<Address::kAddressStringSize + kCidrSuffixSize> InfoString;
|
||||
|
||||
/**
|
||||
* This method converts the IPv4 CIDR to a string.
|
||||
*
|
||||
* The string format uses quad-dotted notation of four bytes in the address with the length of prefix (e.g.,
|
||||
* "127.0.0.1/32").
|
||||
*
|
||||
* If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
|
||||
* truncated but the outputted string is always null-terminated.
|
||||
*
|
||||
* @param[out] aBuffer A pointer to a char array to output the string (MUST NOT be `nullptr`).
|
||||
* @param[in] aSize The size of @p aBuffer (in bytes).
|
||||
*
|
||||
*/
|
||||
void ToString(char *aBuffer, uint16_t aSize) const;
|
||||
|
||||
/**
|
||||
* This method converts the IPv4 CIDR to a string.
|
||||
*
|
||||
@@ -237,6 +269,8 @@ private:
|
||||
}
|
||||
|
||||
uint32_t SubnetMask(void) const { return ~HostMask(); }
|
||||
|
||||
void ToString(StringWriter &aWriter) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,6 +52,8 @@ Translator::Translator(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mMappingExpirer(aInstance, MappingExpirerHandler)
|
||||
{
|
||||
Random::NonCrypto::FillBuffer(reinterpret_cast<uint8_t *>(&mNextMappingId), sizeof(mNextMappingId));
|
||||
|
||||
mNat64Prefix.Clear();
|
||||
mIp4Cidr.Clear();
|
||||
mMappingExpirer.Start(kAddressMappingIdleTimeoutMsec);
|
||||
@@ -91,10 +93,11 @@ exit:
|
||||
|
||||
Translator::Result Translator::TranslateFromIp6(Message &aMessage)
|
||||
{
|
||||
Result res = kDrop;
|
||||
Ip6::Header ip6Header;
|
||||
Ip4::Header ip4Header;
|
||||
AddressMapping *mapping = nullptr;
|
||||
Result res = kDrop;
|
||||
ErrorCounters::Reason dropReason = ErrorCounters::kUnknown;
|
||||
Ip6::Header ip6Header;
|
||||
Ip4::Header ip4Header;
|
||||
AddressMapping * mapping = nullptr;
|
||||
|
||||
if (mIp4Cidr.mLength == 0 || !mNat64Prefix.IsValidNat64())
|
||||
{
|
||||
@@ -105,6 +108,7 @@ Translator::Result Translator::TranslateFromIp6(Message &aMessage)
|
||||
if (ip6Header.ParseFrom(aMessage) != kErrorNone)
|
||||
{
|
||||
LogWarn("outgoing datagram is not a valid IPv6 datagram, drop");
|
||||
dropReason = ErrorCounters::Reason::kIllegalPacket;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -117,6 +121,7 @@ Translator::Result Translator::TranslateFromIp6(Message &aMessage)
|
||||
if (mapping == nullptr)
|
||||
{
|
||||
LogWarn("failed to get a mapping for %s (mapping pool full?)", ip6Header.GetSource().ToString().AsCString());
|
||||
dropReason = ErrorCounters::Reason::kNoMapping;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -145,6 +150,7 @@ Translator::Result Translator::TranslateFromIp6(Message &aMessage)
|
||||
res = kForward;
|
||||
break;
|
||||
default:
|
||||
dropReason = ErrorCounters::Reason::kUnsupportedProto;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -161,17 +167,24 @@ Translator::Result Translator::TranslateFromIp6(Message &aMessage)
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
aMessage.SetType(Message::kTypeIp4);
|
||||
mCounters.Count6To4Packet(ip6Header.GetNextHeader(), ip6Header.GetPayloadLength());
|
||||
mapping->mCounters.Count6To4Packet(ip6Header.GetNextHeader(), ip6Header.GetPayloadLength());
|
||||
|
||||
exit:
|
||||
if (res == Result::kDrop)
|
||||
{
|
||||
mErrorCounters.Count6To4(dropReason);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Translator::Result Translator::TranslateToIp6(Message &aMessage)
|
||||
{
|
||||
Result res = Result::kDrop;
|
||||
Ip6::Header ip6Header;
|
||||
Ip4::Header ip4Header;
|
||||
AddressMapping *mapping = nullptr;
|
||||
Result res = Result::kDrop;
|
||||
ErrorCounters::Reason dropReason = ErrorCounters::kUnknown;
|
||||
Ip6::Header ip6Header;
|
||||
Ip4::Header ip4Header;
|
||||
AddressMapping * mapping = nullptr;
|
||||
|
||||
// Ip6::Header::ParseFrom may return an error value when the incoming message is an IPv4 datagram.
|
||||
// If the message is already an IPv6 datagram, forward it directly.
|
||||
@@ -193,6 +206,7 @@ Translator::Result Translator::TranslateToIp6(Message &aMessage)
|
||||
if (ip4Header.ParseFrom(aMessage) != kErrorNone)
|
||||
{
|
||||
LogWarn("incoming message is neither IPv4 nor an IPv6 datagram, drop");
|
||||
dropReason = ErrorCounters::Reason::kIllegalPacket;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -200,6 +214,7 @@ Translator::Result Translator::TranslateToIp6(Message &aMessage)
|
||||
if (mapping == nullptr)
|
||||
{
|
||||
LogWarn("no mapping found for the IPv4 address");
|
||||
dropReason = ErrorCounters::Reason::kNoMapping;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -230,6 +245,7 @@ Translator::Result Translator::TranslateToIp6(Message &aMessage)
|
||||
res = kForward;
|
||||
break;
|
||||
default:
|
||||
dropReason = ErrorCounters::Reason::kUnsupportedProto;
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
|
||||
@@ -245,8 +261,15 @@ Translator::Result Translator::TranslateToIp6(Message &aMessage)
|
||||
ExitNow(res = kDrop);
|
||||
}
|
||||
aMessage.SetType(Message::kTypeIp6);
|
||||
mCounters.Count4To6Packet(ip4Header.GetProtocol(), ip4Header.GetTotalLength() - sizeof(ip4Header));
|
||||
mapping->mCounters.Count4To6Packet(ip4Header.GetProtocol(), ip4Header.GetTotalLength() - sizeof(ip4Header));
|
||||
|
||||
exit:
|
||||
if (res == Result::kDrop)
|
||||
{
|
||||
mErrorCounters.Count4To6(dropReason);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -259,6 +282,25 @@ Translator::AddressMapping::InfoString Translator::AddressMapping::ToString(void
|
||||
return string;
|
||||
}
|
||||
|
||||
void Translator::AddressMapping::CopyTo(otNat64AddressMapping &aMapping, TimeMilli aNow) const
|
||||
{
|
||||
aMapping.mId = mId;
|
||||
aMapping.mIp4 = mIp4;
|
||||
aMapping.mIp6 = mIp6;
|
||||
aMapping.mCounters = mCounters;
|
||||
|
||||
// We are removing expired mappings lazily, and an expired mapping might become active again before actually
|
||||
// removed. Report the mapping to be "just expired" to avoid confusion.
|
||||
if (mExpiry < aNow)
|
||||
{
|
||||
aMapping.mRemainingTimeMs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
aMapping.mRemainingTimeMs = mExpiry - aNow;
|
||||
}
|
||||
}
|
||||
|
||||
void Translator::ReleaseMapping(AddressMapping &aMapping)
|
||||
{
|
||||
IgnoreError(mIp4AddressPool.PushBack(aMapping.mIp4));
|
||||
@@ -300,6 +342,7 @@ Translator::AddressMapping *Translator::AllocateMapping(const Ip6::Address &aIp6
|
||||
VerifyOrExit(mapping != nullptr);
|
||||
|
||||
mActiveAddressMappings.Push(*mapping);
|
||||
mapping->mId = ++mNextMappingId;
|
||||
mapping->mIp6 = aIp6Addr;
|
||||
// PopBack must return a valid address since it is not empty.
|
||||
mapping->mIp4 = *mIp4AddressPool.PopBack();
|
||||
@@ -460,6 +503,93 @@ void Translator::MappingExpirerHandler(Timer &aTimer)
|
||||
aTimer.Get<Translator>().mMappingExpirer.Start(kAddressMappingIdleTimeoutMsec);
|
||||
}
|
||||
|
||||
void Translator::InitAddressMappingIterator(AddressMappingIterator &aIterator)
|
||||
{
|
||||
aIterator.mPtr = mActiveAddressMappings.GetHead();
|
||||
}
|
||||
|
||||
Error Translator::GetNextAddressMapping(AddressMappingIterator &aIterator, otNat64AddressMapping &aMapping)
|
||||
{
|
||||
Error err = kErrorNotFound;
|
||||
TimeMilli now = TimerMilli::GetNow();
|
||||
AddressMapping *item = static_cast<AddressMapping *>(aIterator.mPtr);
|
||||
|
||||
VerifyOrExit(item != nullptr);
|
||||
|
||||
item->CopyTo(aMapping, now);
|
||||
aIterator.mPtr = item->GetNext();
|
||||
err = kErrorNone;
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
Error Translator::GetIp4Cidr(Ip4::Cidr &aCidr)
|
||||
{
|
||||
Error err = kErrorNone;
|
||||
|
||||
VerifyOrExit(mIp4Cidr.mLength > 0, err = kErrorNotFound);
|
||||
aCidr = mIp4Cidr;
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
Error Translator::GetIp6Prefix(Ip6::Prefix &aPrefix)
|
||||
{
|
||||
Error err = kErrorNone;
|
||||
|
||||
VerifyOrExit(mNat64Prefix.mLength > 0, err = kErrorNotFound);
|
||||
aPrefix = mNat64Prefix;
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
void Translator::ProtocolCounters::Count6To4Packet(uint8_t aProtocol, uint64_t aPacketSize)
|
||||
{
|
||||
switch (aProtocol)
|
||||
{
|
||||
case Ip6::kProtoUdp:
|
||||
mUdp.m6To4Packets++;
|
||||
mUdp.m6To4Bytes += aPacketSize;
|
||||
break;
|
||||
case Ip6::kProtoTcp:
|
||||
mTcp.m6To4Packets++;
|
||||
mTcp.m6To4Bytes += aPacketSize;
|
||||
break;
|
||||
case Ip6::kProtoIcmp6:
|
||||
mIcmp.m6To4Packets++;
|
||||
mIcmp.m6To4Bytes += aPacketSize;
|
||||
break;
|
||||
}
|
||||
|
||||
mTotal.m6To4Packets++;
|
||||
mTotal.m6To4Bytes += aPacketSize;
|
||||
}
|
||||
|
||||
void Translator::ProtocolCounters::Count4To6Packet(uint8_t aProtocol, uint64_t aPacketSize)
|
||||
{
|
||||
switch (aProtocol)
|
||||
{
|
||||
case Ip4::kProtoUdp:
|
||||
mUdp.m4To6Packets++;
|
||||
mUdp.m4To6Bytes += aPacketSize;
|
||||
break;
|
||||
case Ip4::kProtoTcp:
|
||||
mTcp.m4To6Packets++;
|
||||
mTcp.m4To6Bytes += aPacketSize;
|
||||
break;
|
||||
case Ip4::kProtoIcmp:
|
||||
mIcmp.m4To6Packets++;
|
||||
mIcmp.m4To6Bytes += aPacketSize;
|
||||
break;
|
||||
}
|
||||
|
||||
mTotal.m4To6Packets++;
|
||||
mTotal.m4To6Bytes += aPacketSize;
|
||||
}
|
||||
|
||||
} // namespace Nat64
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
OPENTHREAD_CONFIG_NAT64_IDLE_TIMEOUT_SECONDS * Time::kOneSecondInMsec;
|
||||
static constexpr uint32_t kAddressMappingPoolSize = OPENTHREAD_CONFIG_NAT64_MAX_MAPPINGS;
|
||||
|
||||
typedef otNat64AddressMappingIterator AddressMappingIterator; ///< Address mapping Iterator.
|
||||
|
||||
/**
|
||||
* The possible results of NAT64 translation.
|
||||
*
|
||||
@@ -74,6 +76,64 @@ public:
|
||||
kDrop, ///< The caller should drop the datagram silently.
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the counters for the protocols supported by NAT64.
|
||||
*
|
||||
*/
|
||||
class ProtocolCounters : public otNat64ProtocolCounters, public Clearable<ProtocolCounters>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Adds the packet to the counter for the given IPv6 protocol.
|
||||
*
|
||||
* @param[in] aProtocol The protocol of the packet.
|
||||
* @param[in] aPacketSize The size of the packet.
|
||||
*
|
||||
*/
|
||||
void Count6To4Packet(uint8_t aProtocol, uint64_t aPacketSize);
|
||||
|
||||
/**
|
||||
* Adds the packet to the counter for the given IPv4 protocol.
|
||||
*
|
||||
* @param[in] aProtocol The protocol of the packet.
|
||||
* @param[in] aPacketSize The size of the packet.
|
||||
*
|
||||
*/
|
||||
void Count4To6Packet(uint8_t aProtocol, uint64_t aPacketSize);
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the counters of dropped packets due to errors when handling NAT64 packets.
|
||||
*
|
||||
*/
|
||||
class ErrorCounters : public otNat64ErrorCounters, public Clearable<otNat64ErrorCounters>
|
||||
{
|
||||
public:
|
||||
enum Reason : uint8_t
|
||||
{
|
||||
kUnknown = OT_NAT64_DROP_REASON_UNKNOWN,
|
||||
kIllegalPacket = OT_NAT64_DROP_REASON_ILLEGAL_PACKET,
|
||||
kUnsupportedProto = OT_NAT64_DROP_REASON_UNSUPPORTED_PROTO,
|
||||
kNoMapping = OT_NAT64_DROP_REASON_NO_MAPPING,
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the counter for the given reason when translating an IPv4 datagram.
|
||||
*
|
||||
* @param[in] aReason The reason of packet drop.
|
||||
*
|
||||
*/
|
||||
void Count4To6(Reason aReason) { mCount4To6[aReason]++; }
|
||||
|
||||
/**
|
||||
* Adds the counter for the given reason when translating an IPv6 datagram.
|
||||
*
|
||||
* @param[in] aReason The reason of packet drop.
|
||||
*
|
||||
*/
|
||||
void Count6To4(Reason aReason) { mCount6To4[aReason]++; }
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor initializes the NAT64 translator.
|
||||
*
|
||||
@@ -163,6 +223,76 @@ public:
|
||||
*/
|
||||
void SetNat64Prefix(const Ip6::Prefix &aNat64Prefix);
|
||||
|
||||
/**
|
||||
* Initializes an `otNat64AddressMappingIterator`.
|
||||
*
|
||||
* An iterator MUST be initialized before it is used.
|
||||
*
|
||||
* An iterator can be initialized again to restart from the beginning of the mapping info.
|
||||
*
|
||||
* @param[out] aIterator An iterator to initialize.
|
||||
*
|
||||
*/
|
||||
void InitAddressMappingIterator(AddressMappingIterator &aIterator);
|
||||
|
||||
/**
|
||||
* Gets the next AddressMapping info (using an iterator).
|
||||
*
|
||||
* @param[in,out] aIterator The iterator. On success the iterator will be updated to point to next NAT64
|
||||
* address mapping record. To get the first entry the iterator should be set to
|
||||
* OT_NAT64_ADDRESS_MAPPING_ITERATOR_INIT.
|
||||
* @param[out] aMapping An `otNat64AddressMapping` where information of next NAT64 address mapping record
|
||||
* is placed (on success).
|
||||
*
|
||||
* @retval kErrorNone Successfully found the next NAT64 address mapping info (@p aMapping was successfully
|
||||
* updated).
|
||||
* @retval kErrorNotFound No subsequent NAT64 address mapping info was found.
|
||||
*
|
||||
*/
|
||||
Error GetNextAddressMapping(AddressMappingIterator &aIterator, otNat64AddressMapping &aMapping);
|
||||
|
||||
/**
|
||||
* Gets the NAT64 translator counters.
|
||||
*
|
||||
* The counters are initialized to zero when the OpenThread instance is initialized.
|
||||
*
|
||||
* @param[out] aCounters A `ProtocolCounters` where the counters of NAT64 translator will be placed.
|
||||
*
|
||||
*/
|
||||
void GetCounters(ProtocolCounters &aCounters) const { aCounters = mCounters; }
|
||||
|
||||
/**
|
||||
* Gets the NAT64 translator error counters.
|
||||
*
|
||||
* The counters are initialized to zero when the OpenThread instance is initialized.
|
||||
*
|
||||
* @param[out] aCounters An `ErrorCounters` where the counters of NAT64 translator will be placed.
|
||||
*
|
||||
*/
|
||||
void GetErrorCounters(ErrorCounters &aCounters) const { aCounters = mErrorCounters; }
|
||||
|
||||
/**
|
||||
* Gets the configured CIDR in the NAT64 translator.
|
||||
*
|
||||
* @param[out] aCidr The `Ip4::Cidr` Where the configured CIDR will be placed.
|
||||
*
|
||||
* @retval kErrorNone @p aCidr is set to the configured CIDR.
|
||||
* @retval kErrorNotFound The translator is not configured with an IPv4 CIDR.
|
||||
*
|
||||
*/
|
||||
Error GetIp4Cidr(Ip4::Cidr &aCidr);
|
||||
|
||||
/**
|
||||
* Gets the configured IPv6 prefix in the NAT64 translator.
|
||||
*
|
||||
* @param[out] aPrefix The `Ip6::Prefix` where the configured NAT64 prefix will be placed.
|
||||
*
|
||||
* @retval kErrorNone @p aPrefix is set to the configured prefix.
|
||||
* @retval kErrorNotFound The translator is not configured with an IPv6 prefix.
|
||||
*
|
||||
*/
|
||||
Error GetIp6Prefix(Ip6::Prefix &aPrefix);
|
||||
|
||||
private:
|
||||
class AddressMapping : public LinkedListEntry<AddressMapping>
|
||||
{
|
||||
@@ -174,11 +304,16 @@ private:
|
||||
|
||||
void Touch(TimeMilli aNow) { mExpiry = aNow + kAddressMappingIdleTimeoutMsec; }
|
||||
InfoString ToString(void);
|
||||
void CopyTo(otNat64AddressMapping &aMapping, TimeMilli aNow) const;
|
||||
|
||||
uint64_t mId; // The unique id for a mapping session.
|
||||
|
||||
Ip4::Address mIp4;
|
||||
Ip6::Address mIp6;
|
||||
TimeMilli mExpiry; // The timestamp when this mapping expires, in milliseconds.
|
||||
|
||||
ProtocolCounters mCounters;
|
||||
|
||||
private:
|
||||
bool Matches(const Ip4::Address &aIp4) const { return mIp4 == aIp4; }
|
||||
bool Matches(const Ip6::Address &aIp6) const { return mIp6 == aIp6; }
|
||||
@@ -198,6 +333,8 @@ private:
|
||||
|
||||
static void MappingExpirerHandler(Timer &aTimer);
|
||||
|
||||
uint64_t mNextMappingId;
|
||||
|
||||
Array<Ip4::Address, kAddressMappingPoolSize> mIp4AddressPool;
|
||||
Pool<AddressMapping, kAddressMappingPoolSize> mAddressMappingPool;
|
||||
LinkedList<AddressMapping> mActiveAddressMappings;
|
||||
@@ -206,9 +343,16 @@ private:
|
||||
Ip4::Cidr mIp4Cidr;
|
||||
|
||||
TimerMilli mMappingExpirer;
|
||||
|
||||
ProtocolCounters mCounters;
|
||||
ErrorCounters mErrorCounters;
|
||||
};
|
||||
|
||||
} // namespace Nat64
|
||||
|
||||
DefineCoreType(otNat64ProtocolCounters, Nat64::Translator::ProtocolCounters);
|
||||
DefineCoreType(otNat64ErrorCounters, Nat64::Translator::ErrorCounters);
|
||||
|
||||
} // namespace ot
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
|
||||
|
||||
Reference in New Issue
Block a user