Skip to content

Commit 382337f

Browse files
authored
[nat64] clear NAT64 counters when allocating new mapping table item (openthread#10871)
When allocating a new NAT64 mapping table item to a transaction, the counters might be dirty, causing incorrect counter values in NAT64 mapping protocol counters.
1 parent 090c777 commit 382337f

File tree

3 files changed

+189
-2
lines changed

3 files changed

+189
-2
lines changed

.code-spell-ignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
aactual
12
aafter
23
aanother
34
acount

src/core/net/nat64_translator.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,8 @@ Translator::AddressMapping *Translator::AllocateMapping(const Ip6::Address &aIp6
363363
VerifyOrExit(mapping != nullptr);
364364

365365
mActiveAddressMappings.Push(*mapping);
366-
mapping->mId = ++mNextMappingId;
366+
mapping->mId = ++mNextMappingId;
367+
mapping->mCounters.Clear();
367368
mapping->mIp6 = aIp6Addr;
368369
// PopBack must return a valid address since it is not empty.
369370
mapping->mIp4 = *mIp4AddressPool.PopBack();

tests/unit/test_nat64.cpp

+186-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
#include "test_platform.h"
3232
#include "test_util.hpp"
3333

34-
#include "string.h"
34+
#include <inttypes.h>
35+
#include <string.h>
3536

3637
#include "common/code_utils.hpp"
3738
#include "common/debug.hpp"
@@ -141,6 +142,36 @@ void TestCase4To6(const char *aTestName,
141142
printf(" ... PASS\n");
142143
}
143144

145+
void PrintCounters(const otNat64Counters &aCounter)
146+
{
147+
printf(" ... 4To6Packets = %" PRIu64 "\n", aCounter.m4To6Packets);
148+
printf(" ... 4To6Bytes = %" PRIu64 "\n", aCounter.m4To6Bytes);
149+
printf(" ... 6To4Packets = %" PRIu64 "\n", aCounter.m6To4Packets);
150+
printf(" ... 6To4Bytes = %" PRIu64 "\n", aCounter.m6To4Bytes);
151+
}
152+
153+
void PrintProtocolCounters(const otNat64ProtocolCounters &aCounter)
154+
{
155+
printf(" Total \n");
156+
PrintCounters(aCounter.mTotal);
157+
printf(" ICMP \n");
158+
PrintCounters(aCounter.mIcmp);
159+
printf(" UDP \n");
160+
PrintCounters(aCounter.mUdp);
161+
printf(" TCP \n");
162+
PrintCounters(aCounter.mTcp);
163+
}
164+
165+
void VerifyCounters(const otNat64ProtocolCounters &aExpected, const otNat64ProtocolCounters &aActual)
166+
{
167+
printf("Expected packet counters: \n");
168+
PrintProtocolCounters(aExpected);
169+
printf("Actual packet counters: \n");
170+
PrintProtocolCounters(aActual);
171+
VerifyOrQuit(memcmp(&aExpected, &aActual, sizeof(aActual)) == 0);
172+
printf(" ... PASS\n");
173+
}
174+
144175
void TestNat64(void)
145176
{
146177
Ip6::Prefix nat64prefix;
@@ -297,6 +328,159 @@ void TestNat64(void)
297328
testFreeInstance(sInstance);
298329
}
299330

331+
void TestPacketCounter(void)
332+
{
333+
Ip6::Prefix nat64prefix;
334+
Ip4::Cidr nat64cidr;
335+
Ip6::Address ip6Source;
336+
Ip6::Address ip6Dest;
337+
338+
printf("Test: Packet counter is cleared for new mappings.\n");
339+
340+
sInstance = testInitInstance();
341+
342+
{
343+
const uint8_t ip6Address[] = {0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
345+
const uint8_t ip4Address[] = {192, 168, 123, 1};
346+
347+
nat64cidr.Set(ip4Address, 32);
348+
nat64prefix.Set(ip6Address, 96);
349+
SuccessOrQuit(sInstance->Get<Nat64::Translator>().SetIp4Cidr(nat64cidr));
350+
sInstance->Get<Nat64::Translator>().SetNat64Prefix(nat64prefix);
351+
}
352+
353+
// Step 1: Make the mapping table dirty.
354+
{
355+
// fd02::1 fd01::ac10:f3c5 UDP 52 43981 → 4660 Len=4
356+
const uint8_t kIp6Packet[] = {
357+
0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
358+
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359+
172, 16, 243, 197, 0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
360+
};
361+
// 192.168.123.1 172.16.243.197 UDP 32 43981 → 4660 Len=4
362+
const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x9f,
363+
0x4d, 192, 168, 123, 1, 172, 16, 243, 197, 0xab, 0xcd,
364+
0x12, 0x34, 0x00, 0x0c, 0xa1, 0x8d, 0x61, 0x62, 0x63, 0x64};
365+
366+
TestCase6To4("initial translation", kIp6Packet, Nat64::Translator::kForward, kIp4Packet, sizeof(kIp4Packet));
367+
}
368+
369+
{
370+
Nat64::Translator::AddressMappingIterator iter;
371+
otNat64AddressMapping mapping;
372+
size_t totalMappingCount = 0;
373+
374+
sInstance->Get<Nat64::Translator>().InitAddressMappingIterator(iter);
375+
while (sInstance->Get<Nat64::Translator>().GetNextAddressMapping(iter, mapping) == kErrorNone)
376+
{
377+
totalMappingCount++;
378+
VerifyCounters(otNat64ProtocolCounters{.mTotal =
379+
{
380+
.m4To6Packets = 0,
381+
.m4To6Bytes = 0,
382+
.m6To4Packets = 1,
383+
.m6To4Bytes = 12,
384+
},
385+
.mIcmp =
386+
{
387+
.m4To6Packets = 0,
388+
.m4To6Bytes = 0,
389+
.m6To4Packets = 0,
390+
.m6To4Bytes = 0,
391+
},
392+
.mUdp =
393+
{
394+
.m4To6Packets = 0,
395+
.m4To6Bytes = 0,
396+
.m6To4Packets = 1,
397+
.m6To4Bytes = 12,
398+
},
399+
.mTcp =
400+
{
401+
.m4To6Packets = 0,
402+
.m4To6Bytes = 0,
403+
.m6To4Packets = 0,
404+
.m6To4Bytes = 0,
405+
}},
406+
mapping.mCounters);
407+
}
408+
VerifyOrQuit(totalMappingCount == 1);
409+
}
410+
411+
// Step 2: Release the mapping table item.
412+
{
413+
const uint8_t ip6Address[] = {0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
414+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
415+
const uint8_t ip4Address[] = {192, 168, 124, 1};
416+
417+
nat64cidr.Set(ip4Address, 32);
418+
nat64prefix.Set(ip6Address, 96);
419+
SuccessOrQuit(sInstance->Get<Nat64::Translator>().SetIp4Cidr(nat64cidr));
420+
sInstance->Get<Nat64::Translator>().SetNat64Prefix(nat64prefix);
421+
}
422+
423+
// Step 3: Reuse the same object for new mapping table item.
424+
// If the counters are not reset, the verification below will fail.
425+
{
426+
// fd02::1 fd01::ac10:f3c5 UDP 52 43981 → 4660 Len=4
427+
const uint8_t kIp6Packet[] = {
428+
0x60, 0x08, 0x6e, 0x38, 0x00, 0x0c, 0x11, 0x40, 0xfd, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429+
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfd, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430+
172, 16, 243, 197, 0xab, 0xcd, 0x12, 0x34, 0x00, 0x0c, 0xe3, 0x31, 0x61, 0x62, 0x63, 0x64,
431+
};
432+
// 192.168.124.1 172.16.243.197 UDP 32 43981 → 4660 Len=4
433+
const uint8_t kIp4Packet[] = {0x45, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x9e,
434+
0x4d, 192, 168, 124, 1, 172, 16, 243, 197, 0xab, 0xcd,
435+
0x12, 0x34, 0x00, 0x0c, 0xa0, 0x8d, 0x61, 0x62, 0x63, 0x64};
436+
437+
TestCase6To4("translation with new mapping", kIp6Packet, Nat64::Translator::kForward, kIp4Packet,
438+
sizeof(kIp4Packet));
439+
}
440+
441+
{
442+
Nat64::Translator::AddressMappingIterator iter;
443+
otNat64AddressMapping mapping;
444+
size_t totalMappingCount = 0;
445+
446+
sInstance->Get<Nat64::Translator>().InitAddressMappingIterator(iter);
447+
while (sInstance->Get<Nat64::Translator>().GetNextAddressMapping(iter, mapping) == kErrorNone)
448+
{
449+
totalMappingCount++;
450+
VerifyCounters(otNat64ProtocolCounters{.mTotal =
451+
{
452+
.m4To6Packets = 0,
453+
.m4To6Bytes = 0,
454+
.m6To4Packets = 1,
455+
.m6To4Bytes = 12,
456+
},
457+
.mIcmp =
458+
{
459+
.m4To6Packets = 0,
460+
.m4To6Bytes = 0,
461+
.m6To4Packets = 0,
462+
.m6To4Bytes = 0,
463+
},
464+
.mUdp =
465+
{
466+
.m4To6Packets = 0,
467+
.m4To6Bytes = 0,
468+
.m6To4Packets = 1,
469+
.m6To4Bytes = 12,
470+
},
471+
.mTcp =
472+
{
473+
.m4To6Packets = 0,
474+
.m4To6Bytes = 0,
475+
.m6To4Packets = 0,
476+
.m6To4Bytes = 0,
477+
}},
478+
mapping.mCounters);
479+
}
480+
VerifyOrQuit(totalMappingCount == 1);
481+
}
482+
}
483+
300484
} // namespace BorderRouter
301485
} // namespace ot
302486

@@ -306,6 +490,7 @@ int main(void)
306490
{
307491
#if OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
308492
ot::BorderRouter::TestNat64();
493+
ot::BorderRouter::TestPacketCounter();
309494
printf("All tests passed\n");
310495
#else // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
311496
printf("NAT64 is not enabled\n");

0 commit comments

Comments
 (0)