-
Notifications
You must be signed in to change notification settings - Fork 5.1k
ipv6: use absl:uint128 instead of array of uint_8 for address return. #2431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
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>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool, few comments
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whether the type is intrinsic or not, you should be able to just memcpy here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated all call paths to use memcpy instead.
source/common/network/utility.cc
Outdated
|
||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method is not needed. memcpy should work where this is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated all call paths to use memcpy.
source/common/network/utility.cc
Outdated
@@ -342,5 +342,30 @@ bool Utility::portInRangeList(const Address::Instance& address, const std::list< | |||
return false; | |||
} | |||
|
|||
absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { return flipOrder(address); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this break if Envoy is running on a big endian system?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been updated to have an assert on little endianess and a todo has been added to support big endian.
source/common/network/cidr_range.cc
Outdated
} | ||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use absl::Uint128Max()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Figured it out. There was an update 11 days ago to change kuint128max
to Uint128Max()
. I locally have the older absl.
source/common/network/cidr_range.cc
Outdated
max_int <<= (128 - length); | ||
ip6 &= max_int; | ||
|
||
std::array<uint8_t, 16> ip6_array = Utility::getArrayRepresentation(Utility::Ip6htonl(ip6)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can it be const std::array
source/common/network/utility.cc
Outdated
@@ -342,5 +342,30 @@ bool Utility::portInRangeList(const Address::Instance& address, const std::list< | |||
return false; | |||
} | |||
|
|||
absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { return flipOrder(address); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't this break if Envoy is running on a big endian system?
source/common/network/utility.h
Outdated
/** | ||
* 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: return type in @return
(here and the other functions in this file)
test/common/network/utility_test.cc
Outdated
EXPECT_EQ(expected_result, Utility::getArrayRepresentation(address.ip()->ipv6()->address())); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
source/common/network/utility.cc
Outdated
} | ||
|
||
bool Utility::isLittleEndian() { | ||
int num = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
source/common/network/utility.cc
Outdated
@@ -342,5 +346,28 @@ bool Utility::portInRangeList(const Address::Instance& address, const std::list< | |||
return false; | |||
} | |||
|
|||
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 :-)
test/common/network/utility_test.cc
Outdated
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we update the comment "but we don't have a uint128_t available."?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I'll remove that.
source/common/network/cidr_range.cc
Outdated
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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/max_int/mask/?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -342,5 +346,30 @@ bool Utility::portInRangeList(const Address::Instance& address, const std::list< | |||
return false; | |||
} | |||
|
|||
absl::uint128 Utility::Ip6ntohl(const absl::uint128& address) { | |||
// TODO(ccaraman): Support Ip6ntohl for big-endian. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.