From a4a1ed4357ac63624346813c114f68e77e490e9f Mon Sep 17 00:00:00 2001 From: zzz <zzz@mail.i2p> Date: Wed, 18 Jan 2012 02:01:59 +0000 Subject: [PATCH] - When a peer is shitlisted, fail all our tunnels where that peer is the adjacent hop. In particular this will remove outbound tunnels when we can't contact the first hop, and enable quicker recovery. --- router/java/src/net/i2p/router/Shitlist.java | 1 + .../net/i2p/router/TunnelManagerFacade.java | 3 ++ .../dummy/DummyTunnelManagerFacade.java | 1 + .../i2p/router/tunnel/pool/TunnelPool.java | 37 ++++++++++--- .../router/tunnel/pool/TunnelPoolManager.java | 53 +++++++++++++++++++ 5 files changed, 88 insertions(+), 7 deletions(-) diff --git a/router/java/src/net/i2p/router/Shitlist.java b/router/java/src/net/i2p/router/Shitlist.java index 7b182d1054..92e78d3de2 100644 --- a/router/java/src/net/i2p/router/Shitlist.java +++ b/router/java/src/net/i2p/router/Shitlist.java @@ -198,6 +198,7 @@ public class Shitlist { if (transport == null) { // we hate the peer on *any* transport _context.netDb().fail(peer); + _context.tunnelManager().fail(peer); } //_context.tunnelManager().peerFailed(peer); //_context.messageRegistry().peerFailed(peer); diff --git a/router/java/src/net/i2p/router/TunnelManagerFacade.java b/router/java/src/net/i2p/router/TunnelManagerFacade.java index ae54f6077d..5e00d7010d 100644 --- a/router/java/src/net/i2p/router/TunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/TunnelManagerFacade.java @@ -165,4 +165,7 @@ public interface TunnelManagerFacade extends Service { public TunnelPool getInboundExploratoryPool(); /** for TunnelRenderer in router console */ public TunnelPool getOutboundExploratoryPool(); + + /** @since 0.8.13 */ + public void fail(Hash peer); } diff --git a/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java b/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java index b1574738cb..221f2d9e93 100644 --- a/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java +++ b/router/java/src/net/i2p/router/dummy/DummyTunnelManagerFacade.java @@ -70,4 +70,5 @@ public class DummyTunnelManagerFacade implements TunnelManagerFacade { public Map<Hash, TunnelPool> getOutboundClientPools() { return null; } public TunnelPool getInboundExploratoryPool() { return null; } public TunnelPool getOutboundExploratoryPool() { return null; } + public void fail(Hash peer) {} } diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java index c5397580f1..753f931bcb 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPool.java @@ -486,8 +486,30 @@ public class TunnelPool { } } - /** This may be called multiple times from TestJob */ - void tunnelFailed(PooledTunnelCreatorConfig cfg) { + /** + * Remove the tunnel and blame all the peers (not necessarily equally). + * This may be called multiple times from TestJob. + */ + void tunnelFailed(TunnelInfo cfg) { + fail(cfg); + tellProfileFailed(cfg); + } + + /** + * Remove the tunnel and blame only one peer. + * This may be called multiple times. + * + * @since 0.8.13 + */ + void tunnelFailed(TunnelInfo cfg, Hash blamePeer) { + fail(cfg); + _context.profileManager().tunnelFailed(blamePeer, 100); + } + + /** + * Remove the tunnel. + */ + private void fail(TunnelInfo cfg) { if (_log.shouldLog(Log.WARN)) _log.warn(toString() + ": Tunnel failed: " + cfg); LeaseSet ls = null; @@ -504,7 +526,6 @@ public class TunnelPool { } _manager.tunnelFailed(); - tellProfileFailed(cfg); _lifetimeProcessed += cfg.getProcessedMessagesCount(); updateRate(); @@ -516,9 +537,11 @@ public class TunnelPool { } } - // Blame all the other peers in the tunnel, with a probability - // inversely related to the tunnel length - private void tellProfileFailed(PooledTunnelCreatorConfig cfg) { + /** + * Blame all the other peers in the tunnel, with a probability + * inversely related to the tunnel length + */ + private void tellProfileFailed(TunnelInfo cfg) { int len = cfg.getLength(); if (len < 2) return; @@ -543,7 +566,7 @@ public class TunnelPool { } } - void updateRate() { + private void updateRate() { long now = _context.clock().now(); long et = now - _lastRateUpdate; if (et > 2*60*1000) { diff --git a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java index 8df88c8b0b..56f8a587bd 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java +++ b/router/java/src/net/i2p/router/tunnel/pool/TunnelPoolManager.java @@ -644,4 +644,57 @@ public class TunnelPoolManager implements TunnelManagerFacade { public TunnelPool getOutboundExploratoryPool() { return _outboundExploratory; } + + /** + * Fail all outbound tunnels with this peer as first hop, + * and all inbound tunnels with this peer as the last hop, + * baecause we can't contact it any more. + * This is most likely to be triggered by an outbound tunnel. + * + * @since 0.8.13 + */ + public void fail(Hash peer) { + if (_outboundExploratory != null) + failTunnelsWithFirstHop(_outboundExploratory, peer); + for (TunnelPool pool : _clientOutboundPools.values()) { + failTunnelsWithFirstHop(pool, peer); + } + if (_inboundExploratory != null) + failTunnelsWithLastHop(_inboundExploratory, peer); + for (TunnelPool pool : _clientInboundPools.values()) { + failTunnelsWithLastHop(pool, peer); + } + } + + /** + * Fail all (outbound) tunnels with this peer as first hop (not counting us) + * + * @since 0.8.13 + */ + private void failTunnelsWithFirstHop(TunnelPool pool, Hash peer) { + for (TunnelInfo tun : pool.listTunnels()) { + int len = tun.getLength(); + if (len > 1 && tun.getPeer(1).equals(peer)) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Removing OB tunnel, first hop shitlisted: " + tun); + pool.tunnelFailed(tun, peer); + } + } + } + + /** + * Fail all (inbound) tunnels with this peer as last hop (not counting us) + * + * @since 0.8.13 + */ + private void failTunnelsWithLastHop(TunnelPool pool, Hash peer) { + for (TunnelInfo tun : pool.listTunnels()) { + int len = tun.getLength(); + if (len > 1 && tun.getPeer(len - 2).equals(peer)) { + if (_log.shouldLog(Log.WARN)) + _log.warn("Removing IB tunnel, prev. hop shitlisted: " + tun); + pool.tunnelFailed(tun, peer); + } + } + } } -- GitLab