This is an automated email from the ASF dual-hosted git repository. aweisberg pushed a commit to branch cassandra-17945-4.1-guest in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 57c8e686673d15f84183062df6e411a6191f6b26 Author: Andy Tolbert <6889771+tolber...@users.noreply.github.com> AuthorDate: Tue Oct 4 12:02:26 2022 -0500 Update StorageService.getNativeaddress to handle IPv6 addresses StorageService.getNativeaddress does not currently correctly handle IPv6 addresses correctly when NATIVE_ADDRESS_AND_PORT are not present in that it simply concatenates the IP address with the default native port, e.g.: 0:0:0:0:0:0:5a:3:9042 This does not parse into an InetSocketAddress as the address and port can't be disambiguated. Such a case would usually be present when there are 3.x nodes present in a cluster with 4.0 nodes. Change updates RPC_ADDRESS and else case to create InetAddressAndPort instances with DatabaseDescriptor.getNativeTransportPort and returns the getHostAddress(withPort) which properly bracket encodes the address, e.g.: [0:0:0:0:0:0:5a:3]:9042 which can be parsed as an InetSocketAddress. --- .../apache/cassandra/service/StorageService.java | 27 +++++++++++++++++++--- .../service/StorageServiceServerTest.java | 22 ++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 0d0ede5ab7..b39c049c88 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -2136,10 +2136,31 @@ public class StorageService extends NotificationBroadcasterSupport implements IE throw new RuntimeException(e); } } - else if (Gossiper.instance.getEndpointStateForEndpoint(endpoint).getApplicationState(ApplicationState.RPC_ADDRESS) == null) - return endpoint.getAddress().getHostAddress() + ":" + DatabaseDescriptor.getNativeTransportPort(); else - return Gossiper.instance.getEndpointStateForEndpoint(endpoint).getApplicationState(ApplicationState.RPC_ADDRESS).value + ":" + DatabaseDescriptor.getNativeTransportPort(); + { + final String ipAddress; + // If RPC_ADDRESS present in gossip for this endpoint use it. This is expected for 3.x nodes. + if (Gossiper.instance.getEndpointStateForEndpoint(endpoint).getApplicationState(ApplicationState.RPC_ADDRESS) != null) + { + ipAddress = Gossiper.instance.getEndpointStateForEndpoint(endpoint).getApplicationState(ApplicationState.RPC_ADDRESS).value; + } + else + { + // otherwise just use the IP of the endpoint itself. + ipAddress = endpoint.getHostAddress(false); + } + + // include the configured native_transport_port. + try + { + InetAddressAndPort address = InetAddressAndPort.getByNameOverrideDefaults(ipAddress, DatabaseDescriptor.getNativeTransportPort()); + return address.getHostAddress(withPort); + } + catch (UnknownHostException e) + { + throw new RuntimeException(e); + } + } } public Map<List<String>, List<String>> getRangeToRpcaddressMap(String keyspace) diff --git a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java index c8739ae1bc..119b8104d4 100644 --- a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java +++ b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java @@ -572,6 +572,28 @@ public class StorageServiceServerTest assertEquals("127.0.0.3:666", StorageService.instance.getNativeaddress(internalAddress, true)); } + @Test + public void testGetNativeAddressIPV6() throws Exception + { + // Ensure IPv6 addresses are properly bracketed in RFC2732 (https://datatracker.ietf.org/doc/html/rfc2732) format when including ports. + // See https://issues.apache.org/jira/browse/CASSANDRA-17945 for more context. + String internalAddressIPV6String = "[0:0:0:0:0:0:0:3]:666"; + InetAddressAndPort internalAddressIPV6 = InetAddressAndPort.getByName(internalAddressIPV6String); + Gossiper.instance.addSavedEndpoint(internalAddressIPV6); + + //Default to using the provided address with the configured port + assertEquals("[0:0:0:0:0:0:0:3]:" + DatabaseDescriptor.getNativeTransportPort(), StorageService.instance.getNativeaddress(internalAddressIPV6, true)); + + VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(Murmur3Partitioner.instance); + //If RPC_ADDRESS is present with an IPv6 address, we should properly bracket encode the IP with the configured port. + Gossiper.instance.getEndpointStateForEndpoint(internalAddressIPV6).addApplicationState(ApplicationState.RPC_ADDRESS, valueFactory.rpcaddress(InetAddress.getByName("0:0:0:0:0:0:5a:3"))); + assertEquals("[0:0:0:0:0:0:5a:3]:" + DatabaseDescriptor.getNativeTransportPort(), StorageService.instance.getNativeaddress(internalAddressIPV6, true)); + + //If we have the address and port in gossip use that + Gossiper.instance.getEndpointStateForEndpoint(internalAddressIPV6).addApplicationState(ApplicationState.NATIVE_ADDRESS_AND_PORT, valueFactory.nativeaddressAndPort(InetAddressAndPort.getByName("[0:0:0:0:0:0:5c:3]:8675"))); + assertEquals("[0:0:0:0:0:0:5c:3]:8675", StorageService.instance.getNativeaddress(internalAddressIPV6, true)); + } + @Test public void testAuditLogEnableLoggerNotFound() throws Exception { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org