ipv6: use absl:uint128 instead of array of uint_8 for address return.#2431
ipv6: use absl:uint128 instead of array of uint_8 for address return.#2431mattklein123 merged 10 commits intomasterfrom
Conversation
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
| std::copy(std::begin(address_.sin6_addr.s6_addr), std::end(address_.sin6_addr.s6_addr), | ||
| std::begin(result)); | ||
| absl::uint128 Ipv6Instance::Ipv6Helper::address() const { | ||
| absl::uint128 result{0}; |
There was a problem hiding this comment.
Whether the type is intrinsic or not, you should be able to just memcpy here.
There was a problem hiding this comment.
Updated all call paths to use memcpy instead.
|
|
||
| absl::uint128 Utility::Ip6htonl(const absl::uint128& address) { return flipOrder(address); } | ||
|
|
||
| std::array<uint8_t, 16> Utility::getArrayRepresentation(const absl::uint128& address) { |
There was a problem hiding this comment.
I think this method is not needed. memcpy should work where this is used.
There was a problem hiding this comment.
Updated all call paths to use memcpy.
| return false; | ||
| } | ||
|
|
||
| absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { return flipOrder(address); } |
There was a problem hiding this comment.
I don't think it makes sense that both of these functions do the same thing unless you actually check for local endianness somewhere. I would either do that, or use a single function, assert endianness somehow, and add a TODO.
There was a problem hiding this comment.
Doesn't this break if Envoy is running on a big endian system?
There was a problem hiding this comment.
This has been updated to have an assert on little endianess and a todo has been added to support big endian.
| } | ||
| absl::uint128 ip6 = Utility::Ip6ntohl(address->ip()->ipv6()->address()); | ||
| // The maximum number stored in absl::uint128 has every bit set to 1. | ||
| absl::uint128 max_int = absl::MakeUint128(std::numeric_limits<uint64_t>::max(), |
There was a problem hiding this comment.
Can you use absl::Uint128Max()?
There was a problem hiding this comment.
When I try using it, I get the following: error: 'Uint128Max' is not a member of 'absl' absl::uint128 max_int = absl::Uint128Max(); ?
There was a problem hiding this comment.
Figured it out. There was an update 11 days ago to change kuint128max to Uint128Max(). I locally have the older absl.
| max_int <<= (128 - length); | ||
| ip6 &= max_int; | ||
|
|
||
| std::array<uint8_t, 16> ip6_array = Utility::getArrayRepresentation(Utility::Ip6htonl(ip6)); |
| return false; | ||
| } | ||
|
|
||
| absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { return flipOrder(address); } |
There was a problem hiding this comment.
Doesn't this break if Envoy is running on a big endian system?
| /** | ||
| * Converts IPv6 absl::uint128 in network byte order to host byte order. | ||
| * @param address supplies the IPv6 address in network byte order. | ||
| * @return IPv6 in host byte order. |
There was a problem hiding this comment.
nit: return type in @return (here and the other functions in this file)
| EXPECT_EQ(expected_result, Utility::getArrayRepresentation(address.ip()->ipv6()->address())); | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
It's worth thinking about how this test will work (or won't work) on a big endian machine.
There was a problem hiding this comment.
I've added an assert to only work on big endian machines.
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
| } | ||
|
|
||
| bool Utility::isLittleEndian() { | ||
| int num = 1; |
There was a problem hiding this comment.
absl already has a define for this which I think we implicitly include. Can we just use that instead of reimplementing the logic?
| std::begin(result)); | ||
| absl::uint128 Ipv6Instance::Ipv6Helper::address() const { | ||
| absl::uint128 result{0}; | ||
| memcpy(&result, &address_.sin6_addr.s6_addr, 16); |
There was a problem hiding this comment.
I would add a static_assert everywhere you do memcpy to make sure sizeof(absl::uint128) is what you expect, and then potentially use sizeof(absl::uint128) instead of 16.
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
|
|
||
| absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { | ||
| // TODO(ccaraman): Support Ip6ntohl for big-endian. | ||
| ASSERT(ABSL_IS_LITTLE_ENDIAN); |
There was a problem hiding this comment.
I would make both this assert and the other similar ones static_assert. We should just prevent the code from compiling on big endian systems until we implement this. With static_assert, the compilation message will be very clear also, much like #error
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
alyssawilk
left a comment
There was a problem hiding this comment.
Thank you so much for doing this as its own PR with preexisting tests - it's much easier to trust the code when I don't feel responsible for catching bitmath bugs by eye :-)
| std::numeric_limits<uint64_t>::max()); | ||
| EXPECT_EQ(max_int, address.ip()->ipv6()->address()); | ||
| EXPECT_EQ(max_int, Utility::Ip6ntohl(address.ip()->ipv6()->address())); | ||
| } |
There was a problem hiding this comment.
Optional but I'm a big fan of RNG code for tests like this. What would you think of setting low and high bytes based on TestRandomGenerator and making sure if you ntohl and htonl you end up with the original?
There was a problem hiding this comment.
Yes, that sounds good. I'll update the tests.
| @@ -200,21 +185,17 @@ InstanceConstSharedPtr CidrRange::truncateIpAddressAndLength(InstanceConstShared | |||
| sockaddr_in6 sa6; | |||
There was a problem hiding this comment.
Should we update the comment "but we don't have a uint128_t available."?
There was a problem hiding this comment.
Yes, I'll remove that.
| absl::uint128 max_int = absl::Uint128Max(); | ||
| // Shifting the value to the left set all bits between 128-length and 128 to zero. | ||
| max_int <<= (128 - length); | ||
| ip6 &= max_int; |
| } | ||
|
|
||
| absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { | ||
| // TODO(ccaraman): Support Ip6ntohl for big-endian. |
There was a problem hiding this comment.
This one is up to Matt and you but I wouldn't even TODO big-endian support unless we have a big-endian machine to test on just because I'd be concerned we'd screw something up somewhere else without being able to test.
There was a problem hiding this comment.
I was thinking we would be testing this on Google import but looks like that's specifically the Little Endian flavor of PPC (ppc64le). Some kind of compile time assert is probably sufficient to avoid surprises if someone manages to get Envoy build on a BE machine.
There was a problem hiding this comment.
No real preference on keeping the TODO or removing it. Will leave it up to you all. I basically figured that with the static_assert if someone cares they can come along and remove the static assert, add appropriate code, and test it.
There was a problem hiding this comment.
I'm going to leave the TODO. I think it helps future contributors know that this is something that Envoy wants to support at a future date.
| for (int i = 0; i < 16; i++) { | ||
| result <<= 8; | ||
| result |= (data & 0x000000000000000000000000000000FF); | ||
| data >>= 8; |
There was a problem hiding this comment.
optional : internally I think we roughly return uint128(htonl(input.low), htonl(input.high)) which obviously only works if htonl is flipping bits. If this is only going to be called for little endian switching might save some operations but I'm also fine leaving as is since if we add big endian support we'd need rename it something awful like flipOrderForLittleEndian to make it clear :-P
There was a problem hiding this comment.
I'm going to leave it as is.
Signed-off-by: Constance Caramanolis <ccaramanolis@lyft.com>
This patch resolves the TODO from envoyproxy#2431. Tests pass on a big-endian machine (IBM Z). Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
This patch resolves the TODO from #2431. Tests pass on a big-endian machine (IBM Z). Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Signed-off-by: Douglas Reid <douglas-reid@users.noreply.github.com>
This patch resolves the TODO from envoyproxy/envoy#2431. Tests pass on a big-endian machine (IBM Z). Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Description: Change IPv6 to return absl::uint128 instead of array of uint8_t. Equivalent ntohl and htonl have been implemented in Utility.
Risk Level: Low.
Testing: Existing Ipv6 tests and extended utility unit tests to cover new method.