java.lang.Object
net.i2p.router.tunnel.pool.ParticipatingThrottler

public class ParticipatingThrottlerextends Object
Count how often we have accepted a tunnel with the peer as the previous or next hop. We limit each peer to a percentage of all participating tunnels, subject to minimum and maximum values for the limit.

This offers basic protection against simple attacks but is not a complete solution, as by design, we don't know the originator of a tunnel request.

This also effectively limits the number of tunnels between any given pair of routers, which probably isn't a bad thing.

  • Field Details

    • IS_SLOW

      static final boolean IS_SLOW
      True on platforms we treat as slow. Selects a more conservative percentage divisor (300 rather than 100) and a lower _minLimit cap in baseLimitFor(int, boolean, boolean, int, int, int, boolean). Package-visible so the limit arithmetic can be pinned for both branches without a RouterContext.
    • _minLimit

      public static volatile int _minLimit
      Min tunnels per peer before throttling.
    • _maxLimit

      public static volatile int _maxLimit
      Max tunnels per peer before throttling.
    • _percentLimit

      public static volatile int _percentLimit
      Max pct of participating tunnels per peer.
    • _rejectThreshold

      public static volatile int _rejectThreshold
      Rejection threshold: start rejecting at count/limit ratio this high (30-100, default 70%).
    • _rejectSteepness

      public static volatile int _rejectSteepness
      Rejection steepness: 100=linear ramp, 200=quadratic, higher=faster escalation.
    • _loadWeight

      public static volatile int _loadWeight
      Load weight: how much load inflates effective ratio (0-300%, default 100%).
  • Constructor Details

    • ParticipatingThrottler

      ParticipatingThrottler(RouterContext ctx)
      Participating throttler.
      Parameters:
      ctx - the router context supplying properties, rate stats and the ban logger that records throttled peers
  • Method Details

    • getParticipatingMinLimit

      public static int getParticipatingMinLimit()
      The participating minimum limit.
      Returns:
      tunnels per peer below which throttling never applies
    • setParticipatingMinLimit

      public static void setParticipatingMinLimit(int val)
      The participating minimum limit.
      Parameters:
      val - tunnels per peer below which throttling never applies, clamped to 20-500
    • getParticipatingMaxLimit

      public static int getParticipatingMaxLimit()
      The participating maximum limit.
      Returns:
      tunnels per peer at which throttling is at full strength
    • setParticipatingMaxLimit

      public static void setParticipatingMaxLimit(int val)
      The participating maximum limit.
      Parameters:
      val - tunnels per peer at which throttling is at full strength, clamped to 50-1000
    • getParticipatingPctLimit

      public static int getParticipatingPctLimit()
      The participating percent limit.
      Returns:
      max percentage of a peer's tunnels that may participate
    • setParticipatingPctLimit

      public static void setParticipatingPctLimit(int val)
      The participating percent limit.
      Parameters:
      val - max percentage of a peer's tunnels that may participate, clamped to 5-100
    • getRejectThreshold

      public static int getRejectThreshold()
      The rejection threshold.
      Returns:
      count/limit ratio percentage at which rejection starts
    • setRejectThreshold

      public static void setRejectThreshold(int val)
      The rejection threshold.
      Parameters:
      val - count/limit ratio percentage at which rejection starts, clamped to 30-100
    • getRejectSteepness

      public static int getRejectSteepness()
      The rejection steepness.
      Returns:
      how fast rejection probability ramps past the threshold; 100 is linear
    • setRejectSteepness

      public static void setRejectSteepness(int val)
      The rejection steepness.
      Parameters:
      val - how fast rejection probability ramps past the threshold, clamped to 100-500
    • getLoadWeight

      public static int getLoadWeight()
      The load weight.
      Returns:
      how much system load inflates the effective ratio, as a percentage
    • setLoadWeight

      public static void setLoadWeight(int val)
      The load weight.
      Parameters:
      val - how much system load inflates the effective ratio, clamped to 0-300
    • shouldThrottle

      Determines whether to throttle tunnel participation for the given router, counting the request against the peer's limit.
      Parameters:
      h - the hash of the router to check
      Returns:
      the throttling Result (ACCEPT, REJECT, or DROP)
    • shouldThrottle

      ParticipatingThrottler.Result shouldThrottle(Hash h, boolean countRequest)
      Determines whether to throttle tunnel participation for the given router. When countRequest is set the request increments the peer's counter; consult-only checks read the current count without advancing it, and never DROP or ban on it: a count this request did not contribute to must not silently kill it, and mid-chain hops would otherwise accumulate roughly twice per tunnel via both their prev-hop and next-hop roles.
      Parameters:
      h - the hash of the router to check
      countRequest - true to increment the peer's counter
      Returns:
      the throttling Result (ACCEPT, REJECT, or DROP)
    • limitInvariantCacheStale

      static boolean limitInvariantCacheStale(long lastQueried, long now, RouterContext cachedCtx, RouterContext ctx)
      Whether the two invariant limit inputs are old enough to re-read. Never-read (lastQueried == 0) counts as stale so the first call reads them rather than trusting the field initializers. A swapped RouterContext (unit tests build their own) invalidates regardless of age, as does a wall-clock step backwards, which a plain age comparison would keep serving until the clock caught up again.
      Parameters:
      lastQueried - the wall-clock ms of the previous read, or 0
      now - the current wall-clock ms
      cachedCtx - the context the cached values were read against
      ctx - the context being asked for now
      Returns:
      true if the cached values should be refreshed
    • computeLimit

      static int computeLimit(int numTunnels, boolean isUnreachable, boolean isLowShare, boolean isFast, int maxTunnels, double bwUsage, int sysLoad)
      The participation-limit arithmetic, with every input supplied, so it can be exercised without a RouterContext. Reads the policy fields (_minLimit, _maxLimit, _percentLimit, IS_SLOW) and applies the capacity relaxation, the idle-CPU bonus and the participation floor.
      Parameters:
      numTunnels - the current count of participating tunnels
      isUnreachable - true if the router is unreachable
      isLowShare - true if the router has low bandwidth share
      isFast - true if the router has high bandwidth share; not consumed by the current arithmetic, kept so the signature matches calculateLimit(int, boolean, boolean, boolean) and shouldThrottle(Hash, boolean)
      maxTunnels - the configured participating tunnel ceiling
      bwUsage - outbound bandwidth usage as a fraction of the limit, 0 when unknown
      sysLoad - system load 0-100
      Returns:
      the per-peer tunnel participation limit, floored to prevent starvation
    • baseLimitFor

      static int baseLimitFor(int numTunnels, boolean isUnreachable, boolean isLowShare, int minLimit, int maxLimit, int pctLimit, boolean isSlow)
      Percentage share of participating tunnels granted to one peer, before any relaxation. Unreachable and low-share peers are held to a fifth of the nominal share (a tenth on slow platforms) and capped at the min limit. Everyone else gets the full share and may reach three times the min limit, bounded below by half the max limit. The divisors are applied in floating point so a low pctLimit cannot truncate the share to zero.
      Parameters:
      numTunnels - the current count of participating tunnels
      isUnreachable - true if the router is unreachable
      isLowShare - true if the router has low bandwidth share
      minLimit - the min limit
      maxLimit - the max limit
      pctLimit - the max pct of participating tunnels per peer
      isSlow - true to use the conservative slow-platform divisor
      Returns:
      the unrelaxed percentage-based limit
    • calculateLoadScore

      static float calculateLoadScore(RouterContext context)
      Computes a 0.0–1.0 load score from job queue lag, CPU load, system load, and bandwidth queue pressure, reusing the score computed within the last LOAD_SCORE_CACHE_MS. Used to shift the rejection probability curve left when the router is under load. Shared by ParticipatingThrottler and RequestThrottler; both the score and the RateStat handle are cached per context.

      Publication order matters: the score and its context are written before the timestamp, so a thread that sees a fresh timestamp also sees the matching score. Concurrent callers may both compute - the worst case is one redundant computation per interval, so no lock is taken.

      Parameters:
      context - the context to read the load inputs from
      Returns:
      the load score, 0.0 (idle) to 1.0 (saturated)
      See Also:
    • loadScoreCacheStale

      static boolean loadScoreCacheStale(long lastQueried, long now, RouterContext cachedCtx, RouterContext ctx)
      Whether the cached load score is old enough to recompute. Never-computed (lastQueried == 0) counts as stale so the first call computes rather than returning the 0.0 initializer. A swapped RouterContext (unit tests build their own) invalidates regardless of age, as does a wall-clock step backwards, which a plain age comparison would keep serving until the clock caught up again.
      Parameters:
      lastQueried - the wall-clock ms of the previous computation, or 0
      now - the current wall-clock ms
      cachedCtx - the context the cached score was computed against
      ctx - the context being asked for now
      Returns:
      true if the score should be recomputed
    • computeLoadScore

      static float computeLoadScore(RouterContext context)
      Uncached 0.0–1.0 load score from job queue lag, CPU load, system load, and bandwidth queue pressure. Job lag contributes 40% of the score and saturates at 1000ms, CPU load 25%, system load 20%, and bandwidth queue pressure 15%, saturating at 100KB/s. Each input is clamped to its own range so a lagging counter cannot push the total past 1.0.
      Parameters:
      context - the context to read the load inputs from
      Returns:
      the load score, 0.0 (idle) to 1.0 (saturated)