[tor-commits] [metrics-tasks/master] Add ipv6.py script for tpo/metrics/trac#40002.

karsten at torproject.org karsten at torproject.org
Mon Jul 13 07:48:19 UTC 2020


commit 2cab2b49267cb5e0f7fb8f7f89926b244a2d3acb
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Mon Jul 13 09:47:54 2020 +0200

    Add ipv6.py script for tpo/metrics/trac#40002.
---
 tpo-metrics-trac-40002/README.md |   4 +
 tpo-metrics-trac-40002/ipv6.py   | 173 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 177 insertions(+)

diff --git a/tpo-metrics-trac-40002/README.md b/tpo-metrics-trac-40002/README.md
new file mode 100644
index 0000000..e141b02
--- /dev/null
+++ b/tpo-metrics-trac-40002/README.md
@@ -0,0 +1,4 @@
+# Script that Counts IPv6 Relays in the Consensus
+
+See `ipv6.py` for usage information and [tpo/metrics/trac#40002](https://gitlab.torproject.org/tpo/metrics/trac/-/issues/40002) for context.
+
diff --git a/tpo-metrics-trac-40002/ipv6.py b/tpo-metrics-trac-40002/ipv6.py
new file mode 100644
index 0000000..497ea26
--- /dev/null
+++ b/tpo-metrics-trac-40002/ipv6.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python3
+
+"""
+----------------------------------------------------------------------------
+
+This script implements Section 3 of Proposal 313:
+
+3. Monitoring IPv6 Relays in the Consensus
+
+We propose writing a script that calculates:
+  * the number of relays, and
+  * the consensus weight fraction of relays,
+in the consensus that:
+  * have an IPv6 ORPort,
+  * support IPv6 reachability checks,
+  * support IPv6 clients, and
+  * support IPv6 reachability checks, and IPv6 clients.
+
+In order to provide easy access to these statistics, we propose
+that the script should:
+  * download a consensus (or read an existing consensus), and
+  * calculate and report these statistics.
+
+The following consensus weight fractions should divide by the total
+consensus weight:
+  * have an IPv6 ORPort (all relays have an IPv4 ORPort), and
+  * support IPv6 reachability checks (all relays support IPv4 reachability).
+
+The following consensus weight fractions should divide by the
+"usable Guard" consensus weight:
+  * support IPv6 clients, and
+  * support IPv6 reachability checks and IPv6 clients.
+
+"Usable Guards" have the Guard flag, but do not have the Exit flag. If the
+Guard also has the BadExit flag, the Exit flag should be ignored.
+
+Note that this definition of "Usable Guards" is only valid when the
+consensus contains many more guards than exits. That is, Wgd must be 0 in
+the consensus. (See the [Tor Directory Protocol] for more details.)
+
+Therefore, the script should check that Wgd is 0. If it is not, the script
+should log a warning about the accuracy of the "Usable Guard" statistics.
+
+----------------------------------------------------------------------------
+
+Copyright 2020 The Tor Project
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the following disclaimer
+  in the documentation and/or other materials provided with the
+  distribution.
+
+* Neither the names of the copyright owners nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------
+"""
+
+import sys, stem, stem.version, stem.descriptor
+
+partial_support_version = stem.version.Version('0.4.4')
+full_support_version = stem.version.Version('0.4.5')
+
+def read(consensus_filename):
+
+    parsed_consensus = stem.descriptor.parse_file(consensus_filename,
+            descriptor_type = 'network-status-consensus-3 1.0')
+
+    valid_after = None
+    wgd = None
+
+    relays = []
+    relays_ipv6 = []
+    relays_partial = []
+    relays_full = []
+    guards = []
+    guards_ipv6 = []
+    guards_partial = []
+    guards_full = []
+
+    for relay in parsed_consensus:
+
+        if not valid_after:
+            valid_after = relay.document.valid_after
+            wgd = relay.document.bandwidth_weights["Wgd"]
+
+        if relay.bandwidth is None:
+            continue
+
+        has_ipv6_address = False
+        if relay.or_addresses:
+            for or_address in relay.or_addresses:
+                if len(or_address) == 3 and or_address[2]:
+                    has_ipv6_address = True
+        is_usable_guard = False
+        if relay.flags:
+            if "Guard" in relay.flags and (
+                    "Exit" not in relay.flags or "BadExit" in relay.flags):
+                is_usable_guard = True
+        has_partial_support = False
+        has_full_support = False
+        if relay.version:
+            if relay.version >= full_support_version:
+                has_full_support = True
+            if relay.version >= partial_support_version:
+                has_partial_support = True
+
+        relays.append(relay.bandwidth)
+        if has_ipv6_address:
+            relays_ipv6.append(relay.bandwidth)
+            if has_partial_support:
+                relays_partial.append(relay.bandwidth)
+            if has_full_support:
+                relays_full.append(relay.bandwidth)
+        if is_usable_guard:
+            guards.append(relay.bandwidth)
+            if has_ipv6_address:
+                guards_ipv6.append(relay.bandwidth)
+                if has_partial_support:
+                    guards_partial.append(relay.bandwidth)
+                if has_full_support:
+                    guards_full.append(relay.bandwidth)
+
+    print("\nParsed consensus with valid-after time {0}:".format(valid_after))
+    print(" - Consensus contains {0} relays:".format(len(relays)))
+    print("   - {0} of these ({1:.2f}% TCW) have an IPv6 ORPort.".
+            format(len(relays_ipv6), 100 * sum(relays_ipv6) / sum(relays)))
+    print("   - {0} of these ({1:.2f}% TCW) support at least partial IPv6 reachability checks.".
+            format(len(relays_partial), 100 * sum(relays_partial) / sum(relays)))
+    print("   - {0} of these ({1:.2f}% TCW) support full IPv6 reachability checks.".
+            format(len(relays_full), 100 * sum(relays_full) / sum(relays)))
+    print(" - Consensus contains {0} \"usable guards\" and Wgd={1}.".
+            format(len(guards), wgd))
+    print("   - {0} of these ({1:.2f}% UGCW) support IPv6 clients.".
+            format(len(guards_ipv6), 100 * sum(guards_ipv6) / sum(guards)))
+    print("   - {0} of these ({1:.2f}% UGCW) support at least partial IPv6 reachability checks.".
+            format(len(guards_partial), 100 * sum(guards_partial) / sum(guards)))
+    print("   - {0} of these ({1:.2f}% UGCW) support full IPv6 reachability checks.".
+            format(len(guards_full), 100 * sum(guards_full) / sum(guards)))
+    if wgd != 0:
+        print("   - WARNING: \"usable guards\" definition is only valid when Wgd=0!")
+
+def main():
+    if len(sys.argv) < 2:
+        print("Please provide one or more downloaded consensus files as arguments.")
+    else:
+        for argv in sorted(sys.argv[1:]):
+            read(argv)
+        print()
+
+if __name__ == '__main__':
+    sys.exit(main())
+



More information about the tor-commits mailing list