2006-04-19 jrandom

* Adjust how we pick high capacity peers to allow the inclusion of fast
      peers (the previous filter assumed an old usage pattern)
    * New set of stats to help track per-packet-type bandwidth usage better
    * Cut out the proactive tail drop from the SSU transport, for now
    * Reduce the frequency of tunnel build attempts while we're saturated
    * Don't drop tunnel requests as easily - prefer to explicitly reject them
This commit is contained in:
jrandom
2006-04-19 17:46:51 +00:00
committed by zzz
parent 40d5ed31ac
commit 8cba2f4236
17 changed files with 212 additions and 72 deletions

View File

@ -62,8 +62,10 @@ public class GraphHelper {
+ "\" title=\"Combined bandwidth graph\" />\n"); + "\" title=\"Combined bandwidth graph\" />\n");
List listeners = StatSummarizer.instance().getListeners(); List listeners = StatSummarizer.instance().getListeners();
for (int i = 0; i < listeners.size(); i++) { TreeSet ordered = new TreeSet(new AlphaComparator());
SummaryListener lsnr = (SummaryListener)listeners.get(i); ordered.addAll(listeners);
for (Iterator iter = ordered.iterator(); iter.hasNext(); ) {
SummaryListener lsnr = (SummaryListener)iter.next();
Rate r = lsnr.getRate(); Rate r = lsnr.getRate();
String title = r.getRateStat().getName() + " for " + DataHelper.formatDuration(_periodCount * r.getPeriod()); String title = r.getRateStat().getName() + " for " + DataHelper.formatDuration(_periodCount * r.getPeriod());
_out.write("<img src=\"viewstat.jsp?stat=" + r.getRateStat().getName() _out.write("<img src=\"viewstat.jsp?stat=" + r.getRateStat().getName()
@ -108,3 +110,13 @@ public class GraphHelper {
return ""; return "";
} }
} }
class AlphaComparator implements Comparator {
public int compare(Object lhs, Object rhs) {
SummaryListener l = (SummaryListener)lhs;
SummaryListener r = (SummaryListener)rhs;
String lName = l.getRate().getRateStat().getName() + "." + l.getRate().getPeriod();
String rName = r.getRate().getRateStat().getName() + "." + r.getRate().getPeriod();
return lName.compareTo(rName);
}
}

View File

@ -153,7 +153,7 @@ class SummaryRenderer {
* specify who can get it from where, etc. * specify who can get it from where, etc.
* *
*/ */
public static void render(I2PAppContext ctx, OutputStream out, String filename) throws IOException { public static synchronized void render(I2PAppContext ctx, OutputStream out, String filename) throws IOException {
long end = ctx.clock().now(); long end = ctx.clock().now();
long start = end - 60*1000*SummaryListener.PERIODS; long start = end - 60*1000*SummaryListener.PERIODS;
long begin = System.currentTimeMillis(); long begin = System.currentTimeMillis();

View File

@ -433,6 +433,7 @@ public class Rate {
public boolean equals(Object obj) { public boolean equals(Object obj) {
if ((obj == null) || (obj.getClass() != Rate.class)) return false; if ((obj == null) || (obj.getClass() != Rate.class)) return false;
if (obj == this) return true;
Rate r = (Rate) obj; Rate r = (Rate) obj;
return _period == r.getPeriod() && _creationDate == r.getCreationDate() && return _period == r.getPeriod() && _creationDate == r.getCreationDate() &&
//_lastCoalesceDate == r.getLastCoalesceDate() && //_lastCoalesceDate == r.getLastCoalesceDate() &&

View File

@ -1,4 +1,12 @@
$Id: history.txt,v 1.459 2006/04/15 02:15:19 jrandom Exp $ $Id: history.txt,v 1.460 2006/04/15 02:58:12 jrandom Exp $
2006-04-19 jrandom
* Adjust how we pick high capacity peers to allow the inclusion of fast
peers (the previous filter assumed an old usage pattern)
* New set of stats to help track per-packet-type bandwidth usage better
* Cut out the proactive tail drop from the SSU transport, for now
* Reduce the frequency of tunnel build attempts while we're saturated
* Don't drop tunnel requests as easily - prefer to explicitly reject them
* 2006-04-15 0.6.1.16 released * 2006-04-15 0.6.1.16 released

View File

@ -333,7 +333,7 @@ public abstract class I2NPMessageImpl extends DataStructureImpl implements I2NPM
} }
protected void verifyUnwritten() { protected void verifyUnwritten() {
if (_written) throw new RuntimeException("Already written"); if (_written) throw new IllegalStateException("Already written");
} }
protected void written() { _written = true; } protected void written() { _written = true; }
protected void read() { _read = true; } protected void read() { _read = true; }

View File

@ -506,9 +506,9 @@ public class LoadTestManager {
} }
private int getBps() { private int getBps() {
int used1s = RouterThrottleImpl.get1sRate(_context); int used1s = _context.router().get1sRate();
int used1m = RouterThrottleImpl.get1mRate(_context); int used1m = _context.router().get1mRate();
int used5m = RouterThrottleImpl.get5mRate(_context); int used5m = _context.router().get5mRate();
return Math.max(used1s, Math.max(used1m, used5m)); return Math.max(used1s, Math.max(used1m, used5m));
} }

View File

@ -35,8 +35,10 @@ import net.i2p.router.message.GarlicMessageHandler;
//import net.i2p.router.message.TunnelMessageHandler; //import net.i2p.router.message.TunnelMessageHandler;
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade; import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
import net.i2p.router.startup.StartupJob; import net.i2p.router.startup.StartupJob;
import net.i2p.router.transport.FIFOBandwidthLimiter;
import net.i2p.stat.Rate; import net.i2p.stat.Rate;
import net.i2p.stat.RateStat; import net.i2p.stat.RateStat;
import net.i2p.stat.StatManager;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.I2PThread; import net.i2p.util.I2PThread;
import net.i2p.util.SimpleTimer; import net.i2p.util.SimpleTimer;
@ -1029,6 +1031,82 @@ public class Router {
t.start(); t.start();
return true; return true;
} }
private static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage";
/**
* What fraction of the bandwidth specified in our bandwidth limits should
* we allow to be consumed by participating tunnels?
*
*/
public double getSharePercentage() {
RouterContext ctx = _context;
if (ctx == null) return 0;
String pct = ctx.getProperty(PROP_BANDWIDTH_SHARE_PERCENTAGE);
if (pct != null) {
try {
double d = Double.parseDouble(pct);
if (d > 1)
return d/100d; // *cough* sometimes its 80 instead of .8 (!stab jrandom)
else
return d;
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.INFO))
_log.info("Unable to get the share percentage");
}
}
return 0.8;
}
public int get1sRate() { return get1sRate(false); }
public int get1sRate(boolean outboundOnly) {
RouterContext ctx = _context;
if (ctx != null) {
FIFOBandwidthLimiter bw = ctx.bandwidthLimiter();
if (bw != null) {
int out = (int)bw.getSendBps();
if (outboundOnly)
return out;
return (int)Math.max(out, bw.getReceiveBps());
}
}
return 0;
}
public int get1mRate() { return get1mRate(false); }
public int get1mRate(boolean outboundOnly) {
int send = 0;
RouterContext ctx = _context;
if (ctx == null)
return 0;
StatManager mgr = ctx.statManager();
if (mgr == null)
return 0;
RateStat rs = mgr.getRate("bw.sendRate");
if (rs != null)
send = (int)rs.getRate(1*60*1000).getAverageValue();
if (outboundOnly)
return send;
int recv = 0;
rs = mgr.getRate("bw.recvRate");
if (rs != null)
recv = (int)rs.getRate(1*60*1000).getAverageValue();
return Math.max(send, recv);
}
public int get5mRate() { return get5mRate(false); }
public int get5mRate(boolean outboundOnly) {
int send = 0;
RateStat rs = _context.statManager().getRate("bw.sendRate");
if (rs != null)
send = (int)rs.getRate(5*60*1000).getAverageValue();
if (outboundOnly)
return send;
int recv = 0;
rs = _context.statManager().getRate("bw.recvRate");
if (rs != null)
recv = (int)rs.getRate(5*60*1000).getAverageValue();
return Math.max(send, recv);
}
} }
/** /**

View File

@ -32,8 +32,7 @@ class RouterThrottleImpl implements RouterThrottle {
private static final String PROP_MAX_TUNNELS = "router.maxParticipatingTunnels"; private static final String PROP_MAX_TUNNELS = "router.maxParticipatingTunnels";
private static final String PROP_DEFAULT_KBPS_THROTTLE = "router.defaultKBpsThrottle"; private static final String PROP_DEFAULT_KBPS_THROTTLE = "router.defaultKBpsThrottle";
private static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage";
/** tunnel acceptance */ /** tunnel acceptance */
public static final int TUNNEL_ACCEPT = 0; public static final int TUNNEL_ACCEPT = 0;
@ -218,32 +217,6 @@ class RouterThrottleImpl implements RouterThrottle {
return TUNNEL_ACCEPT; return TUNNEL_ACCEPT;
} }
static int get1sRate(RouterContext ctx) {
return (int)Math.max(ctx.bandwidthLimiter().getSendBps(), ctx.bandwidthLimiter().getReceiveBps());
}
static int get1mRate(RouterContext ctx) {
int send = 0;
RateStat rs = ctx.statManager().getRate("bw.sendRate");
if (rs != null)
send = (int)rs.getRate(1*60*1000).getAverageValue();
int recv = 0;
rs = ctx.statManager().getRate("bw.recvRate");
if (rs != null)
recv = (int)rs.getRate(1*60*1000).getAverageValue();
return Math.max(send, recv);
}
static int get5mRate(RouterContext ctx) {
int send = 0;
RateStat rs = ctx.statManager().getRate("bw.sendRate");
if (rs != null)
send = (int)rs.getRate(5*60*1000).getAverageValue();
int recv = 0;
rs = ctx.statManager().getRate("bw.recvRate");
if (rs != null)
recv = (int)rs.getRate(5*60*1000).getAverageValue();
return Math.max(send, recv);
}
private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 60; // .1KBps private static final int DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE = 60; // .1KBps
private static final int MIN_AVAILABLE_BPS = 4*1024; // always leave at least 4KBps free when allowing private static final int MIN_AVAILABLE_BPS = 4*1024; // always leave at least 4KBps free when allowing
@ -256,10 +229,10 @@ class RouterThrottleImpl implements RouterThrottle {
private boolean allowTunnel(double bytesAllocated, int numTunnels) { private boolean allowTunnel(double bytesAllocated, int numTunnels) {
int maxKBps = Math.min(_context.bandwidthLimiter().getOutboundKBytesPerSecond(), _context.bandwidthLimiter().getInboundKBytesPerSecond()); int maxKBps = Math.min(_context.bandwidthLimiter().getOutboundKBytesPerSecond(), _context.bandwidthLimiter().getInboundKBytesPerSecond());
int used1s = 0; //get1sRate(_context); // dont throttle on the 1s rate, its too volatile int used1s = 0; //get1sRate(_context); // dont throttle on the 1s rate, its too volatile
int used1m = get1mRate(_context); int used1m = _context.router().get1mRate();
int used5m = 0; //get5mRate(_context); // don't throttle on the 5m rate, as that'd hide available bandwidth int used5m = 0; //get5mRate(_context); // don't throttle on the 5m rate, as that'd hide available bandwidth
int used = Math.max(Math.max(used1s, used1m), used5m); int used = Math.max(Math.max(used1s, used1m), used5m);
double share = getSharePercentage(); double share = _context.router().getSharePercentage();
int availBps = (int)(((maxKBps*1024)*share) - used); //(int)(((maxKBps*1024) - used) * getSharePercentage()); int availBps = (int)(((maxKBps*1024)*share) - used); //(int)(((maxKBps*1024) - used) * getSharePercentage());
_context.statManager().addRateData("router.throttleTunnelBytesUsed", used, maxKBps); _context.statManager().addRateData("router.throttleTunnelBytesUsed", used, maxKBps);
@ -326,28 +299,6 @@ class RouterThrottleImpl implements RouterThrottle {
} }
} }
/**
* What fraction of the bandwidth specified in our bandwidth limits should
* we allow to be consumed by participating tunnels?
*
*/
private double getSharePercentage() {
String pct = _context.getProperty(PROP_BANDWIDTH_SHARE_PERCENTAGE);
if (pct != null) {
try {
double d = Double.parseDouble(pct);
if (d > 1)
return d/100d; // *cough* sometimes its 80 instead of .8 (!stab jrandom)
else
return d;
} catch (NumberFormatException nfe) {
if (_log.shouldLog(Log.INFO))
_log.info("Unable to get the share percentage");
}
}
return 0.8;
}
/** dont ever probabalistically throttle tunnels if we have less than this many */ /** dont ever probabalistically throttle tunnels if we have less than this many */
private int getMinThrottleTunnels() { private int getMinThrottleTunnels() {
try { try {

View File

@ -15,9 +15,9 @@ import net.i2p.CoreVersion;
* *
*/ */
public class RouterVersion { public class RouterVersion {
public final static String ID = "$Revision: 1.399 $ $Date: 2006/04/15 02:15:23 $"; public final static String ID = "$Revision: 1.400 $ $Date: 2006/04/15 02:58:14 $";
public final static String VERSION = "0.6.1.16"; public final static String VERSION = "0.6.1.16";
public final static long BUILD = 0; public final static long BUILD = 1;
public static void main(String args[]) { public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID); System.out.println("Router ID: " + RouterVersion.ID);

View File

@ -251,10 +251,12 @@ public class ProfileOrganizer {
// we only use selectHighCapacityPeers when we are selecting for PURPOSE_TEST // we only use selectHighCapacityPeers when we are selecting for PURPOSE_TEST
// or we are falling back due to _fastPeers being too small, so we can always // or we are falling back due to _fastPeers being too small, so we can always
// exclude the fast peers // exclude the fast peers
/*
if (exclude == null) if (exclude == null)
exclude = new HashSet(_fastPeers.keySet()); exclude = new HashSet(_fastPeers.keySet());
else else
exclude.addAll(_fastPeers.keySet()); exclude.addAll(_fastPeers.keySet());
*/
locked_selectPeers(_highCapacityPeers, howMany, exclude, matches); locked_selectPeers(_highCapacityPeers, howMany, exclude, matches);
} }
if (matches.size() < howMany) { if (matches.size() < howMany) {
@ -809,6 +811,8 @@ public class ProfileOrganizer {
} else { } else {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Peer " + peer.toBase64() + " is locally known, allowing its use"); _log.info("Peer " + peer.toBase64() + " is locally known, allowing its use");
// perhaps check to see if they are active?
return true; return true;
} }
} else { } else {

View File

@ -402,6 +402,7 @@ public class PacketBuilder {
authenticate(packet, ourIntroKey, ourIntroKey, iv); authenticate(packet, ourIntroKey, ourIntroKey, iv);
setTo(packet, to, state.getSentPort()); setTo(packet, to, state.getSentPort());
_ivCache.release(iv); _ivCache.release(iv);
packet.setMessageType(53);
return packet; return packet;
} }
@ -465,6 +466,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, state.getIntroKey(), state.getIntroKey()); authenticate(packet, state.getIntroKey(), state.getIntroKey());
setTo(packet, to, state.getSentPort()); setTo(packet, to, state.getSentPort());
packet.setMessageType(52);
return packet; return packet;
} }
@ -571,6 +573,7 @@ public class PacketBuilder {
} }
setTo(packet, to, state.getSentPort()); setTo(packet, to, state.getSentPort());
packet.setMessageType(51);
return packet; return packet;
} }
@ -623,6 +626,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, toCipherKey, toMACKey); authenticate(packet, toCipherKey, toMACKey);
setTo(packet, toIP, toPort); setTo(packet, toIP, toPort);
packet.setMessageType(50);
return packet; return packet;
} }
@ -667,6 +671,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, aliceIntroKey, aliceIntroKey); authenticate(packet, aliceIntroKey, aliceIntroKey);
setTo(packet, aliceIP, alicePort); setTo(packet, aliceIP, alicePort);
packet.setMessageType(49);
return packet; return packet;
} }
@ -713,6 +718,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, charlieCipherKey, charlieMACKey); authenticate(packet, charlieCipherKey, charlieMACKey);
setTo(packet, charlieIP, charliePort); setTo(packet, charlieIP, charliePort);
packet.setMessageType(48);
return packet; return packet;
} }
@ -757,6 +763,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, bobCipherKey, bobMACKey); authenticate(packet, bobCipherKey, bobMACKey);
setTo(packet, bobIP, bobPort); setTo(packet, bobIP, bobPort);
packet.setMessageType(47);
return packet; return packet;
} }
@ -854,6 +861,7 @@ public class PacketBuilder {
if (encrypt) if (encrypt)
authenticate(packet, new SessionKey(introKey), new SessionKey(introKey)); authenticate(packet, new SessionKey(introKey), new SessionKey(introKey));
setTo(packet, introHost, introPort); setTo(packet, introHost, introPort);
packet.setMessageType(46);
return packet; return packet;
} }
@ -903,6 +911,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, charlie.getCurrentCipherKey(), charlie.getCurrentMACKey()); authenticate(packet, charlie.getCurrentCipherKey(), charlie.getCurrentMACKey());
setTo(packet, charlie.getRemoteIPAddress(), charlie.getRemotePort()); setTo(packet, charlie.getRemoteIPAddress(), charlie.getRemotePort());
packet.setMessageType(45);
return packet; return packet;
} }
@ -963,6 +972,7 @@ public class PacketBuilder {
packet.getPacket().setLength(off); packet.getPacket().setLength(off);
authenticate(packet, aliceIntroKey, aliceIntroKey); authenticate(packet, aliceIntroKey, aliceIntroKey);
setTo(packet, aliceAddr, alice.getPort()); setTo(packet, aliceAddr, alice.getPort());
packet.setMessageType(44);
return packet; return packet;
} }
@ -994,6 +1004,8 @@ public class PacketBuilder {
// its just for hole punching // its just for hole punching
packet.getPacket().setLength(0); packet.getPacket().setLength(0);
setTo(packet, to, port); setTo(packet, to, port);
packet.setMessageType(43);
return packet; return packet;
} }

