commit 86fae9e607668a1768041ac6cf19ee0b41cb7aea Author: Karsten Loesing karsten.loesing@gmx.net Date: Thu Jul 19 22:32:28 2012 +0200
Add path selection probabilities to details files. --- src/org/torproject/onionoo/CurrentNodes.java | 7 + src/org/torproject/onionoo/DetailDataWriter.java | 137 ++++++++++++++++++++++ src/org/torproject/onionoo/Main.java | 1 + src/org/torproject/onionoo/Node.java | 36 ++++++ web/index.html | 48 ++++++++ 5 files changed, 229 insertions(+), 0 deletions(-)
diff --git a/src/org/torproject/onionoo/CurrentNodes.java b/src/org/torproject/onionoo/CurrentNodes.java index 7c4bec8..7ef1473 100644 --- a/src/org/torproject/onionoo/CurrentNodes.java +++ b/src/org/torproject/onionoo/CurrentNodes.java @@ -250,6 +250,10 @@ public class CurrentNodes { } }
+ SortedMap<String, Integer> lastBandwidthWeights = null; + public SortedMap<String, Integer> getLastBandwidthWeights() { + return this.lastBandwidthWeights; + } private void updateRelayNetworkStatusConsensus( RelayNetworkStatusConsensus consensus) { long validAfterMillis = consensus.getValidAfterMillis(); @@ -268,6 +272,9 @@ public class CurrentNodes { null, validAfterMillis, orPort, dirPort, relayFlags, consensusWeight, null, null, -1L); } + if (this.lastValidAfterMillis == validAfterMillis) { + this.lastBandwidthWeights = consensus.getBandwidthWeights(); + } }
public void addRelay(String nickname, String fingerprint, diff --git a/src/org/torproject/onionoo/DetailDataWriter.java b/src/org/torproject/onionoo/DetailDataWriter.java index 155c4eb..2961de9 100644 --- a/src/org/torproject/onionoo/DetailDataWriter.java +++ b/src/org/torproject/onionoo/DetailDataWriter.java @@ -13,6 +13,7 @@ import java.net.UnknownHostException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -194,6 +195,115 @@ public class DetailDataWriter { } }
+ public void calculatePathSelectionProbabilities( + SortedMap<String, Integer> bandwidthWeights) { + boolean consensusContainsBandwidthWeights = false; + double wgg = 0.0, wgd = 0.0, wmg = 0.0, wmm = 0.0, wme = 0.0, + wmd = 0.0, wee = 0.0, wed = 0.0; + if (bandwidthWeights != null) { + SortedSet<String> weightKeys = new TreeSet<String>(Arrays.asList( + "Wgg,Wgd,Wmg,Wmm,Wme,Wmd,Wee,Wed".split(","))); + weightKeys.removeAll(bandwidthWeights.keySet()); + if (weightKeys.isEmpty()) { + consensusContainsBandwidthWeights = true; + wgg = ((double) bandwidthWeights.get("Wgg")) / 10000.0; + wgd = ((double) bandwidthWeights.get("Wgd")) / 10000.0; + wmg = ((double) bandwidthWeights.get("Wmg")) / 10000.0; + wmm = ((double) bandwidthWeights.get("Wmm")) / 10000.0; + wme = ((double) bandwidthWeights.get("Wme")) / 10000.0; + wmd = ((double) bandwidthWeights.get("Wmd")) / 10000.0; + wee = ((double) bandwidthWeights.get("Wee")) / 10000.0; + wed = ((double) bandwidthWeights.get("Wed")) / 10000.0; + } + } + SortedMap<String, Double> + advertisedBandwidths = new TreeMap<String, Double>(), + consensusWeights = new TreeMap<String, Double>(), + guardWeights = new TreeMap<String, Double>(), + middleWeights = new TreeMap<String, Double>(), + exitWeights = new TreeMap<String, Double>(); + double totalAdvertisedBandwidth = 0.0; + double totalConsensusWeight = 0.0; + double totalGuardWeight = 0.0; + double totalMiddleWeight = 0.0; + double totalExitWeight = 0.0; + for (Map.Entry<String, Node> e : this.relays.entrySet()) { + String fingerprint = e.getKey(); + Node relay = e.getValue(); + if (!relay.getRunning()) { + continue; + } + boolean isExit = relay.getRelayFlags().contains("Exit") && + !relay.getRelayFlags().contains("BadExit"); + boolean isGuard = relay.getRelayFlags().contains("Guard"); + if (this.relayServerDescriptors.containsKey(fingerprint)) { + ServerDescriptor serverDescriptor = + this.relayServerDescriptors.get(fingerprint); + double advertisedBandwidth = (double) Math.min(Math.min( + serverDescriptor.getBandwidthBurst(), + serverDescriptor.getBandwidthObserved()), + serverDescriptor.getBandwidthRate()); + advertisedBandwidths.put(fingerprint, advertisedBandwidth); + totalAdvertisedBandwidth += advertisedBandwidth; + } + double consensusWeight = (double) relay.getConsensusWeight(); + consensusWeights.put(fingerprint, consensusWeight); + totalConsensusWeight += consensusWeight; + if (consensusContainsBandwidthWeights) { + double guardWeight = consensusWeight, + middleWeight = consensusWeight, + exitWeight = consensusWeight; + if (isGuard && isExit) { + guardWeight *= wgd; + middleWeight *= wmd; + exitWeight *= wed; + } else if (isGuard) { + guardWeight *= wgg; + middleWeight *= wmg; + exitWeight = 0.0; + } else if (isExit) { + guardWeight = 0.0; + middleWeight *= wme; + exitWeight *= wee; + } else { + guardWeight = 0.0; + middleWeight *= wmm; + exitWeight = 0.0; + } + guardWeights.put(fingerprint, guardWeight); + middleWeights.put(fingerprint, middleWeight); + exitWeights.put(fingerprint, exitWeight); + totalGuardWeight += guardWeight; + totalMiddleWeight += middleWeight; + totalExitWeight += exitWeight; + } + } + for (Map.Entry<String, Node> e : this.relays.entrySet()) { + String fingerprint = e.getKey(); + Node relay = e.getValue(); + if (advertisedBandwidths.containsKey(fingerprint)) { + relay.setAdvertisedBandwidthFraction(advertisedBandwidths.get( + fingerprint) / totalAdvertisedBandwidth); + } + if (consensusWeights.containsKey(fingerprint)) { + relay.setConsensusWeightFraction(consensusWeights.get(fingerprint) + / totalConsensusWeight); + } + if (guardWeights.containsKey(fingerprint)) { + relay.setGuardProbability(guardWeights.get(fingerprint) + / totalGuardWeight); + } + if (middleWeights.containsKey(fingerprint)) { + relay.setMiddleProbability(middleWeights.get(fingerprint) + / totalMiddleWeight); + } + if (exitWeights.containsKey(fingerprint)) { + relay.setExitProbability(exitWeights.get(fingerprint) + / totalExitWeight); + } + } + } + private long now = System.currentTimeMillis(); private Map<String, Set<ExitListEntry>> exitListEntries = new HashMap<String, Set<ExitListEntry>>(); @@ -444,6 +554,12 @@ public class DetailDataWriter { String aSName = entry.getASName(); long consensusWeight = entry.getConsensusWeight(); String hostName = entry.getHostName(); + double advertisedBandwidthFraction = + entry.getAdvertisedBandwidthFraction(); + double consensusWeightFraction = entry.getConsensusWeightFraction(); + double guardProbability = entry.getGuardProbability(); + double middleProbability = entry.getMiddleProbability(); + double exitProbability = entry.getExitProbability(); StringBuilder sb = new StringBuilder(); sb.append("{"version":1,\n" + ""nickname":"" + nickname + "",\n" @@ -501,6 +617,27 @@ public class DetailDataWriter { sb.append(",\n"host_name":"" + escapeJSON(hostName) + """); } + if (advertisedBandwidthFraction >= 0.0) { + sb.append(String.format( + ",\n"advertised_bandwidth_fraction":%.9f", + advertisedBandwidthFraction)); + } + if (consensusWeightFraction >= 0.0) { + sb.append(String.format(",\n"consensus_weight_fraction":%.9f", + consensusWeightFraction)); + } + if (guardProbability >= 0.0) { + sb.append(String.format(",\n"guard_probability":%.9f", + guardProbability)); + } + if (middleProbability >= 0.0) { + sb.append(String.format(",\n"middle_probability":%.9f", + middleProbability)); + } + if (exitProbability >= 0.0) { + sb.append(String.format(",\n"exit_probability":%.9f", + exitProbability)); + }
/* Add exit addresses if at least one of them is distinct from the * onion-routing addresses. */ diff --git a/src/org/torproject/onionoo/Main.java b/src/org/torproject/onionoo/Main.java index 5cac8de..175176c 100644 --- a/src/org/torproject/onionoo/Main.java +++ b/src/org/torproject/onionoo/Main.java @@ -24,6 +24,7 @@ public class Main { ddw.setCurrentBridges(cn.getCurrentBridges()); ddw.startReverseDomainNameLookups(); ddw.readRelayServerDescriptors(); + ddw.calculatePathSelectionProbabilities(cn.getLastBandwidthWeights()); ddw.readExitLists(); ddw.readBridgeServerDescriptors(); ddw.readBridgePoolAssignments(); diff --git a/src/org/torproject/onionoo/Node.java b/src/org/torproject/onionoo/Node.java index 88ca71c..61a26ed 100644 --- a/src/org/torproject/onionoo/Node.java +++ b/src/org/torproject/onionoo/Node.java @@ -35,6 +35,11 @@ public class Node { private boolean running; private String hostName; private long lastRdnsLookup = -1L; + private double advertisedBandwidthFraction = -1.0; + private double consensusWeightFraction = -1.0; + private double guardProbability = -1.0; + private double middleProbability = -1.0; + private double exitProbability = -1.0; public Node(String nickname, String fingerprint, String address, SortedSet<String> orAddressesAndPorts, SortedSet<String> exitAddresses, long lastSeenMillis, int orPort, @@ -194,5 +199,36 @@ public class Node { public long getLastRdnsLookup() { return this.lastRdnsLookup; } + public void setAdvertisedBandwidthFraction( + double advertisedBandwidthFraction) { + this.advertisedBandwidthFraction = advertisedBandwidthFraction; + } + public double getAdvertisedBandwidthFraction() { + return this.advertisedBandwidthFraction; + } + public void setConsensusWeightFraction(double consensusWeightFraction) { + this.consensusWeightFraction = consensusWeightFraction; + } + public double getConsensusWeightFraction() { + return this.consensusWeightFraction; + } + public void setGuardProbability(double guardProbability) { + this.guardProbability = guardProbability; + } + public double getGuardProbability() { + return this.guardProbability; + } + public void setMiddleProbability(double middleProbability) { + this.middleProbability = middleProbability; + } + public double getMiddleProbability() { + return this.middleProbability; + } + public void setExitProbability(double exitProbability) { + this.exitProbability = exitProbability; + } + public double getExitProbability() { + return this.exitProbability; + } }
diff --git a/web/index.html b/web/index.html index 5788bf9..0578843 100755 --- a/web/index.html +++ b/web/index.html @@ -276,6 +276,54 @@ same family as this relay. Optional field. Omitted if empty or if descriptor containing this information cannot be found.</li> +<li><b><font color="blue">"advertised_bandwidth_fraction":</font></b> +Relative advertised bandwidth of this relay compared to the total +advertised bandwidth in the network. +If there were no bandwidth authorities, this fraction would be a very +rough approximation of the probability of this relay to be selected by +clients. +Optional field. +Omitted if the relay is not running, or router descriptor containing this +information cannot be found. +<font color="blue">Added field on July 19, 2012.</font></li> +<li><b><font color="blue">"consensus_weight_fraction":</font></b> +Fraction of this relay's consensus weight compared to the sum of all +consensus weights in the network. +This fraction is a very rough approximation of the probability of this +relay to be selected by clients. +Optional field. +Omitted if the relay is not running. +<font color="blue">Added field on July 19, 2012.</font></li> +<li><b><font color="blue">"guard_probability":</font></b> +Probability of this relay to be selected for the guard position. +This probability is calculated based on consensus weights, relay flags, +and bandwidth weights in the consensus. +Path selection depends on more factors, so that this probability can only +be an approximation. +Optional field. +Omitted if the relay is not running, or the consensus does not contain +bandwidth weights. +<font color="blue">Added field on July 19, 2012.</font></li> +<li><b><font color="blue">"middle_probability":</font></b> +Probability of this relay to be selected for the middle position. +This probability is calculated based on consensus weights, relay flags, +and bandwidth weights in the consensus. +Path selection depends on more factors, so that this probability can only +be an approximation. +Optional field. +Omitted if the relay is not running, or the consensus does not contain +bandwidth weights. +<font color="blue">Added field on July 19, 2012.</font></li> +<li><b><font color="blue">"exit_probability":</font></b> +Probability of this relay to be selected for the exit position. +This probability is calculated based on consensus weights, relay flags, +and bandwidth weights in the consensus. +Path selection depends on more factors, so that this probability can only +be an approximation. +Optional field. +Omitted if the relay is not running, or the consensus does not contain +bandwidth weights. +<font color="blue">Added field on July 19, 2012.</font></li> </ul> </li> <li><b>"bridges_published":</b> UTC timestamp (YYYY-MM-DD hh:mm:ss) when
tor-commits@lists.torproject.org