forked from I2P_Developers/i2p.i2p
Tunnel building:
- Don't count zero-hop tunnels as part of the pool when building - Don't build more than one zero-hop tunnel in a pool - Assume high build failure rate for new installs - Reduce threshold for tunnel length override
This commit is contained in:
@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Monotone";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 5;
|
||||
public final static long BUILD = 6;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
@ -111,10 +111,7 @@ public class TunnelPoolSettings {
|
||||
_lengthVariance = _isExploratory ? DEFAULT_OB_EXPL_LENGTH_VARIANCE : DEFAULT_LENGTH_VARIANCE;
|
||||
}
|
||||
_lengthOverride = -1;
|
||||
if (_isExploratory)
|
||||
_allowZeroHop = true;
|
||||
else
|
||||
_allowZeroHop = DEFAULT_ALLOW_ZERO_HOP;
|
||||
_allowZeroHop = DEFAULT_ALLOW_ZERO_HOP;
|
||||
_IPRestriction = DEFAULT_IP_RESTRICTION;
|
||||
_unknownOptions = new Properties();
|
||||
_randomKey = generateRandomKey();
|
||||
@ -162,7 +159,7 @@ public class TunnelPoolSettings {
|
||||
/**
|
||||
* If there are no tunnels to build with, will this pool allow 0 hop tunnels?
|
||||
*
|
||||
* Always true for exploratory.
|
||||
* As of 0.9.44, same goes for exploratory:
|
||||
* Prior to 0.9.35, generally true for client.
|
||||
* As of 0.9.35, generally false for client, but true if
|
||||
* getLength() + Math.min(getLengthVariance(), 0) <= 0,
|
||||
|
@ -338,8 +338,9 @@ class BuildExecutor implements Runnable {
|
||||
if (!pool.isAlive())
|
||||
continue;
|
||||
int howMany = pool.countHowManyToBuild();
|
||||
for (int j = 0; j < howMany; j++)
|
||||
for (int j = 0; j < howMany; j++) {
|
||||
wanted.add(pool);
|
||||
}
|
||||
}
|
||||
|
||||
// allowed() also expires timed out requests (for new style requests)
|
||||
@ -500,19 +501,18 @@ class BuildExecutor implements Runnable {
|
||||
* @return number of tunnels allowed after processing these zero hop tunnels (almost always the same as before)
|
||||
*/
|
||||
private int buildZeroHopTunnels(List<TunnelPool> wanted, int allowed) {
|
||||
for (int i = 0; i < wanted.size(); i++) {
|
||||
TunnelPool pool = wanted.get(0);
|
||||
for (Iterator<TunnelPool> iter = wanted.iterator(); iter.hasNext(); ) {
|
||||
TunnelPool pool = iter.next();
|
||||
if (pool.getSettings().getLength() == 0) {
|
||||
PooledTunnelCreatorConfig cfg = pool.configureNewTunnel();
|
||||
if (cfg != null) {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Configuring short tunnel " + i + " for " + pool + ": " + cfg);
|
||||
_log.debug("Configuring short tunnel for " + pool + ": " + cfg);
|
||||
buildTunnel(cfg);
|
||||
if (cfg.getLength() > 1) {
|
||||
allowed--; // oops... shouldn't have done that, but hey, its not that bad...
|
||||
}
|
||||
wanted.remove(i);
|
||||
i--;
|
||||
iter.remove();
|
||||
} else {
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Configured a null tunnel");
|
||||
@ -571,7 +571,7 @@ class BuildExecutor implements Runnable {
|
||||
_currentlyBuilding.notifyAll();
|
||||
}
|
||||
} else {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
if (cfg.getLength() > 1 && _log.shouldLog(Log.INFO))
|
||||
_log.info("Build complete really fast (" + buildTime + " ms) for tunnel: " + cfg);
|
||||
}
|
||||
|
||||
|
@ -47,13 +47,14 @@ public class TunnelPool {
|
||||
private long _lastRateUpdate;
|
||||
private long _lastLifetimeProcessed;
|
||||
private final String _rateName;
|
||||
private final long _firstInstalled;
|
||||
|
||||
private static final int TUNNEL_LIFETIME = 10*60*1000;
|
||||
/** if less than one success in this many, reduce quantity (exploratory only) */
|
||||
private static final int BUILD_TRIES_QUANTITY_OVERRIDE = 12;
|
||||
/** if less than one success in this many, reduce length (exploratory only) */
|
||||
private static final int BUILD_TRIES_LENGTH_OVERRIDE_1 = 10;
|
||||
private static final int BUILD_TRIES_LENGTH_OVERRIDE_2 = 18;
|
||||
private static final int BUILD_TRIES_LENGTH_OVERRIDE_1 = 8;
|
||||
private static final int BUILD_TRIES_LENGTH_OVERRIDE_2 = 12;
|
||||
private static final long STARTUP_TIME = 30*60*1000;
|
||||
|
||||
TunnelPool(RouterContext ctx, TunnelPoolManager mgr, TunnelPoolSettings settings, TunnelPeerSelector sel) {
|
||||
@ -66,6 +67,7 @@ public class TunnelPool {
|
||||
_expireSkew = _context.random().nextInt(90*1000);
|
||||
_started = System.currentTimeMillis();
|
||||
_lastRateUpdate = _started;
|
||||
_firstInstalled = ctx.getProperty("router.firstInstalled", 0L) + 60*60*1000;
|
||||
String name;
|
||||
if (_settings.isExploratory()) {
|
||||
name = "exploratory";
|
||||
@ -315,15 +317,15 @@ public class TunnelPool {
|
||||
|
||||
/**
|
||||
* Do we really need more fallbacks?
|
||||
* Used to prevent a zillion of them
|
||||
* Used to prevent a zillion of them.
|
||||
* Does not check config, only call if config allows zero hop.
|
||||
*/
|
||||
boolean needFallback() {
|
||||
int needed = getAdjustedTotalQuantity();
|
||||
int fallbacks = 0;
|
||||
long exp = _context.clock().now() + 120*1000;
|
||||
synchronized (_tunnels) {
|
||||
for (int i = 0; i < _tunnels.size(); i++) {
|
||||
TunnelInfo info = _tunnels.get(i);
|
||||
if (info.getLength() <= 1 && ++fallbacks >= needed)
|
||||
if (info.getLength() <= 1 && info.getExpiration() > exp)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -343,16 +345,22 @@ public class TunnelPool {
|
||||
* generate a lot of exploratory traffic.
|
||||
* TODO high-bandwidth non-floodfills do also...
|
||||
*
|
||||
* Also returns 1 if set for zero hop, client or exploratory.
|
||||
*
|
||||
* @since 0.8.11
|
||||
*/
|
||||
private int getAdjustedTotalQuantity() {
|
||||
if (_settings.getLength() == 0 && _settings.getLengthVariance() == 0)
|
||||
return 1;
|
||||
int rv = _settings.getTotalQuantity();
|
||||
if (!_settings.isExploratory())
|
||||
return rv;
|
||||
// TODO high-bw non-ff also
|
||||
if (_settings.isExploratory() && _context.netDb().floodfillEnabled() &&
|
||||
if (_context.netDb().floodfillEnabled() &&
|
||||
_context.router().getUptime() > 5*60*1000) {
|
||||
rv += 2;
|
||||
}
|
||||
if (_settings.isExploratory() && rv > 1) {
|
||||
if (rv > 1) {
|
||||
RateStat e = _context.statManager().getRate("tunnel.buildExploratoryExpire");
|
||||
RateStat r = _context.statManager().getRate("tunnel.buildExploratoryReject");
|
||||
RateStat s = _context.statManager().getRate("tunnel.buildExploratorySuccess");
|
||||
@ -373,7 +381,7 @@ public class TunnelPool {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_settings.isExploratory() && _context.router().getUptime() < STARTUP_TIME) {
|
||||
if (_context.router().getUptime() < STARTUP_TIME) {
|
||||
// more exploratory during startup, when we are refreshing the netdb RIs
|
||||
rv++;
|
||||
}
|
||||
@ -406,8 +414,9 @@ public class TunnelPool {
|
||||
long rc = rr.computeAverages(ra, false).getTotalEventCount();
|
||||
long sc = sr.computeAverages(ra, false).getTotalEventCount();
|
||||
long tot = ec + rc + sc;
|
||||
if (tot >= BUILD_TRIES_LENGTH_OVERRIDE_1) {
|
||||
long succ = 1000 * sc / tot;
|
||||
if (tot >= BUILD_TRIES_LENGTH_OVERRIDE_1 ||
|
||||
_firstInstalled > _context.clock().now()) {
|
||||
long succ = tot > 0 ? 1000 * sc / tot : 0;
|
||||
if (succ <= 1000 / BUILD_TRIES_LENGTH_OVERRIDE_1) {
|
||||
if (len > 2 && succ <= 1000 / BUILD_TRIES_LENGTH_OVERRIDE_2)
|
||||
_settings.setLengthOverride(len - 2);
|
||||
@ -644,8 +653,10 @@ public class TunnelPool {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a fallback tunnel is built
|
||||
* This will build a fallback (zero-hop) tunnel ONLY if
|
||||
* this pool is exploratory, or the settings allow it.
|
||||
*
|
||||
* @return true if a fallback tunnel is built
|
||||
*/
|
||||
boolean buildFallback() {
|
||||
int quantity = getAdjustedTotalQuantity();
|
||||
@ -656,7 +667,7 @@ public class TunnelPool {
|
||||
if (usable > 0)
|
||||
return false;
|
||||
|
||||
if (_settings.getAllowZeroHop()) {
|
||||
if (_settings.isExploratory() || _settings.getAllowZeroHop()) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info(toString() + ": building a fallback tunnel (usable: " + usable + " needed: " + quantity + ")");
|
||||
|
||||
@ -910,8 +921,6 @@ public class TunnelPool {
|
||||
inProgress = _inProgress.size();
|
||||
}
|
||||
int remainingWanted = (wanted - expireLater) - inProgress;
|
||||
if (allowZeroHop)
|
||||
remainingWanted -= fallback;
|
||||
|
||||
int rv = 0;
|
||||
int latesttime = 0;
|
||||
|
@ -586,11 +586,11 @@ public class TunnelPoolManager implements TunnelManagerFacade {
|
||||
}
|
||||
|
||||
private static class BootstrapPool extends JobImpl {
|
||||
private TunnelPool _pool;
|
||||
private final TunnelPool _pool;
|
||||
public BootstrapPool(RouterContext ctx, TunnelPool pool) {
|
||||
super(ctx);
|
||||
_pool = pool;
|
||||
getTiming().setStartAfter(ctx.clock().now() + 30*1000);
|
||||
getTiming().setStartAfter(ctx.clock().now() + 5*1000);
|
||||
}
|
||||
public String getName() { return "Bootstrap tunnel pool"; }
|
||||
public void runJob() {
|
||||
|
Reference in New Issue
Block a user