Skip to content

Commit

Permalink
refactor: Clean up, match presto, and optimize ipprefix string -> ipp…
Browse files Browse the repository at this point in the history
…refix (#11670)

Summary:
Clean up the code for converting from string->ipprefix.
Also removed all unnecessary error message processing to match java presto's output.
Removed unnecessary variables
Enable IPPREFIX cast test

Pull Request resolved: #11670

Reviewed By: yuandagits

Differential Revision: D66682847

Pulled By: xiaoxmeng

fbshipit-source-id: b31ff7c563a9e7e3c14ec42ef80537e64773fc8f
  • Loading branch information
mohsaka authored and facebook-github-bot committed Dec 3, 2024
1 parent 0a685b1 commit c542ebc
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 87 deletions.
1 change: 1 addition & 0 deletions velox/functions/prestosql/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ add_executable(
HyperLogLogFunctionsTest.cpp
InPredicateTest.cpp
IPAddressCastTest.cpp
IPPrefixCastTest.cpp
JsonCastTest.cpp
JsonExtractScalarTest.cpp
JsonFunctionsTest.cpp
Expand Down
110 changes: 23 additions & 87 deletions velox/functions/prestosql/types/IPPrefixType.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,55 +38,6 @@ auto splitIpSlashCidr(folly::StringPiece ipSlashCidr) {
folly::split('/', ipSlashCidr, vec);
return vec;
}

Status handleFailedToCreateNetworkError(
folly::StringPiece ipaddress,
folly::CIDRNetworkError error) {
if (threadSkipErrorDetails()) {
return Status::UserError();
}

switch (error) {
case folly::CIDRNetworkError::INVALID_DEFAULT_CIDR: {
return Status::UserError(
"defaultCidr must be <= std::numeric_limits<uint8_t>::max()");
}
case folly::CIDRNetworkError::INVALID_IP_SLASH_CIDR: {
return Status::UserError(
"Invalid IP address string received. Received string:{} of length:{}",
ipaddress,
ipaddress.size());
}
case folly::CIDRNetworkError::INVALID_IP: {
const auto vec = splitIpSlashCidr(ipaddress);
return Status::UserError(
"Invalid IP address '{}'", vec.size() > 0 ? vec.at(0) : "");
}
case folly::CIDRNetworkError::INVALID_CIDR: {
auto const vec = splitIpSlashCidr(ipaddress);
return Status::UserError(
"Mask value '{}' not a valid mask", vec.size() > 1 ? vec.at(1) : "");
}
case folly::CIDRNetworkError::CIDR_MISMATCH: {
const auto vec = splitIpSlashCidr(ipaddress);
if (!vec.empty()) {
const auto subnet = folly::IPAddress::tryFromString(vec.at(0)).value();
return Status::UserError(
"CIDR value '{}' is > network bit count '{}'",
vec.size() == 2 ? vec.at(1)
: folly::to<std::string>(
subnet.isV4() ? ipaddress::kIPV4Bits
: ipaddress::kIPV6Bits),
subnet.bitCount());
}
return Status::UserError(
"Invalid IP address of size:{} received", ipaddress.size());
}
default:
return Status::UserError(
"Unknown parsing error when parsing IP address: {} ", ipaddress);
}
}
} // namespace

inline folly::Expected<std::pair<int128_t, int8_t>, Status>
Expand All @@ -97,55 +48,40 @@ tryParseIpPrefixString(folly::StringPiece ipprefixString) {
threadSkipErrorDetails()
? Status::UserError()
: Status::UserError(
"Invalid CIDR IP address specified. Expected IP/PREFIX format, got: {}",
ipprefixString));
"Cannot cast value to IPPREFIX: {}", ipprefixString));
}

auto tryCdirNetwork = folly::IPAddress::tryCreateNetwork(
ipprefixString, /*defaultCidr*/ -1, /*applyMask*/ false);

if (tryCdirNetwork.hasError()) {
return folly::makeUnexpected(handleFailedToCreateNetworkError(
ipprefixString, std::move(tryCdirNetwork.error())));
return folly::makeUnexpected(
threadSkipErrorDetails()
? Status::UserError()
: Status::UserError(
"Cannot cast value to IPPREFIX: {}", ipprefixString));
}

folly::ByteArray16 addrBytes;
const auto& cdirNetwork = tryCdirNetwork.value();
if (cdirNetwork.first.isIPv4Mapped() || cdirNetwork.first.isV4()) {
// Validate that the prefix value is <= 32 for ipv4
if (cdirNetwork.second > ipaddress::kIPV4Bits) {
return folly::makeUnexpected(
threadSkipErrorDetails()
? Status::UserError()
: Status::UserError(
"CIDR value '{}' is > network bit count '{}'",
cdirNetwork.second,
ipaddress::kIPV4Bits));
}
auto ipv4Addr = folly::IPAddress::createIPv4(cdirNetwork.first);
auto ipv4AddrWithMask = ipv4Addr.mask(cdirNetwork.second);
auto ipv6Addr = ipv4AddrWithMask.createIPv6();
addrBytes = ipv6Addr.toByteArray();
} else {
// Validate that the prefix value is <= 128 for ipv6
if (cdirNetwork.second > ipaddress::kIPV6Bits) {
return folly::makeUnexpected(
threadSkipErrorDetails()
? Status::UserError()
: Status::UserError(
"CIDR value '{}' is > network bit count '{}'",
cdirNetwork.second,
ipaddress::kIPV6Bits));
}
auto ipv6Addr = folly::IPAddress::createIPv6(cdirNetwork.first);
auto ipv6AddrWithMask = ipv6Addr.mask(cdirNetwork.second);
addrBytes = ipv6AddrWithMask.toByteArray();
auto [ip, prefix] = tryCdirNetwork.value();
if (prefix > ((ip.isIPv4Mapped() || ip.isV4()) ? ipaddress::kIPV4Bits
: ipaddress::kIPV6Bits)) {
return folly::makeUnexpected(
threadSkipErrorDetails()
? Status::UserError()
: Status::UserError(
"Cannot cast value to IPPREFIX: {}", ipprefixString));
}

int128_t intAddr;
// Similar to IPAdressType, assume Velox is always on little endian systems
auto addrBytes = (ip.isIPv4Mapped() || ip.isV4())
? folly::IPAddress::createIPv4(ip).mask(prefix).createIPv6().toByteArray()
: folly::IPAddress::createIPv6(ip).mask(prefix).toByteArray();

std::reverse(addrBytes.begin(), addrBytes.end());

int128_t intAddr = 0;
static_assert(sizeof(intAddr) == ipaddress::kIPAddressBytes);
memcpy(&intAddr, &addrBytes, ipaddress::kIPAddressBytes);
return std::make_pair(intAddr, cdirNetwork.second);
return std::make_pair(intAddr, prefix);
}
}; // namespace ipaddress

Expand Down

0 comments on commit c542ebc

Please sign in to comment.