View File

@ -68,6 +68,17 @@ public class PacketHandler {
_context.statManager().createRateStat("udp.packetVerifyTimeSlow", "How long it takes the PacketHandler to verify a data packet after dequeueing when its slow (period is dequeue time)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); _context.statManager().createRateStat("udp.packetVerifyTimeSlow", "How long it takes the PacketHandler to verify a data packet after dequeueing when its slow (period is dequeue time)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("udp.packetValidateMultipleCount", "How many times we validate a packet, if done more than once (period = afterValidate-enqueue)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); _context.statManager().createRateStat("udp.packetValidateMultipleCount", "How many times we validate a packet, if done more than once (period = afterValidate-enqueue)", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("udp.packetNoValidationLifetime", "How long packets that are never validated are around for", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 }); _context.statManager().createRateStat("udp.packetNoValidationLifetime", "How long packets that are never validated are around for", "udp", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.sessionRequest", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.sessionConfirmed", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.sessionCreated", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.dataKnown", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.dataKnownAck", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.dataUnknown", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.dataUnknownAck", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.test", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.relayRequest", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.relayIntro", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
_context.statManager().createRateStat("udp.receivePacketSize.relayResponse", "Packet size of the given inbound packet type (period is the packet's lifetime)", "udp", new long[] { 60*1000, 10*60*1000 });
} }
public void startup() { public void startup() {
@ -440,14 +451,17 @@ public class PacketHandler {
case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST: case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST:
_state = 47; _state = 47;
_establisher.receiveSessionRequest(from, reader); _establisher.receiveSessionRequest(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.sessionRequest", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED: case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED:
_state = 48; _state = 48;
_establisher.receiveSessionConfirmed(from, reader); _establisher.receiveSessionConfirmed(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.sessionConfirmed", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_SESSION_CREATED: case UDPPacket.PAYLOAD_TYPE_SESSION_CREATED:
_state = 49; _state = 49;
_establisher.receiveSessionCreated(from, reader); _establisher.receiveSessionCreated(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.sessionCreated", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_DATA: case UDPPacket.PAYLOAD_TYPE_DATA:
_state = 50; _state = 50;
@ -472,6 +486,14 @@ public class PacketHandler {
} }
packet.beforeReceiveFragments(); packet.beforeReceiveFragments();
_inbound.receiveData(state, dr); _inbound.receiveData(state, dr);
_context.statManager().addRateData("udp.receivePacketSize.dataKnown", packet.getPacket().getLength(), packet.getLifetime());
if (dr.readFragmentCount() <= 0)
_context.statManager().addRateData("udp.receivePacketSize.dataKnownAck", packet.getPacket().getLength(), packet.getLifetime());
} else {
_context.statManager().addRateData("udp.receivePacketSize.dataUnknown", packet.getPacket().getLength(), packet.getLifetime());
UDPPacketReader.DataReader dr = reader.getDataReader();
if (dr.readFragmentCount() <= 0)
_context.statManager().addRateData("udp.receivePacketSize.dataUnknownAck", packet.getPacket().getLength(), packet.getLifetime());
} }
break; break;
case UDPPacket.PAYLOAD_TYPE_TEST: case UDPPacket.PAYLOAD_TYPE_TEST:
@ -479,21 +501,25 @@ public class PacketHandler {
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.DEBUG))
_log.debug("Received test packet: " + reader + " from " + from); _log.debug("Received test packet: " + reader + " from " + from);
_testManager.receiveTest(from, reader); _testManager.receiveTest(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.test", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_RELAY_REQUEST: case UDPPacket.PAYLOAD_TYPE_RELAY_REQUEST:
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Received relay request packet: " + reader + " from " + from); _log.info("Received relay request packet: " + reader + " from " + from);
_introManager.receiveRelayRequest(from, reader); _introManager.receiveRelayRequest(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.relayRequest", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_RELAY_INTRO: case UDPPacket.PAYLOAD_TYPE_RELAY_INTRO:
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Received relay intro packet: " + reader + " from " + from); _log.info("Received relay intro packet: " + reader + " from " + from);
_introManager.receiveRelayIntro(from, reader); _introManager.receiveRelayIntro(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.relayIntro", packet.getPacket().getLength(), packet.getLifetime());
break; break;
case UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE: case UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE:
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
_log.info("Received relay response packet: " + reader + " from " + from); _log.info("Received relay response packet: " + reader + " from " + from);
_establisher.receiveRelayResponse(from, reader); _establisher.receiveRelayResponse(from, reader);
_context.statManager().addRateData("udp.receivePacketSize.relayResponse", packet.getPacket().getLength(), packet.getLifetime());
break; break;
default: default:
_state = 52; _state = 52;

View File

@ -1036,7 +1036,7 @@ public class PeerState {
remaining = 1; // total lifetime will exceed it anyway, guaranteeing failure remaining = 1; // total lifetime will exceed it anyway, guaranteeing failure
float pDrop = totalLifetime / (float)remaining; float pDrop = totalLifetime / (float)remaining;
pDrop = pDrop * pDrop * pDrop; pDrop = pDrop * pDrop * pDrop;
if (pDrop >= _context.random().nextFloat()) { if (false && (pDrop >= _context.random().nextFloat())) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Proactively tail dropping for " + _remotePeer.toBase64() + " (messages=" + msgs.size() _log.warn("Proactively tail dropping for " + _remotePeer.toBase64() + " (messages=" + msgs.size()
+ " headLifetime=" + lifetime + " totalLifetime=" + totalLifetime + " curLifetime=" + state.getLifetime() + " headLifetime=" + lifetime + " totalLifetime=" + totalLifetime + " curLifetime=" + state.getLifetime()

View File

@ -55,7 +55,21 @@ public class UDPSender {
_context.statManager().createRateStat("udp.sendPacketSize.18", "tunnel data message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 }); _context.statManager().createRateStat("udp.sendPacketSize.18", "tunnel data message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.19", "tunnel gateway message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 }); _context.statManager().createRateStat("udp.sendPacketSize.19", "tunnel gateway message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.20", "data message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 }); _context.statManager().createRateStat("udp.sendPacketSize.20", "data message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.21", "tunnel build", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.22", "tunnel build reply", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.20", "data message size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.42", "ack-only packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 }); _context.statManager().createRateStat("udp.sendPacketSize.42", "ack-only packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.43", "hole punch packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.44", "relay response packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.45", "relay intro packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.46", "relay request packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.47", "peer test charlie to bob packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.48", "peer test bob to charlie packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.49", "peer test to alice packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.50", "peer test from alice packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.51", "session confirmed packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.52", "session request packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
_context.statManager().createRateStat("udp.sendPacketSize.53", "session created packet size", "udp", new long[] { 60*1000, 5*60*1000, 30*60*1000 });
} }
public void startup() { public void startup() {
@ -211,7 +225,7 @@ public class UDPSender {
//_log.debug("Sending packet: (size="+size + "/"+size2 +")\nraw: " + Base64.encode(packet.getPacket().getData(), 0, size)); //_log.debug("Sending packet: (size="+size + "/"+size2 +")\nraw: " + Base64.encode(packet.getPacket().getData(), 0, size));
} }
//_context.statManager().addRateData("udp.sendPacketSize." + packet.getMessageType(), size, packet.getFragmentCount()); _context.statManager().addRateData("udp.sendPacketSize." + packet.getMessageType(), size, packet.getFragmentCount());
//packet.getPacket().setLength(size); //packet.getPacket().setLength(size);
try { try {

View File

@ -1673,6 +1673,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
} }
if (_alive) { if (_alive) {
long delay = _context.random().nextInt(2*TEST_FREQUENCY); long delay = _context.random().nextInt(2*TEST_FREQUENCY);
if (delay <= 0)
throw new RuntimeException("wtf, delay is " + delay);
SimpleTimer.getInstance().addEvent(PeerTestEvent.this, delay); SimpleTimer.getInstance().addEvent(PeerTestEvent.this, delay);
} }
} }

View File

@ -52,7 +52,7 @@ class BuildExecutor implements Runnable {
buf = new StringBuffer(128); buf = new StringBuffer(128);
buf.append("Allowed: "); buf.append("Allowed: ");
} }
int allowed = 20; int allowed = 5;
String prop = _context.getProperty("router.tunnelConcurrentBuilds"); String prop = _context.getProperty("router.tunnelConcurrentBuilds");
if (prop != null) if (prop != null)
try { allowed = Integer.valueOf(prop).intValue(); } catch (NumberFormatException nfe) {} try { allowed = Integer.valueOf(prop).intValue(); } catch (NumberFormatException nfe) {}
@ -92,6 +92,8 @@ class BuildExecutor implements Runnable {
_context.statManager().addRateData("tunnel.buildExploratoryExpire", 1, 0); _context.statManager().addRateData("tunnel.buildExploratoryExpire", 1, 0);
else else
_context.statManager().addRateData("tunnel.buildClientExpire", 1, 0); _context.statManager().addRateData("tunnel.buildClientExpire", 1, 0);
for (int j = 0; j < cfg.getLength(); j++)
didNotReply(cfg.getReplyMessageId(), cfg.getPeer(j));
} }
} }
@ -107,11 +109,33 @@ class BuildExecutor implements Runnable {
_context.statManager().addRateData("tunnel.concurrentBuildsLagged", concurrent, lag); _context.statManager().addRateData("tunnel.concurrentBuildsLagged", concurrent, lag);
return 0; // if we have a job heavily blocking our jobqueue, ssllloowww dddooowwwnnn return 0; // if we have a job heavily blocking our jobqueue, ssllloowww dddooowwwnnn
} }
//if (isOverloaded())
// return 0; if (isOverloaded())
return 0;
return allowed; return allowed;
} }
/**
* Don't even try to build tunnels if we're saturated
*/
private boolean isOverloaded() {
//if (true) return false;
// dont include the inbound rates when throttling tunnel building, since
// that'd expose a pretty trivial attack.
int maxKBps = _context.bandwidthLimiter().getOutboundKBytesPerSecond();
int used1s = _context.router().get1sRate(true); // dont throttle on the 1s rate, its too volatile
int used1m = _context.router().get1mRate(true);
int used5m = 0; //get5mRate(_context); // don't throttle on the 5m rate, as that'd hide available bandwidth
int used = Math.max(Math.max(used1s, used1m), used5m);
if ((maxKBps * 1024) - used <= 0) {
if (_log.shouldLog(Log.WARN))
_log.warn("Too overloaded to build our own tunnels (used=" + used + ", maxKBps=" + maxKBps + ", 1s=" + used1s + ", 1m=" + used1m + ")");
return true;
} else {
return false;
}
}
public void run() { public void run() {
_isRunning = true; _isRunning = true;
@ -306,6 +330,7 @@ class BuildExecutor implements Runnable {
_currentlyBuilding.remove(cfg); _currentlyBuilding.remove(cfg);
_currentlyBuilding.notifyAll(); _currentlyBuilding.notifyAll();
} }
long expireBefore = _context.clock().now() + 10*60*1000 - BuildRequestor.REQUEST_TIMEOUT; long expireBefore = _context.clock().now() + 10*60*1000 - BuildRequestor.REQUEST_TIMEOUT;
if (cfg.getExpiration() <= expireBefore) { if (cfg.getExpiration() <= expireBefore) {
if (_log.shouldLog(Log.INFO)) if (_log.shouldLog(Log.INFO))
@ -331,6 +356,11 @@ class BuildExecutor implements Runnable {
} }
} }
private void didNotReply(long tunnel, Hash peer) {
if (_log.shouldLog(Log.INFO))
_log.info(tunnel + ": Peer " + peer.toBase64() + " did not reply to the tunnel join request");
}
List locked_getCurrentlyBuilding() { return _currentlyBuilding; } List locked_getCurrentlyBuilding() { return _currentlyBuilding; }
public int getInboundBuildQueueSize() { return _handler.getInboundBuildQueueSize(); } public int getInboundBuildQueueSize() { return _handler.getInboundBuildQueueSize(); }
} }

