* SSU/Reachability:

- Extend shitlist time from 4-8m to 40-60m
      - Add some shitlist logging
      - Don't shitlist twice when unreachable on all transports
      - Exclude netDb-listed unreachable peers from inbound tunnels;
        this won't help much since there are very few of these now
      - Remove 10s delay on inbound UDP connections used for the
        0.6.1.10 transition
      - Track and display UDP connection direction on peers.jsp
      - Show shitlist status in-line on profiles.jsp
This commit is contained in:
zzz
2008-04-16 20:51:57 +00:00
parent 5ba1e458c6
commit 2edd84e088
9 changed files with 83 additions and 31 deletions

View File

@ -1,3 +1,15 @@
2008-04-16 zzz
* SSU/Reachability:
- Extend shitlist time from 4-8m to 40-60m
- Add some shitlist logging
- Don't shitlist twice when unreachable on all transports
- Exclude netDb-listed unreachable peers from inbound tunnels;
this won't help much since there are very few of these now
- Remove 10s delay on inbound UDP connections used for the
0.6.1.10 transition
- Track and display UDP connection direction on peers.jsp
- Show shitlist status in-line on profiles.jsp
2008-04-15 zzz
* SSU Reachability/PeerTestManager:
- Back out strict peer ordering until we fix SSU

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.32";
public final static long BUILD = 17;
public final static long BUILD = 18;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -37,7 +37,7 @@ public class Shitlist {
Set transports;
}
public final static long SHITLIST_DURATION_MS = 4*60*1000; // 4 minute shitlist
public final static long SHITLIST_DURATION_MS = 40*60*1000; // 40 minute shitlist
public Shitlist(RouterContext context) {
_context = context;
@ -72,6 +72,8 @@ public class Shitlist {
if (prof != null)
prof.unshitlist();
_context.messageHistory().unshitlist(peer);
if (_log.shouldLog(Log.INFO))
_log.info("Unshitlisting router (expired) " + peer.toBase64());
}
requeue(30*1000);
@ -152,12 +154,13 @@ public class Shitlist {
public void unshitlistRouter(Hash peer, String transport) { unshitlistRouter(peer, true, transport); }
private void unshitlistRouter(Hash peer, boolean realUnshitlist, String transport) {
if (peer == null) return;
if (_log.shouldLog(Log.INFO))
_log.info("Unshitlisting router " + peer.toBase64()
if (_log.shouldLog(Log.DEBUG))
_log.debug("Calling unshitlistRouter " + peer.toBase64()
+ (transport != null ? "/" + transport : ""));
boolean fully = false;
Entry e;
synchronized (_entries) {
Entry e = (Entry)_entries.remove(peer);
e = (Entry)_entries.remove(peer);
if ( (e == null) || (e.transports == null) || (transport == null) || (e.transports.size() <= 1) ) {
// fully unshitlisted
fully = true;
@ -176,6 +179,9 @@ public class Shitlist {
prof.unshitlist();
}
_context.messageHistory().unshitlist(peer);
if (_log.shouldLog(Log.INFO) && e != null)
_log.info("Unshitlisting router " + peer.toBase64()
+ (transport != null ? "/" + transport : ""));
}
}
@ -209,6 +215,8 @@ public class Shitlist {
if (prof != null)
prof.unshitlist();
_context.messageHistory().unshitlist(peer);
if (_log.shouldLog(Log.INFO))
_log.info("Unshitlisting router (expired) " + peer.toBase64());
}
return rv;

View File

@ -134,7 +134,10 @@ class ProfileOrganizerRenderer {
buf.append("</td>");
buf.append("<td align=\"right\">").append(num(prof.getCapacityValue())).append("</td>");
buf.append("<td align=\"right\">").append(num(prof.getIntegrationValue())).append("</td>");
buf.append("<td align=\"right\">").append(prof.getIsFailing()).append("</td>");
buf.append("<td>");
if (_context.shitlist().isShitlisted(peer)) buf.append("Shitlist");
if (prof.getIsFailing()) buf.append(" Failing");
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>");
buf.append("<td nowrap><a href=\"netdb.jsp#").append(peer.toBase64().substring(0,6)).append("\">netDb</a>");

View File

@ -259,6 +259,9 @@ public class TransportManager implements TransportEventListener {
Transport t = (Transport)_transports.get(i);
if (t.isUnreachable(peer)) {
unreachableTransports++;
// this keeps GetBids() from shitlisting for "no common transports"
// right after we shitlisted for "unreachable on any transport" below...
msg.transportFailed(t.getStyle());
continue;
}
if (failedTransports.contains(t.getStyle())) {

View File

@ -431,6 +431,7 @@ public class EstablishmentManager {
peer.setRemotePeer(remote.calculateHash());
peer.setWeRelayToThemAs(state.getSentRelayTag());
peer.setTheyRelayToUsAs(0);
peer.setInbound();
if (_log.shouldLog(Log.DEBUG))
_log.debug("Handle completely established (inbound): " + state.getRemoteHostId().toString()
@ -451,9 +452,16 @@ public class EstablishmentManager {
* dont send our info immediately, just send a small data packet, and 5-10s later,
* if the peer isnt shitlisted, *then* send them our info. this will help kick off
* the oldnet
* The "oldnet" was < 0.6.1.10, it is long gone.
* The delay really slows down the network.
* The peer is unshitlisted and marked reachable by addRemotePeerState() which calls markReachable()
* so the check below is fairly pointless.
* If for some strange reason an oldnet router (NETWORK_ID == 1) does show up,
* it's handled in UDPTransport.messageReceived()
* (where it will get dropped, marked unreachable and shitlisted at that time).
*/
private void sendInboundComplete(PeerState peer) {
SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 10*1000);
// SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 10*1000);
if (_log.shouldLog(Log.INFO))
_log.info("Completing to the peer after confirm: " + peer);
DeliveryStatusMessage dsm = new DeliveryStatusMessage(_context);
@ -461,6 +469,7 @@ public class EstablishmentManager {
dsm.setMessageExpiration(_context.clock().now()+10*1000);
dsm.setMessageId(_context.random().nextLong(I2NPMessage.MAX_ID_VALUE));
_transport.send(dsm, peer);
SimpleTimer.getInstance().addEvent(new PublishToNewInbound(peer), 0);
}
private class PublishToNewInbound implements SimpleTimer.TimedEvent {
private PeerState _peer;

View File

@ -190,7 +190,9 @@ public class PeerState {
private volatile int _concurrentMessagesActive = 0;
/** how many concurrency rejections have we had in a row */
private volatile int _consecutiveRejections = 0;
/** is it inbound? **/
private boolean _isInbound;
private static final int DEFAULT_SEND_WINDOW_BYTES = 8*1024;
private static final int MINIMUM_WINDOW_BYTES = DEFAULT_SEND_WINDOW_BYTES;
private static final int MAX_SEND_WINDOW_BYTES = 1024*1024;
@ -268,6 +270,7 @@ public class PeerState {
_inboundMessages = new HashMap(8);
_outboundMessages = new ArrayList(32);
_dead = false;
_isInbound = false;
_context.statManager().createRateStat("udp.congestionOccurred", "How large the cwin was when congestion occurred (duration == sendBps)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("udp.congestedRTO", "retransmission timeout after congestion (duration == rtt dev)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
_context.statManager().createRateStat("udp.sendACKPartial", "Number of partial ACKs sent (duration == number of full ACKs in that ack packet)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000, 24*60*60*1000 });
@ -553,6 +556,8 @@ public class PeerState {
public int getConcurrentSends() { return _concurrentMessagesActive; }
public int getConcurrentSendWindow() { return _concurrentMessagesAllowed; }
public int getConsecutiveSendRejections() { return _consecutiveRejections; }
public boolean isInbound() { return _isInbound; }
public void setInbound() { _isInbound = true; }
/** we received the message specified completely */
public void messageFullyReceived(Long messageId, int bytes) { messageFullyReceived(messageId, bytes, false); }

View File

@ -625,6 +625,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
}
markUnreachable(peerHash);
_context.shitlist().shitlistRouter(peerHash, "Part of the wrong network");
//_context.shitlist().shitlistRouter(peerHash, "Part of the wrong network", STYLE);
dropPeer(peerHash, false, "wrong network");
if (_log.shouldLog(Log.WARN))
@ -1673,14 +1674,16 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
buf.append(port);
*/
buf.append("</a>&nbsp;");
if (peer.isInbound())
buf.append("&gt; ");
else
buf.append("&lt; ");
if (peer.getWeRelayToThemAs() > 0)
buf.append("&gt;");
buf.append("^");
else
buf.append("&nbsp;");
if (peer.getTheyRelayToUsAs() > 0)
buf.append("&lt;");
else
buf.append("&nbsp;");
buf.append("v");
boolean appended = false;
if (_activeThrottle.isChoked(peer.getRemotePeer())) {
@ -1872,7 +1875,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
}
private static final String KEY = "<tr><td colspan=\"15\" valign=\"top\" align=\"left\">" +
"<b id=\"def.peer\">peer</b>: the remote peer (&lt; means they offer to introduce us, &gt; means we offer to introduce them)<br />\n" +
"<b id=\"def.peer\">peer</b>: the remote peer (&lt; inbound, &gt; outbound, v means they offer to introduce us, ^ means we offer to introduce them)<br />\n" +
"<b id=\"def.idle\">idle</b>: the idle time is how long since a packet has been received or sent<br />\n" +
"<b id=\"def.rate\">in/out</b>: the rates show a smoothed inbound and outbound transfer rate (KBytes per second)<br />\n" +
"<b id=\"def.up\">up</b>: the uptime is how long ago this session was established<br />\n" +

View File

@ -152,16 +152,26 @@ public abstract class TunnelPeerSelector {
// isn't safe, since they may publish one set of routerInfo to us and another to
// other peers. the defaults for filterUnreachable has always been to return false,
// but might as well make it explicit with a "false &&"
if (false && filterUnreachable(ctx, isInbound, isExploratory)) {
//
// Unreachable peers at the inbound gateway is a major cause of problems.
// Due to a bug in SSU peer testing in 0.6.1.32 and earlier, peers don't know
// if they are unreachable, so this won't help much. As of 0.6.1.33 we should have
// lots of unreachables, so enable this for now.
// We could just try and exclude them as the inbound gateway but that's harder
// (and even worse for anonymity?).
//
// Defaults changed to true for inbound only in filterUnreachable below.
Set peers = new HashSet(1);
// if (false && filterUnreachable(ctx, isInbound, isExploratory)) {
if (filterUnreachable(ctx, isInbound, isExploratory)) {
List caps = ctx.peerManager().getPeersByCapability(Router.CAPABILITY_UNREACHABLE);
if (caps == null) return new HashSet(0);
HashSet rv = new HashSet(caps);
return rv;
} else if (filterSlow(ctx, isInbound, isExploratory)) {
if (caps != null)
peers.addAll(caps);
}
if (filterSlow(ctx, isInbound, isExploratory)) {
Log log = ctx.logManager().getLog(TunnelPeerSelector.class);
char excl[] = getExcludeCaps(ctx);
Set peers = new HashSet(1);
if (excl != null) {
FloodfillNetworkDatabaseFacade fac = (FloodfillNetworkDatabaseFacade)ctx.netDb();
List known = fac.getKnownRouterData();
@ -268,10 +278,8 @@ public abstract class TunnelPeerSelector {
}
*/
}
return peers;
} else {
return new HashSet(1);
}
return peers;
}
public static boolean shouldExclude(RouterContext ctx, RouterInfo peer) {
@ -375,10 +383,11 @@ public abstract class TunnelPeerSelector {
private static final String PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "router.inboundExploratoryExcludeUnreachable";
private static final String PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "router.inboundClientExcludeUnreachable";
private static final boolean DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false;
private static final boolean DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = false;
private static final boolean DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = false;
private static final boolean DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = false;
private static final String DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "false";
private static final String DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE = "false";
// see comments at getExclude() above
private static final String DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE = "true";
private static final String DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE = "true";
protected boolean filterUnreachable(RouterContext ctx, boolean isInbound, boolean isExploratory) {
boolean def = false;
@ -386,14 +395,14 @@ public abstract class TunnelPeerSelector {
if (isExploratory)
if (isInbound)
val = ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
val = ctx.getProperty(PROP_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
else
val = ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
val = ctx.getProperty(PROP_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_EXPLORATORY_EXCLUDE_UNREACHABLE);
else
if (isInbound)
val = ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE);
val = ctx.getProperty(PROP_INBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_INBOUND_CLIENT_EXCLUDE_UNREACHABLE);
else
val = ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE);
val = ctx.getProperty(PROP_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE, DEFAULT_OUTBOUND_CLIENT_EXCLUDE_UNREACHABLE);
boolean rv = (val != null ? Boolean.valueOf(val).booleanValue() : def);
//System.err.println("Filter unreachable? " + rv + " (inbound? " + isInbound + ", exploratory? " + isExploratory);