[PAN-1683] Fix handling of remote connection limit (#1676)

* Fix bugs

Fix remote connection fraction calculation (order of operations bug),
remove early return, allow all remote connections to be prohibited,
change disconnect reason to TOO_MANY_PEERS.

* Fix comment

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
mbaxter 5 years ago committed by Abdelhamid Bakhta
parent 12db3069de
commit 82ec73f956
  1. 4
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/config/RlpxConfiguration.java
  2. 7
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgent.java
  3. 131
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/rlpx/RlpxAgentTest.java

@ -102,8 +102,8 @@ public class RlpxConfiguration {
public RlpxConfiguration setFractionRemoteWireConnectionsAllowed(
final double fractionRemoteWireConnectionsAllowed) {
checkState(
fractionRemoteWireConnectionsAllowed > 0.0,
"Fraction of remote connections allowed must be positive.");
fractionRemoteWireConnectionsAllowed >= 0.0 && fractionRemoteWireConnectionsAllowed <= 1.0,
"Fraction of remote connections allowed must be between 0.0 and 1.0 (inclusive).");
this.fractionRemoteWireConnectionsAllowed = fractionRemoteWireConnectionsAllowed;
return this;
}

@ -341,7 +341,7 @@ public class RlpxAgent {
LOG.warn(
"Fraction of remotely initiated connection is too high, rejecting incoming connection. (max ratio allowed: {})",
fractionRemoteConnectionsAllowed);
peerConnection.disconnect(DisconnectReason.SUBPROTOCOL_TRIGGERED);
peerConnection.disconnect(DisconnectReason.TOO_MANY_PEERS);
return;
}
@ -397,11 +397,8 @@ public class RlpxAgent {
.filter(RlpxConnection::isActive)
.filter(RlpxConnection::initiatedRemotely)
.count());
if (remotelyInitiatedConnectionsCount == 0) {
return false;
}
final double fractionRemoteConnections =
(double) remotelyInitiatedConnectionsCount + 1 / (double) maxPeers;
(double) (remotelyInitiatedConnectionsCount + 1) / (double) maxPeers;
return fractionRemoteConnections > fractionRemoteConnectionsAllowed;
}