View File

@ -213,8 +213,8 @@ class BuildHandler {
Hash peer = cfg.getPeer(i); Hash peer = cfg.getPeer(i);
int record = order.indexOf(new Integer(i)); int record = order.indexOf(new Integer(i));
int howBad = statuses[record]; int howBad = statuses[record];
if (_log.shouldLog(Log.DEBUG)) if (_log.shouldLog(Log.INFO))
_log.debug(msg.getUniqueId() + ": Peer " + peer.toBase64() + " replied with status " + howBad); _log.info(msg.getUniqueId() + ": Peer " + peer.toBase64() + " replied with status " + howBad);
if (howBad == 0) { if (howBad == 0) {
// w3wt // w3wt
@ -415,7 +415,7 @@ class BuildHandler {
int proactiveDrops = countProactiveDrops(); int proactiveDrops = countProactiveDrops();
long recvDelay = System.currentTimeMillis()-state.recvTime; long recvDelay = System.currentTimeMillis()-state.recvTime;
if (response == 0) { if (response == 0) {
float pDrop = recvDelay / (BuildRequestor.REQUEST_TIMEOUT/2); float pDrop = recvDelay / (BuildRequestor.REQUEST_TIMEOUT);
pDrop = (float)Math.pow(pDrop, 16); pDrop = (float)Math.pow(pDrop, 16);
if (_context.random().nextFloat() < pDrop) { // || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) { if (_context.random().nextFloat() < pDrop) { // || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) {
_context.statManager().addRateData("tunnel.rejectOverloaded", recvDelay, proactiveDrops); _context.statManager().addRateData("tunnel.rejectOverloaded", recvDelay, proactiveDrops);
@ -547,6 +547,8 @@ class BuildHandler {
} }
} }
/** um, this is bad. don't set this. */
private static final boolean DROP_ALL_REQUESTS = false;
private static final boolean HANDLE_REPLIES_INLINE = true; private static final boolean HANDLE_REPLIES_INLINE = true;
private class TunnelBuildMessageHandlerJobBuilder implements HandlerJobBuilder { private class TunnelBuildMessageHandlerJobBuilder implements HandlerJobBuilder {
@ -586,7 +588,7 @@ class BuildHandler {
_exec.repoll(); _exec.repoll();
} }
} else { } else {
if (_exec.wasRecentlyBuilding(reqId)) { if (DROP_ALL_REQUESTS || _exec.wasRecentlyBuilding(reqId)) {
if (_log.shouldLog(Log.WARN)) if (_log.shouldLog(Log.WARN))
_log.warn("Dropping the reply " + reqId + ", as we used to be building that"); _log.warn("Dropping the reply " + reqId + ", as we used to be building that");
} else { } else {
@ -608,7 +610,7 @@ class BuildHandler {
_context.statManager().addRateData("tunnel.dropLoadBacklog", _inboundBuildMessages.size(), _inboundBuildMessages.size()); _context.statManager().addRateData("tunnel.dropLoadBacklog", _inboundBuildMessages.size(), _inboundBuildMessages.size());
} else { } else {
int queueTime = estimateQueueTime(_inboundBuildMessages.size()); int queueTime = estimateQueueTime(_inboundBuildMessages.size());
float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT/2); float pDrop = queueTime/((float)BuildRequestor.REQUEST_TIMEOUT);
pDrop = (float)Math.pow(pDrop, 16); // steeeep pDrop = (float)Math.pow(pDrop, 16); // steeeep
float f = _context.random().nextFloat(); float f = _context.random().nextFloat();
if ( (pDrop > f) && (allowProactiveDrop()) ) { if ( (pDrop > f) && (allowProactiveDrop()) ) {