| 
					
				 | 
			
			
				@@ -66,6 +66,9 @@ static cached_dir_t *the_directory = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** For authoritative directories: the current (v1) network status. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static cached_dir_t the_runningrouters; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** Total number of routers with measured bandwidth */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int routers_with_measured_bw = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void directory_remove_invalid(void); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static cached_dir_t *dirserv_regenerate_directory(void); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static char *format_versions_list(config_line_t *ln); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -86,6 +89,7 @@ static const signed_descriptor_t *get_signed_descriptor_by_fp( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                 const char **msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static uint32_t dirserv_get_bandwidth_for_router(const routerinfo_t *ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static uint32_t dirserv_get_credible_bandwidth(const routerinfo_t *ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /************** Fingerprint handling code ************/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1877,12 +1881,18 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * include a router in our calculations, and return true iff we should. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 router_counts_toward_thresholds(const node_t *node, time_t now, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                const digestmap_t *omit_as_sybil) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                const digestmap_t *omit_as_sybil, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                int require_mbw) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Have measured bw? */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int have_mbw = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    dirserv_query_measured_bw_cache(node->ri->cache_info.identity_digest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    NULL, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return node->ri && router_is_active(node->ri, node, now) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     !digestmap_get(omit_as_sybil, node->ri->cache_info.identity_digest) && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    (dirserv_get_bandwidth_for_router(node->ri) >= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (dirserv_get_credible_bandwidth(node->ri) >= 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       ABSOLUTE_MIN_BW_VALUE_TO_CONSIDER) && (have_mbw || !require_mbw); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Look through the routerlist, the Mean Time Between Failure history, and 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1904,6 +1914,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   time_t now = time(NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const or_options_t *options = get_options(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Require mbw? */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int require_mbw = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    (routers_with_measured_bw > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     options->MinMeasuredBWsForAuthToIgnoreAdvertised) ? 1 : 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* initialize these all here, in case there are no routers */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   stable_uptime = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   stable_mtbf = 0; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1936,7 +1951,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Now, fill in the arrays. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (router_counts_toward_thresholds(node, now, omit_as_sybil)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (router_counts_toward_thresholds(node, now, omit_as_sybil, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        require_mbw)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       routerinfo_t *ri = node->ri; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const char *id = ri->cache_info.identity_digest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       uint32_t bw; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1945,7 +1961,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       uptimes[n_active] = (uint32_t)real_uptime(ri, now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       mtbfs[n_active] = rep_hist_get_stability(id, now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       tks  [n_active] = rep_hist_get_weighted_time_known(id, now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      bandwidths[n_active] = bw = dirserv_get_bandwidth_for_router(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      bandwidths[n_active] = bw = dirserv_get_credible_bandwidth(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       total_bandwidth += bw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (node->is_exit && !node->is_bad_exit) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         total_exit_bandwidth += bw; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2001,7 +2017,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   n_familiar = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (router_counts_toward_thresholds(node, now, omit_as_sybil)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (router_counts_toward_thresholds(node, now, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                          omit_as_sybil, require_mbw)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         routerinfo_t *ri = node->ri; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const char *id = ri->cache_info.identity_digest; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         long tk = rep_hist_get_weighted_time_known(id, now); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2182,6 +2199,59 @@ dirserv_get_bandwidth_for_router(const routerinfo_t *ri) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return bw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** Look through the routerlist, and using the measured bandwidth cache count 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * how many measured bandwidths we know.  This is used to decide whether we 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * ever trust advertised bandwidths for purposes of assigning flags. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+dirserv_count_measured_bws(routerlist_t *rl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Initialize this first */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  routers_with_measured_bw = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(rl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(rl->routers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Iterate over the routerlist and count measured bandwidths */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Check if we know a measured bandwidth for this one */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (dirserv_query_measured_bw_cache(ri->cache_info.identity_digest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                        NULL, NULL)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      ++routers_with_measured_bw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } SMARTLIST_FOREACH_END(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** Return the bandwidth we believe for assigning flags; prefer measured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * over advertised, and if we have above a threshold quantity of measured 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * bandwidths, we don't want to ever give flags to unmeasured routers, so 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * return 0. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static uint32_t 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+dirserv_get_credible_bandwidth(const routerinfo_t *ri) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int threshold; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uint32_t bw = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  long mbw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Check if we have a measured bandwidth, and check the threshold if not */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!(dirserv_query_measured_bw_cache(ri->cache_info.identity_digest, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                       &mbw, NULL))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (routers_with_measured_bw > threshold) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* Return zero for unmeasured bandwidth if we are above threshold */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      bw = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* Return an advertised bandwidth otherwise */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      bw = router_get_advertised_bandwidth(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* We have the measured bandwidth in mbw */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    bw = (uint32_t)mbw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return bw; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Give a statement of our current performance thresholds for inclusion 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * in a vote document. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 char * 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2604,7 +2674,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                  int listbaddirs, int vote_on_hsdirs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const or_options_t *options = get_options(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  uint32_t routerbw = dirserv_get_bandwidth_for_router(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  uint32_t routerbw = dirserv_get_credible_bandwidth(ri); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   memset(rs, 0, sizeof(routerstatus_t)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2927,6 +2997,14 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (options->V3BandwidthsFile) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     dirserv_read_measured_bandwidths(options->V3BandwidthsFile, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * No bandwidths file; clear the measured bandwidth cache in case we had 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * one last time around. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (dirserv_get_measured_bw_cache_size() > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      dirserv_clear_measured_bw_cache(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* precompute this part, since we need it to decide what "stable" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2945,6 +3023,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     rep_hist_make_router_pessimal(sybil_id, now); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } DIGESTMAP_FOREACH_END; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Count how many have measured bandwidths so we know how to assign flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   * this must come before dirserv_compute_performance_thresholds() */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  dirserv_count_measured_bws(rl); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   dirserv_compute_performance_thresholds(rl, omit_as_sybil); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   routerstatuses = smartlist_new(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -2989,6 +3071,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   smartlist_free(routers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   digestmap_free(omit_as_sybil, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* This pass through applies the measured bw lines to the routerstatuses */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (options->V3BandwidthsFile) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     dirserv_read_measured_bandwidths(options->V3BandwidthsFile, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                      routerstatuses); 
			 |