From 8cba2f4236e7b78829636cf34ca8f597ab567d35 Mon Sep 17 00:00:00 2001 From: jrandom Date: Wed, 19 Apr 2006 17:46:51 +0000 Subject: [PATCH] 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 --- .../src/net/i2p/router/web/GraphHelper.java | 16 +++- .../net/i2p/router/web/SummaryListener.java | 2 +- core/java/src/net/i2p/stat/Rate.java | 1 + history.txt | 10 ++- .../net/i2p/data/i2np/I2NPMessageImpl.java | 2 +- .../src/net/i2p/router/LoadTestManager.java | 6 +- router/java/src/net/i2p/router/Router.java | 78 +++++++++++++++++++ .../net/i2p/router/RouterThrottleImpl.java | 55 +------------ .../src/net/i2p/router/RouterVersion.java | 4 +- .../router/peermanager/ProfileOrganizer.java | 4 + .../router/transport/udp/PacketBuilder.java | 12 +++ .../router/transport/udp/PacketHandler.java | 26 +++++++ .../i2p/router/transport/udp/PeerState.java | 2 +- .../i2p/router/transport/udp/UDPSender.java | 16 +++- .../router/transport/udp/UDPTransport.java | 2 + .../i2p/router/tunnel/pool/BuildExecutor.java | 36 ++++++++- .../i2p/router/tunnel/pool/BuildHandler.java | 12 +-- 17 files changed, 212 insertions(+), 72 deletions(-) diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java index 3260a2119..6d247e712 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java @@ -62,8 +62,10 @@ public class GraphHelper { + "\" title=\"Combined bandwidth graph\" />\n"); List listeners = StatSummarizer.instance().getListeners(); - for (int i = 0; i < listeners.size(); i++) { - SummaryListener lsnr = (SummaryListener)listeners.get(i); + TreeSet ordered = new TreeSet(new AlphaComparator()); + ordered.addAll(listeners); + for (Iterator iter = ordered.iterator(); iter.hasNext(); ) { + SummaryListener lsnr = (SummaryListener)iter.next(); Rate r = lsnr.getRate(); String title = r.getRateStat().getName() + " for " + DataHelper.formatDuration(_periodCount * r.getPeriod()); _out.write(" 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); + } + } /** diff --git a/router/java/src/net/i2p/router/RouterThrottleImpl.java b/router/java/src/net/i2p/router/RouterThrottleImpl.java index 0b54415ea..05c2582a5 100644 --- a/router/java/src/net/i2p/router/RouterThrottleImpl.java +++ b/router/java/src/net/i2p/router/RouterThrottleImpl.java @@ -32,8 +32,7 @@ class RouterThrottleImpl implements RouterThrottle { private static final String PROP_MAX_TUNNELS = "router.maxParticipatingTunnels"; private static final String PROP_DEFAULT_KBPS_THROTTLE = "router.defaultKBpsThrottle"; - private static final String PROP_BANDWIDTH_SHARE_PERCENTAGE = "router.sharePercentage"; - + /** tunnel acceptance */ public static final int TUNNEL_ACCEPT = 0; @@ -218,32 +217,6 @@ class RouterThrottleImpl implements RouterThrottle { 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 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) { 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 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 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()); _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 */ private int getMinThrottleTunnels() { try { diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 4cacb7118..552461e9a 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -15,9 +15,9 @@ import net.i2p.CoreVersion; * */ 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 long BUILD = 0; + public final static long BUILD = 1; public static void main(String args[]) { System.out.println("I2P Router version: " + VERSION + "-" + BUILD); System.out.println("Router ID: " + RouterVersion.ID); diff --git a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java index b8ea42c2a..3b80749e1 100644 --- a/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java +++ b/router/java/src/net/i2p/router/peermanager/ProfileOrganizer.java @@ -251,10 +251,12 @@ public class ProfileOrganizer { // 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 // exclude the fast peers + /* if (exclude == null) exclude = new HashSet(_fastPeers.keySet()); else exclude.addAll(_fastPeers.keySet()); + */ locked_selectPeers(_highCapacityPeers, howMany, exclude, matches); } if (matches.size() < howMany) { @@ -809,6 +811,8 @@ public class ProfileOrganizer { } else { if (_log.shouldLog(Log.INFO)) _log.info("Peer " + peer.toBase64() + " is locally known, allowing its use"); + // perhaps check to see if they are active? + return true; } } else { diff --git a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java index 86ced1b64..9fad97163 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketBuilder.java @@ -402,6 +402,7 @@ public class PacketBuilder { authenticate(packet, ourIntroKey, ourIntroKey, iv); setTo(packet, to, state.getSentPort()); _ivCache.release(iv); + packet.setMessageType(53); return packet; } @@ -465,6 +466,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, state.getIntroKey(), state.getIntroKey()); setTo(packet, to, state.getSentPort()); + packet.setMessageType(52); return packet; } @@ -571,6 +573,7 @@ public class PacketBuilder { } setTo(packet, to, state.getSentPort()); + packet.setMessageType(51); return packet; } @@ -623,6 +626,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, toCipherKey, toMACKey); setTo(packet, toIP, toPort); + packet.setMessageType(50); return packet; } @@ -667,6 +671,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, aliceIntroKey, aliceIntroKey); setTo(packet, aliceIP, alicePort); + packet.setMessageType(49); return packet; } @@ -713,6 +718,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, charlieCipherKey, charlieMACKey); setTo(packet, charlieIP, charliePort); + packet.setMessageType(48); return packet; } @@ -757,6 +763,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, bobCipherKey, bobMACKey); setTo(packet, bobIP, bobPort); + packet.setMessageType(47); return packet; } @@ -854,6 +861,7 @@ public class PacketBuilder { if (encrypt) authenticate(packet, new SessionKey(introKey), new SessionKey(introKey)); setTo(packet, introHost, introPort); + packet.setMessageType(46); return packet; } @@ -903,6 +911,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, charlie.getCurrentCipherKey(), charlie.getCurrentMACKey()); setTo(packet, charlie.getRemoteIPAddress(), charlie.getRemotePort()); + packet.setMessageType(45); return packet; } @@ -963,6 +972,7 @@ public class PacketBuilder { packet.getPacket().setLength(off); authenticate(packet, aliceIntroKey, aliceIntroKey); setTo(packet, aliceAddr, alice.getPort()); + packet.setMessageType(44); return packet; } @@ -994,6 +1004,8 @@ public class PacketBuilder { // its just for hole punching packet.getPacket().setLength(0); setTo(packet, to, port); + + packet.setMessageType(43); return packet; } diff --git a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java index 882054f1b..af9ef971f 100644 --- a/router/java/src/net/i2p/router/transport/udp/PacketHandler.java +++ b/router/java/src/net/i2p/router/transport/udp/PacketHandler.java @@ -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.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.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() { @@ -440,14 +451,17 @@ public class PacketHandler { case UDPPacket.PAYLOAD_TYPE_SESSION_REQUEST: _state = 47; _establisher.receiveSessionRequest(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.sessionRequest", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_SESSION_CONFIRMED: _state = 48; _establisher.receiveSessionConfirmed(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.sessionConfirmed", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_SESSION_CREATED: _state = 49; _establisher.receiveSessionCreated(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.sessionCreated", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_DATA: _state = 50; @@ -472,6 +486,14 @@ public class PacketHandler { } packet.beforeReceiveFragments(); _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; case UDPPacket.PAYLOAD_TYPE_TEST: @@ -479,21 +501,25 @@ public class PacketHandler { if (_log.shouldLog(Log.DEBUG)) _log.debug("Received test packet: " + reader + " from " + from); _testManager.receiveTest(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.test", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_RELAY_REQUEST: if (_log.shouldLog(Log.INFO)) _log.info("Received relay request packet: " + reader + " from " + from); _introManager.receiveRelayRequest(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.relayRequest", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_RELAY_INTRO: if (_log.shouldLog(Log.INFO)) _log.info("Received relay intro packet: " + reader + " from " + from); _introManager.receiveRelayIntro(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.relayIntro", packet.getPacket().getLength(), packet.getLifetime()); break; case UDPPacket.PAYLOAD_TYPE_RELAY_RESPONSE: if (_log.shouldLog(Log.INFO)) _log.info("Received relay response packet: " + reader + " from " + from); _establisher.receiveRelayResponse(from, reader); + _context.statManager().addRateData("udp.receivePacketSize.relayResponse", packet.getPacket().getLength(), packet.getLifetime()); break; default: _state = 52; diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState.java b/router/java/src/net/i2p/router/transport/udp/PeerState.java index ad8bf1f37..13e24c704 100644 --- a/router/java/src/net/i2p/router/transport/udp/PeerState.java +++ b/router/java/src/net/i2p/router/transport/udp/PeerState.java @@ -1036,7 +1036,7 @@ public class PeerState { remaining = 1; // total lifetime will exceed it anyway, guaranteeing failure float pDrop = totalLifetime / (float)remaining; pDrop = pDrop * pDrop * pDrop; - if (pDrop >= _context.random().nextFloat()) { + if (false && (pDrop >= _context.random().nextFloat())) { if (_log.shouldLog(Log.WARN)) _log.warn("Proactively tail dropping for " + _remotePeer.toBase64() + " (messages=" + msgs.size() + " headLifetime=" + lifetime + " totalLifetime=" + totalLifetime + " curLifetime=" + state.getLifetime() diff --git a/router/java/src/net/i2p/router/transport/udp/UDPSender.java b/router/java/src/net/i2p/router/transport/udp/UDPSender.java index 6ae185b6b..8b22d180d 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPSender.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPSender.java @@ -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.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.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.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() { @@ -211,7 +225,7 @@ public class UDPSender { //_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); try { diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java index 70814e2ba..2e83f608a 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java @@ -1673,6 +1673,8 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority } if (_alive) { long delay = _context.random().nextInt(2*TEST_FREQUENCY); + if (delay <= 0) + throw new RuntimeException("wtf, delay is " + delay); SimpleTimer.getInstance().addEvent(PeerTestEvent.this, delay); } } diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java index 9d20b384a..cfe7aab61 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildExecutor.java @@ -52,7 +52,7 @@ class BuildExecutor implements Runnable { buf = new StringBuffer(128); buf.append("Allowed: "); } - int allowed = 20; + int allowed = 5; String prop = _context.getProperty("router.tunnelConcurrentBuilds"); if (prop != null) try { allowed = Integer.valueOf(prop).intValue(); } catch (NumberFormatException nfe) {} @@ -92,6 +92,8 @@ class BuildExecutor implements Runnable { _context.statManager().addRateData("tunnel.buildExploratoryExpire", 1, 0); else _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); return 0; // if we have a job heavily blocking our jobqueue, ssllloowww dddooowwwnnn } - //if (isOverloaded()) - // return 0; + + if (isOverloaded()) + return 0; 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() { _isRunning = true; @@ -306,6 +330,7 @@ class BuildExecutor implements Runnable { _currentlyBuilding.remove(cfg); _currentlyBuilding.notifyAll(); } + long expireBefore = _context.clock().now() + 10*60*1000 - BuildRequestor.REQUEST_TIMEOUT; if (cfg.getExpiration() <= expireBefore) { 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; } public int getInboundBuildQueueSize() { return _handler.getInboundBuildQueueSize(); } } diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java index aa426c51a..7c0b144d8 100644 --- a/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java +++ b/router/java/src/net/i2p/router/tunnel/pool/BuildHandler.java @@ -213,8 +213,8 @@ class BuildHandler { Hash peer = cfg.getPeer(i); int record = order.indexOf(new Integer(i)); int howBad = statuses[record]; - if (_log.shouldLog(Log.DEBUG)) - _log.debug(msg.getUniqueId() + ": Peer " + peer.toBase64() + " replied with status " + howBad); + if (_log.shouldLog(Log.INFO)) + _log.info(msg.getUniqueId() + ": Peer " + peer.toBase64() + " replied with status " + howBad); if (howBad == 0) { // w3wt @@ -415,7 +415,7 @@ class BuildHandler { int proactiveDrops = countProactiveDrops(); long recvDelay = System.currentTimeMillis()-state.recvTime; if (response == 0) { - float pDrop = recvDelay / (BuildRequestor.REQUEST_TIMEOUT/2); + float pDrop = recvDelay / (BuildRequestor.REQUEST_TIMEOUT); pDrop = (float)Math.pow(pDrop, 16); if (_context.random().nextFloat() < pDrop) { // || (proactiveDrops > MAX_PROACTIVE_DROPS) ) ) { _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 class TunnelBuildMessageHandlerJobBuilder implements HandlerJobBuilder { @@ -586,7 +588,7 @@ class BuildHandler { _exec.repoll(); } } else { - if (_exec.wasRecentlyBuilding(reqId)) { + if (DROP_ALL_REQUESTS || _exec.wasRecentlyBuilding(reqId)) { if (_log.shouldLog(Log.WARN)) _log.warn("Dropping the reply " + reqId + ", as we used to be building that"); } else { @@ -608,7 +610,7 @@ class BuildHandler { _context.statManager().addRateData("tunnel.dropLoadBacklog", _inboundBuildMessages.size(), _inboundBuildMessages.size()); } else { 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 float f = _context.random().nextFloat(); if ( (pDrop > f) && (allowProactiveDrop()) ) {