This is an automated email from the ASF dual-hosted git repository. aweisberg pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra.git
commit 3bdd2caa22a0413929188536b41d8117177574fa Author: Andy Tolbert <6889771+tolber...@users.noreply.github.com> AuthorDate: Thu Oct 6 14:04:38 2022 -0400 Fix StorageService.getNativeaddress handling of 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. patch by Andy Tolbert; reviewed by Ariel Weisberg, Brandon Williams for CASSANDRA-17945 --- CHANGES.txt | 1 + .../apache/cassandra/service/StorageService.java | 27 +++++++++++++++++++--- .../service/StorageServiceServerTest.java | 22 ++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 15bc6413ad..d48edb9a4f 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 4.0.7 + * Fix StorageService.getNativeaddress handling of IPv6 addresses (CASSANDRA-17945) * Mitigate direct buffer memory OOM on replacements (CASSANDRA-17895) * Fix repair failure on assertion if two peers have overlapping mismatching ranges (CASSANDRA-17900) * Better handle null state in Gossip schema migration to avoid NPE (CASSANDRA-17864) diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 7e70e4ce20..b70347a301 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -1975,10 +1975,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.address.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 b5ddd35514..60bed4c64d 100644 --- a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java +++ b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java @@ -641,6 +641,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