* Reachability:

- Call the previously unused profile.tunnelTestFailed()
        (redefined to include a probability argument)
        and severely downgrade a peer's capacity upon failures,
        depending on tunnel length and direction.
        This will help push unreachable and malicious peers
        out of the High Capacity tier.
      - Put recent fail rate on profiles.jsp
    * ProfileOrganizer: Logging cleanup
    * eepsite_index.html: Update add-host and jump links
    * HTTP Proxy: Remove trevorreznik jump server from list
This commit is contained in:
zzz
2008-05-20 12:48:41 +00:00
parent 6c7691cecb
commit 7e3800a5cb
11 changed files with 87 additions and 27 deletions

View File

@ -649,7 +649,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
"http://i2host.i2p/cgi-bin/i2hostjump?",
// "http://orion.i2p/jump/",
"http://stats.i2p/cgi-bin/jump.cgi?a=",
"http://trevorreznik.i2p/cgi-bin/jump.php?hostname=",
// "http://trevorreznik.i2p/cgi-bin/jump.php?hostname=",
"http://i2jump.i2p/"
};
private static void writeErrorMessage(byte[] errMessage, OutputStream out, String targetRequest,

View File

@ -1,3 +1,16 @@
2008-05-20 zzz
* Reachability:
- Call the previously unused profile.tunnelTestFailed()
(redefined to include a probability argument)
and severely downgrade a peer's capacity upon failures,
depending on tunnel length and direction.
This will help push unreachable and malicious peers
out of the High Capacity tier.
- Put recent fail rate on profiles.jsp
* ProfileOrganizer: Logging cleanup
* eepsite_index.html: Update add-host and jump links
* HTTP Proxy: Remove trevorreznik jump server from list
2008-05-20 welterde
* implemented PrivateKeyFile

View File

@ -55,9 +55,7 @@
such as <a href="http://stats.i2p/">stats.i2p</a>.
That is, you must enter
your eepsite name and key into a web interface on one or more of these sites.
Here is <a href="http://stats.i2p/i2p/addkey.html">the key entry form at stats.i2p</a>,
and
here is <a href="http://trevorreznik.i2p/host-database/">the key entry form at trevorreznik.i2p</a>.
Here is <a href="http://stats.i2p/i2p/addkey.html">the key entry form at stats.i2p</a>.
Again, your key is the entire "Local destination" key on the
<a href="http://localhost:7657/i2ptunnel/edit.jsp?tunnel=3">eepsite i2ptunnel configuration page</a>.
Be sure you get the whole thing, ending with "AAAA".
@ -70,14 +68,15 @@
and add a couple of these -
<a href="http://tino.i2p/hosts.txt">http://tino.i2p/hosts.txt</a>,
<a href="http://stats.i2p/cgi-bin/newhosts.txt">http://stats.i2p/cgi-bin/newhosts.txt</a>,
<a href="http://i2jump.i2p/hosts.txt">http://i2jump.i2p/hosts.txt</a>,
<a href="http://trevorreznik.i2p/hosts.txt">http://trevorreznik.i2p/hosts.txt</a> and hit "Save".
<a href="http://i2host.i2p/cgi-bin/i2hostetag">http://i2host.i2p/cgi-bin/i2hostetag</a>,
and hit "Save".
Now you will get updates too!
<li>If you are in a hurry and can't wait a few hours, you can tell people to use a "jump" address helper redirection service.
This will work within a few minutes of your entering the key to an address book.
This will work within a few minutes of your entering the key to an address book on the same site.
Test it yourself first by entering
http://stats.i2p/cgi-bin/jump.cgi?a=<i>something</i>.i2p or
or http://trevorreznik.i2p/cgi-bin/jump.php?hostname=<i>something</i>.i2p into your browser.
or http://i2host.i2p/cgi-bin/i2hostjump?<i>something</i>.i2p
into your browser.
Once it's working, then you can tell others to use it.
<li>Some people check eepsite lists such as
<a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> for new eepsites, so you may start getting

View File

@ -85,7 +85,7 @@ public interface ProfileManager {
* been the peer's fault however.
*
*/
void tunnelFailed(Hash peer);
void tunnelFailed(Hash peer, int pct);
/**
* Note that the peer was able to return the valid data for a db lookup

View File

@ -17,7 +17,7 @@ import net.i2p.CoreVersion;
public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-02-10 15:00:00 $";
public final static String VERSION = "0.6.1.33";
public final static long BUILD = 6;
public final static long BUILD = 7;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -103,8 +103,12 @@ public class CapacityCalculator extends Calculator {
double stretch = ((double)ESTIMATE_PERIOD) / period;
double val = eventCount * stretch;
long failed = 0;
// Let's say a failure is 4 times worse than a rejection.
// It's actually much worse than that, but with 2-hop tunnels and a 8-peer
// fast pool, for example, you have a 1/7 chance of being falsely blamed.
// We also don't want to drive everybody's capacity to zero, that isn't helpful.
if (curFailed != null)
failed = curFailed.getCurrentEventCount() + curFailed.getLastEventCount();
failed = (long) (0.5 + (4.0 * (curFailed.getCurrentTotalValue() + curFailed.getLastTotalValue()) / 100.0));
if (failed > 0) {
//if ( (period <= 10*60*1000) && (curFailed.getCurrentEventCount() > 0) )
// return 0.0d; // their tunnels have failed in the last 0-10 minutes

View File

@ -150,13 +150,14 @@ public class ProfileManagerImpl implements ProfileManager {
/**
* Note that the peer participated in a tunnel that failed. Its failure may not have
* been the peer's fault however.
* Blame the peer with a probability of pct/100.
*
*/
public void tunnelFailed(Hash peer) {
public void tunnelFailed(Hash peer, int pct) {
PeerProfile data = getProfile(peer);
if (data == null) return;
data.setLastHeardFrom(_context.clock().now());
data.getTunnelHistory().incrementFailed();
data.getTunnelHistory().incrementFailed(pct);
}
/**

View File

@ -563,6 +563,7 @@ public class ProfileOrganizer {
if (_log.shouldLog(Log.INFO))
_log.info("Profiles reorganized. averages: [integration: " + _thresholdIntegrationValue
+ ", capacity: " + _thresholdCapacityValue + ", speed: " + _thresholdSpeedValue + "]");
/*****
if (_log.shouldLog(Log.DEBUG)) {
StringBuffer buf = new StringBuffer(512);
for (Iterator iter = _strictCapacityOrder.iterator(); iter.hasNext(); ) {
@ -572,6 +573,7 @@ public class ProfileOrganizer {
_log.debug("Strictly organized (highest capacity first): " + buf.toString());
_log.debug("fast: " + _fastPeers.values());
}
*****/
}
long total = System.currentTimeMillis()-start;
@ -601,16 +603,18 @@ public class ProfileOrganizer {
if ( (!_fastPeers.containsKey(cur.getPeer())) && (!cur.getIsFailing()) ) {
if (!isSelectable(cur.getPeer())) {
// skip peers we dont have in the netDb
if (_log.shouldLog(Log.INFO))
_log.info("skip unknown peer from fast promotion: " + cur.getPeer().toBase64());
// if (_log.shouldLog(Log.INFO))
// _log.info("skip unknown peer from fast promotion: " + cur.getPeer().toBase64());
continue;
}
if (!cur.getIsActive()) {
// skip inactive
if (_log.shouldLog(Log.INFO))
_log.info("skip inactive peer from fast promotion: " + cur.getPeer().toBase64());
// if (_log.shouldLog(Log.INFO))
// _log.info("skip inactive peer from fast promotion: " + cur.getPeer().toBase64());
continue;
}
if (_log.shouldLog(Log.INFO))
_log.info("Fast promoting: " + cur.getPeer().toBase64());
_fastPeers.put(cur.getPeer(), cur);
// no need to remove it from any of the other groups, since if it is
// fast, it has a high capacity, and it is not failing
@ -969,8 +973,8 @@ public class ProfileOrganizer {
if (netDb == null) return true;
if (_context.router() == null) return true;
if ( (_context.shitlist() != null) && (_context.shitlist().isShitlisted(peer)) ) {
if (_log.shouldLog(Log.DEBUG))
_log.debug("Peer " + peer.toBase64() + " is shitlisted, dont select it");
// if (_log.shouldLog(Log.DEBUG))
// _log.debug("Peer " + peer.toBase64() + " is shitlisted, dont select it");
return false; // never select a shitlisted peer
}
@ -983,18 +987,18 @@ public class ProfileOrganizer {
} else {
boolean exclude = TunnelPeerSelector.shouldExclude(_context, info);
if (exclude) {
if (_log.shouldLog(Log.WARN))
_log.warn("Peer " + peer.toBase64() + " has capabilities or other stats suggesting we avoid it");
// if (_log.shouldLog(Log.WARN))
// _log.warn("Peer " + peer.toBase64() + " has capabilities or other stats suggesting we avoid it");
return false;
} else {
if (_log.shouldLog(Log.INFO))
_log.info("Peer " + peer.toBase64() + " is locally known, allowing its use");
// if (_log.shouldLog(Log.INFO))
// _log.info("Peer " + peer.toBase64() + " is locally known, allowing its use");
return true;
}
}
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Peer " + peer.toBase64() + " is NOT locally known, disallowing its use");
// if (_log.shouldLog(Log.WARN))
// _log.warn("Peer " + peer.toBase64() + " is NOT locally known, disallowing its use");
return false;
}
}

View File

@ -143,6 +143,14 @@ class ProfileOrganizerRenderer {
if (_context.shitlist().isShitlisted(peer)) buf.append("Shitlist");
if (prof.getIsFailing()) buf.append(" Failing");
if (_context.commSystem().wasUnreachable(peer)) buf.append(" Unreachable");
Rate failed = prof.getTunnelHistory().getFailedRate().getRate(30*60*1000);
long fails = failed.getCurrentEventCount() + failed.getLastEventCount();
if (fails > 0) {
Rate accepted = prof.getTunnelCreateResponseTime().getRate(30*60*1000);
long total = fails + accepted.getCurrentEventCount() + accepted.getLastEventCount();
if (total / fails <= 10) // hide if < 10%
buf.append(' ').append(fails).append('/').append(total).append(" Test Fails");
}
buf.append("&nbsp</td>");
//buf.append("<td><a href=\"/profile/").append(prof.getPeer().toBase64().substring(0, 32)).append("\">profile.txt</a> ");
//buf.append(" <a href=\"#").append(prof.getPeer().toBase64().substring(0, 32)).append("\">netDb</a></td>");

View File

@ -108,9 +108,12 @@ public class TunnelHistory {
// dont increment the reject rate in this case
}
}
public void incrementFailed() {
// Define this rate as the probability it really failed
// @param pct = probability * 100
public void incrementFailed(int pct) {
_lifetimeFailed++;
_failRate.addData(1, 1);
_failRate.addData(pct, 1);
_lastFailed = _context.clock().now();
}

View File

@ -332,6 +332,7 @@ public class TunnelPool {
}
_manager.tunnelFailed();
tellProfileFailed(cfg);
_lifetimeProcessed += cfg.getProcessedMessagesCount();
updateRate();
@ -343,6 +344,33 @@ 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) {
int len = cfg.getLength();
if (len < 2)
return;
int start = 0;
int end = len;
if (cfg.isInbound())
end--;
else
start++;
for (int i = start; i < end; i++) {
int pct = 100/(len-1);
// if inbound, it's probably the gateway's fault
if (cfg.isInbound() && len > 2) {
if (i == start)
pct *= 2;
else
pct /= 2;
}
if (_log.shouldLog(Log.WARN))
_log.warn(toString() + ": Blaming " + cfg.getPeer(i) + ' ' + pct + '%');
_context.profileManager().tunnelFailed(cfg.getPeer(i), pct);
}
}
void updateRate() {
long now = _context.clock().now();
long et = now - _lastRateUpdate;