[ip6] add Tidy method to Ip6::Prefix (#9057)

Given the fact that we may accept a string from `otIp6Address`, this
commit makes a copy in `ToString()` to make result more consistent.
This commit is contained in:
Song GUO
2023-05-17 12:31:07 -07:00
committed by GitHub
parent dae3ff2c50
commit caf9ce839a
3 changed files with 205 additions and 2 deletions
+19 -1
View File
@@ -96,6 +96,22 @@ bool Prefix::ContainsPrefix(const NetworkPrefix &aSubPrefix) const
(MatchLength(GetBytes(), aSubPrefix.m8, NetworkPrefix::kSize) >= NetworkPrefix::kLength);
}
void Prefix::Tidy(void)
{
uint8_t byteLength = GetBytesSize();
uint8_t lastByteBitMask = ~(static_cast<uint8_t>(1 << (byteLength * 8 - mLength)) - 1);
if (byteLength != 0)
{
mPrefix.mFields.m8[byteLength - 1] &= lastByteBitMask;
}
for (uint16_t i = byteLength; i < GetArrayLength(mPrefix.mFields.m8); i++)
{
mPrefix.mFields.m8[i] = 0;
}
}
bool Prefix::operator==(const Prefix &aOther) const
{
return (mLength == aOther.mLength) && (MatchLength(GetBytes(), aOther.GetBytes(), GetBytesSize()) >= GetLength());
@@ -201,8 +217,10 @@ void Prefix::ToString(char *aBuffer, uint16_t aSize) const
void Prefix::ToString(StringWriter &aWriter) const
{
uint8_t sizeInUint16 = (GetBytesSize() + sizeof(uint16_t) - 1) / sizeof(uint16_t);
Prefix tidyPrefix = *this;
AsCoreType(&mPrefix).AppendHexWords(aWriter, sizeInUint16);
tidyPrefix.Tidy();
AsCoreType(&tidyPrefix.mPrefix).AppendHexWords(aWriter, sizeInUint16);
if (GetBytesSize() < Address::kSize - 1)
{
+8 -1
View File
@@ -172,6 +172,12 @@ public:
*/
void SetLength(uint8_t aLength) { mLength = aLength; }
/**
* This method sets the bits after the prefix length to 0.
*
*/
void Tidy(void);
/**
* This method indicates whether prefix length is valid (smaller or equal to max length).
*
@@ -351,7 +357,8 @@ public:
void ToString(char *aBuffer, uint16_t aSize) const;
private:
void ToString(StringWriter &aWriter) const;
uint8_t ByteAfterTidy(uint8_t aIndex);
void ToString(StringWriter &aWriter) const;
} OT_TOOL_PACKED_END;
/**
+178
View File
@@ -28,6 +28,7 @@
#include <limits.h>
#include "common/array.hpp"
#include "common/encoding.hpp"
#include "common/string.hpp"
#include "net/ip4_types.hpp"
@@ -581,6 +582,182 @@ void TestIp6Prefix(void)
VerifyOrQuit(!PrefixFrom("fe00::", 7).IsUniqueLocal());
}
void TestIp6PrefixTidy(void)
{
struct TestVector
{
uint8_t originalPrefix[OT_IP6_ADDRESS_SIZE];
const char *prefixStringAfterTidy[129];
};
const TestVector kPrefixes[] = {
{
.originalPrefix = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff},
.prefixStringAfterTidy =
{
"::/0",
"8000::/1",
"c000::/2",
"e000::/3",
"f000::/4",
"f800::/5",
"fc00::/6",
"fe00::/7",
"ff00::/8",
"ff80::/9",
"ffc0::/10",
"ffe0::/11",
"fff0::/12",
"fff8::/13",
"fffc::/14",
"fffe::/15",
"ffff::/16",
"ffff:8000::/17",
"ffff:c000::/18",
"ffff:e000::/19",
"ffff:f000::/20",
"ffff:f800::/21",
"ffff:fc00::/22",
"ffff:fe00::/23",
"ffff:ff00::/24",
"ffff:ff80::/25",
"ffff:ffc0::/26",
"ffff:ffe0::/27",
"ffff:fff0::/28",
"ffff:fff8::/29",
"ffff:fffc::/30",
"ffff:fffe::/31",
"ffff:ffff::/32",
"ffff:ffff:8000::/33",
"ffff:ffff:c000::/34",
"ffff:ffff:e000::/35",
"ffff:ffff:f000::/36",
"ffff:ffff:f800::/37",
"ffff:ffff:fc00::/38",
"ffff:ffff:fe00::/39",
"ffff:ffff:ff00::/40",
"ffff:ffff:ff80::/41",
"ffff:ffff:ffc0::/42",
"ffff:ffff:ffe0::/43",
"ffff:ffff:fff0::/44",
"ffff:ffff:fff8::/45",
"ffff:ffff:fffc::/46",
"ffff:ffff:fffe::/47",
"ffff:ffff:ffff::/48",
"ffff:ffff:ffff:8000::/49",
"ffff:ffff:ffff:c000::/50",
"ffff:ffff:ffff:e000::/51",
"ffff:ffff:ffff:f000::/52",
"ffff:ffff:ffff:f800::/53",
"ffff:ffff:ffff:fc00::/54",
"ffff:ffff:ffff:fe00::/55",
"ffff:ffff:ffff:ff00::/56",
"ffff:ffff:ffff:ff80::/57",
"ffff:ffff:ffff:ffc0::/58",
"ffff:ffff:ffff:ffe0::/59",
"ffff:ffff:ffff:fff0::/60",
"ffff:ffff:ffff:fff8::/61",
"ffff:ffff:ffff:fffc::/62",
"ffff:ffff:ffff:fffe::/63",
"ffff:ffff:ffff:ffff::/64",
"ffff:ffff:ffff:ffff:8000::/65",
"ffff:ffff:ffff:ffff:c000::/66",
"ffff:ffff:ffff:ffff:e000::/67",
"ffff:ffff:ffff:ffff:f000::/68",
"ffff:ffff:ffff:ffff:f800::/69",
"ffff:ffff:ffff:ffff:fc00::/70",
"ffff:ffff:ffff:ffff:fe00::/71",
"ffff:ffff:ffff:ffff:ff00::/72",
"ffff:ffff:ffff:ffff:ff80::/73",
"ffff:ffff:ffff:ffff:ffc0::/74",
"ffff:ffff:ffff:ffff:ffe0::/75",
"ffff:ffff:ffff:ffff:fff0::/76",
"ffff:ffff:ffff:ffff:fff8::/77",
"ffff:ffff:ffff:ffff:fffc::/78",
"ffff:ffff:ffff:ffff:fffe::/79",
"ffff:ffff:ffff:ffff:ffff::/80",
"ffff:ffff:ffff:ffff:ffff:8000::/81",
"ffff:ffff:ffff:ffff:ffff:c000::/82",
"ffff:ffff:ffff:ffff:ffff:e000::/83",
"ffff:ffff:ffff:ffff:ffff:f000::/84",
"ffff:ffff:ffff:ffff:ffff:f800::/85",
"ffff:ffff:ffff:ffff:ffff:fc00::/86",
"ffff:ffff:ffff:ffff:ffff:fe00::/87",
"ffff:ffff:ffff:ffff:ffff:ff00::/88",
"ffff:ffff:ffff:ffff:ffff:ff80::/89",
"ffff:ffff:ffff:ffff:ffff:ffc0::/90",
"ffff:ffff:ffff:ffff:ffff:ffe0::/91",
"ffff:ffff:ffff:ffff:ffff:fff0::/92",
"ffff:ffff:ffff:ffff:ffff:fff8::/93",
"ffff:ffff:ffff:ffff:ffff:fffc::/94",
"ffff:ffff:ffff:ffff:ffff:fffe::/95",
"ffff:ffff:ffff:ffff:ffff:ffff::/96",
// Note: The result of /97 to /112 does not meet RFC requirements:
// 4.2.2. Handling One 16-Bit 0 Field
// The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
"ffff:ffff:ffff:ffff:ffff:ffff:8000::/97",
"ffff:ffff:ffff:ffff:ffff:ffff:c000::/98",
"ffff:ffff:ffff:ffff:ffff:ffff:e000::/99",
"ffff:ffff:ffff:ffff:ffff:ffff:f000::/100",
"ffff:ffff:ffff:ffff:ffff:ffff:f800::/101",
"ffff:ffff:ffff:ffff:ffff:ffff:fc00::/102",
"ffff:ffff:ffff:ffff:ffff:ffff:fe00::/103",
"ffff:ffff:ffff:ffff:ffff:ffff:ff00::/104",
"ffff:ffff:ffff:ffff:ffff:ffff:ff80::/105",
"ffff:ffff:ffff:ffff:ffff:ffff:ffc0::/106",
"ffff:ffff:ffff:ffff:ffff:ffff:ffe0::/107",
"ffff:ffff:ffff:ffff:ffff:ffff:fff0::/108",
"ffff:ffff:ffff:ffff:ffff:ffff:fff8::/109",
"ffff:ffff:ffff:ffff:ffff:ffff:fffc::/110",
"ffff:ffff:ffff:ffff:ffff:ffff:fffe::/111",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff::/112",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:8000/113",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:c000/114",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:e000/115",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:f000/116",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:f800/117",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fc00/118",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fe00/119",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00/120",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff80/121",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffc0/122",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffe0/123",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0/124",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8/125",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc/126",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe/127",
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128",
},
},
};
printf("Tidy Prefixes:\n");
for (auto test : kPrefixes)
{
for (uint16_t i = 0; i < ot::GetArrayLength(test.prefixStringAfterTidy); i++)
{
ot::Ip6::Prefix prefix, answer;
SuccessOrQuit(answer.FromString(test.prefixStringAfterTidy[i]));
prefix.Set(test.originalPrefix, i);
prefix.Tidy();
{
ot::Ip6::Prefix::InfoString prefixString = prefix.ToString();
printf("Prefix: %-36s TidyResult: %-36s\n", test.prefixStringAfterTidy[i],
prefix.ToString().AsCString());
VerifyOrQuit(memcmp(answer.mPrefix.mFields.m8, prefix.mPrefix.mFields.m8,
sizeof(answer.mPrefix.mFields.m8)) == 0);
VerifyOrQuit(prefix.mLength == answer.mLength);
VerifyOrQuit(strcmp(test.prefixStringAfterTidy[i], prefixString.AsCString()) == 0);
}
}
}
}
void TestIp4Ip6Translation(void)
{
struct TestCase
@@ -705,6 +882,7 @@ int main(void)
TestIp6AddressFromString();
TestIp6PrefixFromString();
TestIp6Prefix();
TestIp6PrefixTidy();
TestIp4Ip6Translation();
TestIp4Cidr();
TestIp4CidrFromString();