SSU2: Set peer test result to firewalled if no peers available to test

and uptime > 10m and no incoming connections for 10m
to catch completely broken IPv6.
Increase SSU min peers to 10 to improve chance of peer test success.
This commit is contained in:
zzz
2026-03-21 16:05:18 -04:00
parent 39b2116afa
commit 12e2dad36b
2 changed files with 78 additions and 7 deletions
@@ -6,6 +6,7 @@ import net.i2p.router.RouterContext;
import net.i2p.util.Log;
import net.i2p.util.SimpleTimer2;
import net.i2p.router.CommSystemFacade.Status;
import static net.i2p.router.transport.TransportUtil.IPv6Config.*;
import static net.i2p.router.transport.udp.PeerTestState.Role.*;
@@ -94,6 +95,7 @@ class PeerTestEvent extends SimpleTimer2.TimedEvent {
private void locked_runTest(boolean isIPv6) {
_lastTestIPv6 = isIPv6;
boolean allowForce = false;
PeerState bob = _transport.pickTestPeer(BOB, 0, isIPv6, null);
if (bob != null) {
if (_log.shouldLog(Log.INFO))
@@ -104,10 +106,73 @@ class PeerTestEvent extends SimpleTimer2.TimedEvent {
} else {
if (_log.shouldLog(Log.WARN))
_log.warn("Unable to run peer test, no peers available - v6? " + isIPv6);
if (_context.router().getUptime() > 10*60*1000 &&
_transport.countPeers() >= UDPTransport.MIN_PEERS &&
_transport.getInboundConnectionLastReceived(isIPv6) < _context.clock().now() - 10*60*1000) {
// if we have no test peers at all after 10 minutes, presume firewalled
Status old = _transport.getReachabilityStatus();
if (isIPv6) {
switch (old) {
case OK:
case IPV4_OK_IPV6_UNKNOWN:
case IPV4_OK_IPV6_FIREWALLED:
case IPV4_UNKNOWN_IPV6_OK:
case IPV4_FIREWALLED_IPV6_OK:
case IPV4_DISABLED_IPV6_OK:
case IPV4_SNAT_IPV6_OK:
case IPV4_SNAT_IPV6_UNKNOWN:
case IPV4_FIREWALLED_IPV6_UNKNOWN:
case REJECT_UNSOLICITED:
case IPV4_UNKNOWN_IPV6_FIREWALLED:
case IPV4_DISABLED_IPV6_UNKNOWN:
case IPV4_DISABLED_IPV6_FIREWALLED:
case UNKNOWN:
Status status = Status.IPV4_UNKNOWN_IPV6_FIREWALLED;
if (_log.shouldWarn())
_log.warn("Old status: " + old + " new status: " + status);
_transport.setReachabilityStatus(status, isIPv6);
allowForce = true;
break;
default:
// SYMNAT, DISCONNECTED, HOSED, ...
if (_log.shouldWarn())
_log.warn("Not changing current status: " + old);
break;
}
} else {
switch (old) {
case OK:
case IPV4_OK_IPV6_UNKNOWN:
case IPV4_OK_IPV6_FIREWALLED:
case IPV4_UNKNOWN_IPV6_OK:
case IPV4_FIREWALLED_IPV6_OK:
case IPV4_DISABLED_IPV6_OK:
case IPV4_FIREWALLED_IPV6_UNKNOWN:
case REJECT_UNSOLICITED:
case IPV4_UNKNOWN_IPV6_FIREWALLED:
case IPV4_DISABLED_IPV6_UNKNOWN:
case IPV4_DISABLED_IPV6_FIREWALLED:
case UNKNOWN:
Status status = Status.IPV4_FIREWALLED_IPV6_UNKNOWN;
if (_log.shouldWarn())
_log.warn("Old status: " + old + " new status: " + status);
_transport.setReachabilityStatus(status, isIPv6);
allowForce = true;
break;
default:
if (_log.shouldWarn())
_log.warn("Not changing current status: " + old);
break;
}
}
}
}
// We switch to NO_FORCE even if no peers,
// We switch to NO_FORCE unless no peers,
// so we don't get stuck running the same test over and over
_forceRun &= ~(isIPv6 ? FORCE_IPV6 : FORCE_IPV4);
if (!allowForce)
_forceRun &= ~(isIPv6 ? FORCE_IPV6 : FORCE_IPV4);
}
/**
@@ -236,7 +236,7 @@ public class UDPTransport extends TransportImpl {
private static final int SSU_OUTBOUND_COST = 14;
static final long[] RATES = { 10*60*1000 };
/** minimum active peers to maintain IP detection, etc. */
private static final int MIN_PEERS = 5;
static final int MIN_PEERS = 10;
private static final int MIN_PEERS_IF_HAVE_V6 = 30;
/** minimum peers volunteering to be introducers if we need that */
private static final int MIN_INTRODUCER_POOL = 5;
@@ -1155,12 +1155,18 @@ public class UDPTransport extends TransportImpl {
} else {
// Introduced connections are still inbound, this is not evidence
// that we are not firewalled.
// use OS clock since its an ordering thing, not a time thing
_lastInboundReceivedOn = System.currentTimeMillis();
_lastInboundReceivedOn = _context.clock().now();
_context.statManager().addRateData("udp.inboundIPv4Conn", 1);
}
}
/**
* @since 0.9.69
*/
long getInboundConnectionLastReceived(boolean isIPv6) {
return isIPv6 ? _lastInboundIPv6 : _lastInboundReceivedOn;
}
// temp prevent multiples
private boolean gotIPv4Addr = false;
private boolean gotIPv6Addr = false;
@@ -1309,7 +1315,7 @@ public class UDPTransport extends TransportImpl {
boolean inboundRecent;
boolean isIPv6 = ourIP.length == 16;
if (!isIPv6)
inboundRecent = _lastInboundReceivedOn + ALLOW_IP_CHANGE_INTERVAL > System.currentTimeMillis();
inboundRecent = _lastInboundReceivedOn + ALLOW_IP_CHANGE_INTERVAL > _context.clock().now();
else
inboundRecent = _lastInboundIPv6 + ALLOW_IP_CHANGE_INTERVAL > _context.clock().now();
if (_log.shouldLog(Log.INFO))