@ -61,6 +61,7 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Stream;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class RlpxAgentTest {
@ -320,19 +321,122 @@ public class RlpxAgentTest {
}
@Test
public void connect_failsWhenFractionOfRemoteConnectionsTooHigh() {
startAgentWithMaxPeersAndEnableLimitRemoteConnections(3);
// Connect 1 peer (locally initiated)
agent.connect(createPeer());
// Connect 1 peer (remotely initiated)
connectionInitializer.simulateIncomingConnection(connection(createPeer()));
// Add remotely initiated connection, this one must be rejected because the fraction of remote
// connections is 0.5
public void incomingConnection_afterMaxRemotelyInitiatedConnectionsHaveBeenEstablished() {
final int maxPeers = 10;
final int maxRemotePeers = 8;
final double maxRemotePeersFraction = (double) maxRemotePeers / (double) maxPeers;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// Connect max remote peers
for (int i = 0; i < maxRemotePeers; i++) {
final Peer remotelyInitiatedPeer = createPeer();
final MockPeerConnection incomingConnection = connection(remotelyInitiatedPeer);
connectionInitializer.simulateIncomingConnection(incomingConnection);
assertThat(incomingConnection.getDisconnectReason()).isEmpty();
}
// Next remote connection should be rejected
final Peer remotelyInitiatedPeer = createPeer();
final MockPeerConnection incomingConnection = connection(remotelyInitiatedPeer);
connectionInitializer.simulateIncomingConnection(incomingConnection);
assertThat(incomingConnection.getDisconnectReason())
.contains(DisconnectReason.SUBPROTOCOL_TRIGGERED);
assertThat(incomingConnection.getDisconnectReason()).contains(DisconnectReason.TOO_MANY_PEERS);
}
@Test
public void connect_afterMaxRemotelyInitiatedConnectionsHaveBeenEstablished() {
final int maxPeers = 10;
final int maxRemotePeers = 8;
final double maxRemotePeersFraction = (double) maxRemotePeers / (double) maxPeers;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// Connect max remote peers
for (int i = 0; i < maxRemotePeers; i++) {
final Peer remotelyInitiatedPeer = createPeer();
final MockPeerConnection incomingConnection = connection(remotelyInitiatedPeer);
connectionInitializer.simulateIncomingConnection(incomingConnection);
assertThat(incomingConnection.getDisconnectReason()).isEmpty();
}
// Subsequent local connection should be permitted up to maxPeers
for (int i = 0; i < (maxPeers - maxRemotePeers); i++) {
final Peer peer = createPeer();
final CompletableFuture<PeerConnection> connection = agent.connect(peer);
assertThat(connection).isDone();
assertThat(connection).isNotCompletedExceptionally();
assertThat(agent.getPeerConnection(peer)).contains(connection);
}
}
@Test
public void incomingConnection_withMaxRemotelyInitiatedConnectionsAt100Percent() {
final int maxPeers = 10;
final double maxRemotePeersFraction = 1.0;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// Connect max remote peers
for (int i = 0; i < maxPeers; i++) {
final Peer remotelyInitiatedPeer = createPeer();
final MockPeerConnection incomingConnection = connection(remotelyInitiatedPeer);
connectionInitializer.simulateIncomingConnection(incomingConnection);
assertThat(incomingConnection.getDisconnectReason()).isEmpty();
}
}
@Test
public void connect_withMaxRemotelyInitiatedConnectionsAt100Percent() {
final int maxPeers = 10;
final double maxRemotePeersFraction = 1.0;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// Connect max peers locally
for (int i = 0; i < maxPeers; i++) {
final Peer peer = createPeer();
final CompletableFuture<PeerConnection> connection = agent.connect(peer);
assertThat(connection).isDone();
assertThat(connection).isNotCompletedExceptionally();
assertThat(agent.getPeerConnection(peer)).contains(connection);
}
}
@Test
public void incomingConnection_withMaxRemotelyInitiatedConnectionsAtZeroPercent() {
final int maxPeers = 10;
final double maxRemotePeersFraction = 0.0;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// First remote connection should be rejected
final Peer remotelyInitiatedPeer = createPeer();
final MockPeerConnection incomingConnection = connection(remotelyInitiatedPeer);
connectionInitializer.simulateIncomingConnection(incomingConnection);
assertThat(incomingConnection.getDisconnectReason()).contains(DisconnectReason.TOO_MANY_PEERS);
}
@Test
public void connect_withMaxRemotelyInitiatedConnectionsAtZeroPercent() {
final int maxPeers = 10;
final double maxRemotePeersFraction = 0.0;
config.setLimitRemoteWireConnectionsEnabled(true);
config.setFractionRemoteWireConnectionsAllowed(maxRemotePeersFraction);
startAgentWithMaxPeers(maxPeers);
// Connect max local peers
for (int i = 0; i < maxPeers; i++) {
final Peer peer = createPeer();
final CompletableFuture<PeerConnection> connection = agent.connect(peer);
assertThat(connection).isDone();
assertThat(connection).isNotCompletedExceptionally();
assertThat(agent.getPeerConnection(peer)).contains(connection);
}
}
@Test
@ -394,6 +498,7 @@ public class RlpxAgentTest {
}
@Test
@Ignore("Ignore while PAN-1683 is being reworked")
public void incomingConnection_maxPeersExceeded_incomingConnectionExemptFromLimits()
throws ExecutionException, InterruptedException {
final Peer peerA = createPeer();
@ -448,6 +553,7 @@ public class RlpxAgentTest {
}
@Test
@Ignore("Ignore while PAN-1683 is being reworked")
public void incomingConnection_maxPeersExceeded_allConnectionsExemptFromLimits()
throws ExecutionException, InterruptedException {
final Peer peerA = createPeer();
@ -818,11 +924,6 @@ public class RlpxAgentTest {
startAgent();
}
private void startAgentWithMaxPeersAndEnableLimitRemoteConnections(final int maxPeers) {
config.setLimitRemoteWireConnectionsEnabled(true);
startAgentWithMaxPeers(maxPeers);
}
private void startAgent(final BytesValue nodeId) {
agent.start();
localNode.setEnode(enodeBuilder().nodeId(nodeId).build());

Loading…
Cancel
Save