[nat64] use host ID tracking for IPv4 address allocation (#11909)

This change modifies the NAT64 translator to dynamically allocate IPv4
addresses by tracking a range of host IDs within the configured CIDR.
This approach replaces the pre-allocated `mIp4AddressPool`, making it
more memory-efficient by avoiding the storage of an entire address
array.

The translator now maintains `mMinHostId` and `mMaxHostId` derived
from the configured CIDR. When allocating an IPv4 address for a new
mapping:

- If `PORT_TRANSLATION_ENABLE` is enabled, addresses are assigned
  sequentially by cycling through the host ID range. Mappings can
  share an IPv4 address as they are distinguished by translated port
  numbers.

- If `PORT_TRANSLATION_ENABLE` is disabled, a 1-to-1 address mapping
  is used. The translator cycles through host IDs to find an unused
  IPv4 address. If all addresses are allocated, it attempts to free
  expired mappings before failing.

A new test case, `TestNat64CidrAddressReuse`, is added to validate the
address allocation and reuse logic. The test ensures that all
available addresses from a CIDR are used, new requests fail when the
pool is exhausted, and addresses are correctly reused after mappings
expire. It is run against multiple CIDR sizes (`/32`, `/31`, `/30`,
and `/27`) to verify behavior across various configurations.
This commit is contained in:
Abtin Keshavarzian
2025-09-12 21:05:31 -07:00
committed by GitHub
parent d5935a34f3
commit eba5bdc434
6 changed files with 290 additions and 102 deletions
+4
View File
@@ -93,6 +93,7 @@ void VerifyLinkedListContent(const LinkedList<Entry> *aList, ...)
Entry *argPrev = nullptr;
const Entry *prev;
uint16_t unusedId = 100;
uint16_t count = 0;
va_start(args, aList);
@@ -117,6 +118,7 @@ void VerifyLinkedListContent(const LinkedList<Entry> *aList, ...)
VerifyOrQuit(!argEntry->WasFreed());
argPrev = argEntry;
count++;
}
argEntry = va_arg(args, Entry *);
@@ -129,6 +131,8 @@ void VerifyLinkedListContent(const LinkedList<Entry> *aList, ...)
VerifyOrQuit(aList->FindMatching("none") == nullptr, "succeeded for a missing entry");
VerifyOrQuit(aList->FindMatching(unusedId) == nullptr, "succeeded for a missing entry");
VerifyOrQuit(aList->CountAllEntries() == count);
}
void TestLinkedList(void)