[tor-commits] [pytorctl/master] Create option to add in exits if we don't have enough in a slice.
mikeperry at torproject.org
mikeperry at torproject.org
Mon Jun 1 05:36:54 UTC 2015
commit e2561cb287796bd161648d3879ec562d17fbb623
Author: Mike Perry <mikeperry+git at torproject.org>
Date: Wed May 27 16:05:21 2015 -0700
Create option to add in exits if we don't have enough in a slice.
---
PathSupport.py | 44 +++++++++++++++++++++++++++++++++++++++++++-
SQLSupport.py | 10 ++++++++--
ScanSupport.py | 7 +++++--
3 files changed, 56 insertions(+), 5 deletions(-)
diff --git a/PathSupport.py b/PathSupport.py
index c9c5ee1..8d86d3f 100644
--- a/PathSupport.py
+++ b/PathSupport.py
@@ -317,6 +317,20 @@ class ConserveExitsRestriction(NodeRestriction):
def __str__(self):
return self.__class__.__name__+"()"
+class ExitPortRestriction(NodeRestriction):
+ "Restriction to select exits that can exit to a port list"
+ def __init__(self, exit_ports=None):
+ self.exit_ports = exit_ports
+
+ def r_is_ok(self, r):
+ for port in self.exit_ports:
+ if not r.will_exit_to("255.255.255.255", port):
+ return False
+ return True
+
+ def __str__(self):
+ return self.__class__.__name__+"()"
+
class FlagsRestriction(NodeRestriction):
"Restriction for mandatory and forbidden router flags"
def __init__(self, mandatory, forbidden=[]):
@@ -1030,7 +1044,7 @@ class SelectionManager(BaseSelectionManager):
percent_fast, percent_skip, min_bw, use_all_exits,
uniform, use_exit, use_guards,geoip_config=None,
restrict_guards=False, extra_node_rstr=None, exit_ports=None,
- order_by_ratio=False):
+ order_by_ratio=False, min_exits=0):
BaseSelectionManager.__init__(self)
self.__ordered_exit_gen = None
self.pathlen = pathlen
@@ -1049,6 +1063,8 @@ class SelectionManager(BaseSelectionManager):
self.exit_ports = exit_ports
self.extra_node_rstr=extra_node_rstr
self.order_by_ratio = order_by_ratio
+ self.min_exits = min_exits
+ self.added_exits = []
def reconfigure(self, consensus=None):
try:
@@ -1126,6 +1142,21 @@ class SelectionManager(BaseSelectionManager):
mid_rstr.add_restriction(self.extra_node_rstr)
self.exit_rstr.add_restriction(self.extra_node_rstr)
+ # This is a hack just for the bw auths to avoid slices with no exits
+ if self.min_exits and self.exit_ports:
+ test_rstr = NodeRestrictionList(
+ [PctRstr(nonentry_skip, nonentry_fast, sorted_r),
+ ExitPortRestriction(self.exit_ports),
+ FlagsRestriction(["Running"], ["BadExit"])])
+ exit_count = len(filter(lambda r: test_rstr.r_is_ok(r), sorted_r))
+ if exit_count < self.min_exits:
+ self.added_exits = self.find_emergency_exits(sorted_r,
+ self.min_exits-exit_count)
+ plog("NOTICE", "Only "+str(exit_count)+" exits remain in slice "+str(nonentry_skip)+"-"+str(nonentry_fast)+" after restrictions. Adding in "+str(self.added_exits))
+ idhex_list = map(IdHexRestriction, self.added_exits)
+ idhex_list.append(self.exit_rstr)
+ self.exit_rstr = NodeRestrictionList([OrNodeRestriction(idhex_list)])
+
# GeoIP configuration
if self.geoip_config:
# Every node needs country_code
@@ -1198,6 +1229,17 @@ class SelectionManager(BaseSelectionManager):
exitgen, self.path_rstr)
return
+ # Picks num of the top_n fastest exits that can handle our exit ports.
+ def find_emergency_exits(self, sorted_r, num, top_n=100):
+ new_exits = []
+ test_rstr = NodeRestrictionList(
+ [ExitPortRestriction(self.exit_ports),
+ FlagsRestriction(["Running"], ["BadExit"])])
+ for r in sorted_r:
+ if test_rstr.r_is_ok(r): new_exits.append(r.idhex)
+ if len(new_exits) >= top_n: break
+ return random.sample(new_exits, min(len(new_exits), num))
+
def _set_exit(self, exit_name):
# sets an exit, if bad, sets bad_exit
exit_id = None
diff --git a/SQLSupport.py b/SQLSupport.py
index 28963fc..ee15d79 100644
--- a/SQLSupport.py
+++ b/SQLSupport.py
@@ -565,7 +565,7 @@ class RouterStats(Entity):
tc_session.remove()
compute = Callable(compute)
- def write_stats(f, pct_low=0, pct_high=100, order_by=None, recompute=False, stat_clause=None, filter_clause=None, disp_clause=None):
+ def write_stats(f, pct_low=0, pct_high=100, order_by=None, recompute=False, stat_clause=None, filter_clause=None, disp_clause=None, ignore_by_idhex=[]):
l_session = tc_session()
if not order_by:
@@ -626,6 +626,9 @@ class RouterStats(Entity):
for s in RouterStats.query.filter(pct_clause).filter(stat_clause).\
filter(disp_clause).order_by(order_by).all():
+ if s.router.idhex in ignore_by_idhex:
+ plog("NOTICE", "Skipping stats on added exit "+s.router.idhex+" in "+f.name)
+ continue
f.write(s.router.idhex+" ("+s.router.nickname+")\n")
f.write(" CF="+str(cvt(s.circ_from_rate,2)))
f.write(" CT="+str(cvt(s.circ_to_rate,2)))
@@ -649,7 +652,7 @@ class RouterStats(Entity):
write_stats = Callable(write_stats)
- def write_bws(f, pct_low=0, pct_high=100, order_by=None, recompute=False, stat_clause=None, filter_clause=None, disp_clause=None):
+ def write_bws(f, pct_low=0, pct_high=100, order_by=None, recompute=False, stat_clause=None, filter_clause=None, disp_clause=None, ignore_by_idhex=[]):
l_session = tc_session()
if not order_by:
order_by=RouterStats.avg_first_ext
@@ -678,6 +681,9 @@ class RouterStats(Entity):
for s in RouterStats.query.filter(pct_clause).filter(stat_clause).\
filter(disp_clause).order_by(order_by).all():
+ if s.router.idhex in ignore_by_idhex:
+ plog("NOTICE", "Skipping stats on added exit "+s.router.idhex+" in "+f.name)
+ continue
f.write("node_id=$"+s.router.idhex+" nick="+s.router.nickname)
f.write(" strm_bw="+str(cvt(s.sbw,0)))
f.write(" filt_bw="+str(cvt(s.filt_sbw,0)))
diff --git a/ScanSupport.py b/ScanSupport.py
index e6752c5..797fe39 100644
--- a/ScanSupport.py
+++ b/ScanSupport.py
@@ -79,6 +79,7 @@ class ScanHandler(PathSupport.PathBuilder):
cond.acquire()
this.new_nym = True
if this.selmgr.bad_restrictions:
+ # XXX: Maybe add in exits here?
plog("NOTICE", "Clearing bad restrictions with reconfigure..")
this.selmgr.reconfigure(this.current_consensus())
lines = this.c.sendAndRecv("SIGNAL CLEARDNSCACHE\r\n")
@@ -198,7 +199,8 @@ class SQLScanHandler(ScanHandler):
cond.acquire()
SQLSupport.RouterStats.write_stats(file(rfilename, "w"),
0, 100, order_by=SQLSupport.RouterStats.sbw,
- recompute=True, disp_clause=stats_filter)
+ recompute=True, disp_clause=stats_filter,
+ ignore_by_idhex=h.selmgr.added_exits)
cond.notify()
cond.release()
cond.acquire()
@@ -216,7 +218,8 @@ class SQLScanHandler(ScanHandler):
f.write("slicenum="+str(slice_num)+"\n")
SQLSupport.RouterStats.write_bws(f, 0, 100,
order_by=SQLSupport.RouterStats.sbw,
- recompute=False, disp_clause=stats_filter)
+ recompute=False, disp_clause=stats_filter,
+ ignore_by_idhex=this.selmgr.added_exits)
f.close()
cond.notify()
cond.release()
More information about the tor-commits
mailing list