From 82b7eea5f0a6a68de97e374831986540f59fffe0 Mon Sep 17 00:00:00 2001 From: zzz Date: Mon, 8 Mar 2021 08:12:10 -0500 Subject: [PATCH] SSU: Increase CoDel drop threshold at UDPSender queue Increase min and max queue size Tweak stats Util: Allow creation of CoDel queues with non-default parameters New params are tentative, may be adjusted later --- history.txt | 19 +++++++++++ .../src/net/i2p/router/RouterVersion.java | 2 +- .../i2p/router/transport/udp/UDPSender.java | 16 +++++---- .../i2p/router/util/CoDelBlockingQueue.java | 34 +++++++++++++------ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/history.txt b/history.txt index 92fd7051f..6d78d3e22 100644 --- a/history.txt +++ b/history.txt @@ -1,9 +1,28 @@ +2021-03-08 zzz + * SSU: Increase CoDel drop threshold at UDPSender queue + +2021-03-06 zzz + * SSU: Require confirmation for IPv6 firewalled state transitions + +2021-03-04 zzz + * I2CP: More prep for different release and API versions + * i2ptunnel: Add missing button icons for proxy forms + * Router: Increase rekey probability + * Transports: Prefer IPv6 temporary addresses if the kernel does + 2021-03-03 zzz + * NTCP: Fix reachability status when force-firewalled * SSU: - Only advertise 'C' cap if we can really introduce - Only ask for relay tag if we don't have enough - Fix transition out of IPv4 firewalled after UPnP success - Fix validation of current introducers + - Don't publish IPv4 address at startup when force-firewalled + - Publish empty '4' address if firewalled and no introducers + - Publish empty '6' address if firewalled + - 4/6 caps fixes + - Increase hole punch rate limit + * UPnP: Fix retention of deprecated addresses 2021-03-02 zzz * UPnP: diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 9bc4388a0..f2424bd3b 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Git"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 5; + public final static long BUILD = 6; /** for example "-test" */ public final static String EXTRA = ""; 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 dc6078da5..c266e92d2 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPSender.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPSender.java @@ -35,8 +35,10 @@ class UDPSender { // Queue needs to be big enough that we can compete with NTCP for // bandwidth requests, and so CoDel can work well. // When full, packets back up into the PacketPusher thread, pre-CoDel. - private static final int MIN_QUEUE_SIZE = 64; - private static final int MAX_QUEUE_SIZE = 384; + private static final int MIN_QUEUE_SIZE = 128; + private static final int MAX_QUEUE_SIZE = 768; + private static final int CODEL_TARGET = 100; + private static final int CODEL_INTERVAL = 500; public UDPSender(RouterContext ctx, DatagramSocket socket, String name, SocketListener lsnr) { _context = ctx; @@ -44,7 +46,7 @@ class UDPSender { _log = ctx.logManager().getLog(UDPSender.class); long maxMemory = SystemVersion.getMaxMemory(); int qsize = (int) Math.max(MIN_QUEUE_SIZE, Math.min(MAX_QUEUE_SIZE, maxMemory / (1024*1024))); - _outboundQueue = new CoDelBlockingQueue(ctx, "UDP-Sender", qsize); + _outboundQueue = new CoDelBlockingQueue(ctx, "UDP-Sender", qsize, CODEL_TARGET, CODEL_INTERVAL); _socket = socket; _runner = new Runner(); _name = name; @@ -283,13 +285,13 @@ class UDPSender { if (throttleTime > 10) _context.statManager().addRateData("udp.sendBWThrottleTime", throttleTime, acquireTime - packet.getBegin()); if (packet.getMarkedType() == 1) - _context.statManager().addRateData("udp.sendACKTime", throttleTime, packet.getLifetime()); - _context.statManager().addRateData("udp.pushTime", packet.getLifetime(), packet.getLifetime()); - _context.statManager().addRateData("udp.sendPacketSize", size, packet.getLifetime()); + _context.statManager().addRateData("udp.sendACKTime", throttleTime); + _context.statManager().addRateData("udp.pushTime", packet.getLifetime()); + _context.statManager().addRateData("udp.sendPacketSize", size); } catch (IOException ioe) { if (_log.shouldLog(Log.WARN)) _log.warn("Error sending to " + packet.getPacket().getAddress(), ioe); - _context.statManager().addRateData("udp.sendException", 1, packet.getLifetime()); + _context.statManager().addRateData("udp.sendException", 1); if (_socket.isClosed()) { if (_keepRunning) { _keepRunning = false; diff --git a/router/java/src/net/i2p/router/util/CoDelBlockingQueue.java b/router/java/src/net/i2p/router/util/CoDelBlockingQueue.java index 77a995d21..973018731 100644 --- a/router/java/src/net/i2p/router/util/CoDelBlockingQueue.java +++ b/router/java/src/net/i2p/router/util/CoDelBlockingQueue.java @@ -56,17 +56,17 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< * * I2P: Raise to 15 due to multithreading environment * - * Maybe need to make configurable per-instance. */ - private static final long TARGET = 15; + private static final int TARGET = 15; + private final long _target; /** * Quote: * A setting of 100 ms works well across a range of RTTs from 10 ms to 1 second * - * Maybe need to make configurable per-instance. */ - private static final long INTERVAL = 100; + private static final int INTERVAL = 100; + private final long _interval; //private static final int MAXPACKET = 512; private final String STAT_DROP; @@ -75,14 +75,28 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< private static final long BACKLOG_TIME = 2*1000; /** + * Target 15, interval 100 + * * @param name for stats */ public CoDelBlockingQueue(I2PAppContext ctx, String name, int capacity) { + this(ctx, name, capacity, TARGET, INTERVAL); + } + + /** + * @param target the target max latency (ms) + * @param interval how long above target to start dropping (ms) + * @param name for stats + * @since 0.9.50 + */ + public CoDelBlockingQueue(I2PAppContext ctx, String name, int capacity, int target, int interval) { super(capacity); _context = ctx; _log = ctx.logManager().getLog(CoDelBlockingQueue.class); _name = name; _capacity = capacity; + _target = target; + _interval = interval; STAT_DROP = ("codel." + name + ".drop").intern(); STAT_DELAY = ("codel." + name + ".delay").intern(); ctx.statManager().createRateStat(STAT_DROP, "queue delay of dropped items", "Router", RATES); @@ -207,13 +221,13 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< long sojurn = _now - entry.getEnqueueTime(); _context.statManager().addRateData(STAT_DELAY, sojurn); // I2P use isEmpty instead of size() < MAXPACKET - if (sojurn < TARGET || isEmpty()) { + if (sojurn < _target || isEmpty()) { _first_above_time = 0; } else { if (_first_above_time == 0) { // just went above from below. if we stay above - // for at least INTERVAL we'll say it's ok to drop - _first_above_time = _now + INTERVAL; + // for at least _interval we'll say it's ok to drop + _first_above_time = _now + _interval; } else if (_now >= _first_above_time) { ok_to_drop = true; } @@ -270,7 +284,7 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< } } } else if (ok_to_drop && - (_now - _drop_next < INTERVAL || _now - _first_above_time >= INTERVAL)) { + (_now - _drop_next < _interval || _now - _first_above_time >= _interval)) { // If we get here, then we're not in dropping state. If the sojourn time has been above // target for interval, then we decide whether it's time to enter dropping state. // We do so if we've been either in dropping state recently or above target for a relatively @@ -287,7 +301,7 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< _dropping = true; // If we're in a drop cycle, the drop rate that controlled the queue // on the last cycle is a good starting point to control it now. - if (_now - _drop_next < INTERVAL) + if (_now - _drop_next < _interval) _count = _count > 2 ? _count - 2 : 1; else _count = 1; @@ -313,6 +327,6 @@ public class CoDelBlockingQueue extends LinkedBlockingQueue< * Caller must synch on this */ private void control_law(long t) { - _drop_next = t + (long) (INTERVAL / Math.sqrt(_count)); + _drop_next = t + (long) (_interval / Math.sqrt(_count)); } }