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