Commit fc3d3b99 authored by juga  's avatar juga
Browse files

fix: v3bwfile: network means by relay type

Calculate network stream and filtered bandwidth averages per relay
type, to obtain bandwidth weights the same way as Torflow.

Closes #40059.
parent bd57e473
Pipeline #3904 passed with stage
in 47 minutes and 15 seconds
......@@ -187,6 +187,14 @@ MAX_RECENT_PRIORITY_RELAY_COUNT = (
MAX_RECENT_PRIORITY_LIST_COUNT * MAX_RELAYS_PER_PRIORITY_LIST
)
# Used by util/stem.py
G = 0
M = 1
E = 2
GE = 3
# Used by lib/scaling.py to calculate network means by relay type
RELAY_TYPES = [G, M, E, GE]
def fail_hard(*a, **kw):
''' Log something ... and then exit as fast as possible '''
......
from statistics import mean
from sbws.globals import RELAY_TYPES
from sbws.util.stem import rs_relay_type
def bw_measurements_from_results(results):
return [
......
......@@ -985,6 +985,11 @@ class V3BWLine(object):
len(bw_line_str), BW_LINE_SIZE)
return bw_line_str
def set_relay_type(self, relay_type):
self.relay_type = relay_type
def del_relay_type(self):
delattr(self, "relay_type")
class V3BWFile(object):
"""
......@@ -1226,12 +1231,11 @@ class V3BWFile(object):
"""
log.info("Calculating relays' bandwidth using Torflow method.")
bw_lines_tf = copy.deepcopy(bw_lines)
# mean (Torflow's strm_avg)
mu = mean([l.bw_mean for l in bw_lines])
# filtered mean (Torflow's filt_avg)
muf = mean([l.bw_filt for l in bw_lines])
log.debug('mu %s', mu)
log.debug('muf %s', muf)
mu_type, muf_type = scaling.network_means_by_relay_type(
bw_lines_tf, router_statuses_d
)
log.debug('mu %s', mu_type)
log.debug('muf %s', muf_type)
# Torflow's ``tot_net_bw``, sum of the scaled bandwidth for the relays
# that are in the last consensus
......@@ -1292,10 +1296,12 @@ class V3BWFile(object):
continue
# Torflow's scaling
ratio_stream = l.bw_mean / mu
ratio_stream_filtered = l.bw_filt / muf
# relay_type is set in `network_means_by_relay_type` in the lines
# above
ratio_stream = l.bw_mean / mu_type[l.relay_type]
ratio_stream_filtered = l.bw_filt / muf_type[l.relay_type]
l.del_relay_type()
ratio = max(ratio_stream, ratio_stream_filtered)
# Assign it to an attribute, so it's not lost before capping and
# rounding
l.bw = ratio * min_bandwidth
......
......@@ -12,9 +12,11 @@ import logging
import os
from sbws.globals import fail_hard
from sbws.globals import (TORRC_STARTING_POINT, TORRC_RUNTIME_OPTIONS,
TORRC_OPTIONS_CAN_FAIL)
TORRC_OPTIONS_CAN_FAIL, G, M, E, GE)
from sbws import settings
from stem import Flag
log = logging.getLogger(__name__)
stream_building_lock = RLock()
......@@ -325,3 +327,21 @@ def is_torrc_starting_point_set(tor_controller):
if not bad_options:
log.info("Tor is correctly configured to work with sbws.")
return bad_options
def rs_relay_type(rs):
# In torflow, the equivalent to the bw_lines is initialized to "", so when
# the relay is not in the previous consensus and it is not known which
# flags it has, it would return "Medium", as it's the fail case in
# Node.node_class().
# It is not known if it is a bug, or a desired side effect that they relays
# not in the consensus will end up in the Middle class
if not rs:
return M
if Flag.EXIT in rs.flags and Flag.GUARD in rs.flags:
return GE
if Flag.GUARD in rs.flags:
return G
if Flag.EXIT in rs.flags:
return E
return M
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment