Ticket #17903: 0001-Ticket-17903-taken-up-as-the-coding-task-for-the-int.patch

File 0001-Ticket-17903-taken-up-as-the-coding-task-for-the-int.patch, 16.2 KB (added by attila, 3 years ago)

patch from git format-patch

  • src/or/routerlist.c

    From a6446f4a20a2d053d403942a99bbecedec3bd3b9 Mon Sep 17 00:00:00 2001
    From: attila <attila@stalphonsos.com>
    Date: Mon, 6 Feb 2017 13:55:09 -0600
    Subject: [PATCH] Ticket #17903, taken up as the coding task for the interview
     process for the Core Developer position.
    
    Factor out common code between router_pick_directory_server_impl()
    and the desired new behavior of router_pick_trusteddirserver_impl()
    into five ROUTER_PICK_xxx() macros which encapsulate the order in
    which we try the various categories of directory servers examined by
    each function.
    ---
     src/or/routerlist.c | 228 ++++++++++++++++++++++++++++++++++------------------
     1 file changed, 148 insertions(+), 80 deletions(-)
    
    diff --git a/src/or/routerlist.c b/src/or/routerlist.c
    index 473527106..33d4210c3 100644
    a b router_skip_dir_reachability(const or_options_t *options, int try_ip_pref) 
    19741974  return server_mode(options) || (!try_ip_pref && !firewall_is_fascist_dir());
    19751975}
    19761976
     1977/* #17903: the ROUTER_PICK_xxx() macros factor out code common to
     1978 * router_pick_{directory_server,trusted_dirserver}_impl() in so far
     1979 * as the ordering of routers examined is concerned.  In both cases we
     1980 * order our choices so that overloaded routers are the middle
     1981 * (second) choice: the first category of routers to try and the last
     1982 * (third) category of routers to try varies between the two
     1983 * functions as per the ticket.
     1984 *
     1985 * These macros encode the pattern used in both places, parameterized
     1986 * so that the ordering of the classes of directory server we are
     1987 * choosing from is correct.  They parameterize this by accepting two
     1988 * arguments, called first and last, which name the two categories of
     1989 * servers that come first and last, respectively: one of trusted,
     1990 * fallback or mirror depending on the situation.  Overloaded servers
     1991 * are always accounted explicitly for and are always the middle
     1992 * choice.
     1993*/
     1994
     1995/* Declare all of the smartlists necessary to bin up routers by category */
     1996#define ROUTER_PICK_DECLARE_LISTS(first,last)                                 \
     1997  smartlist_t *first##_direct, *first##_tunnel;                               \
     1998  smartlist_t *last##_direct, *last##_tunnel;                                 \
     1999  smartlist_t *overloaded_direct, *overloaded_tunnel;                         \
     2000  smartlist_t *pick_from;
     2001
     2002/* (Re)initialize smartlists declared by DECLARE_LISTS */
     2003#define ROUTER_PICK_INIT_LISTS(first,last)                                    \
     2004  STMT_BEGIN                                                                  \
     2005    first##_direct = smartlist_new();                                         \
     2006    first##_tunnel = smartlist_new();                                         \
     2007    last##_direct = smartlist_new();                                          \
     2008    last##_tunnel = smartlist_new();                                          \
     2009    overloaded_direct = smartlist_new();                                      \
     2010    overloaded_tunnel = smartlist_new();                                      \
     2011  STMT_END
     2012
     2013/* Add the router under examination to the right list.  Our first
     2014 * parameter names the condition we are checking for; we depend on
     2015 * there existing a variable named is_<check> in scope
     2016 * e.g. is_trusted.  Our second parameter is the name of the default
     2017 * list onto which servers that neither patch that condition
     2018 * (e.g. !is_trusted) and are also not overloaded are placed.  The
     2019 * last two arguments account for variations between the two
     2020 * pick_*_impl() functions: in one var is a node_t and in the other
     2021 * var is a dir_server_t, and the names used are different. */
     2022#define ROUTER_PICK_ADD_TO_RIGHT_LIST(first,last,what,var)                    \
     2023  STMT_BEGIN                                                                  \
     2024    if (!fascistfirewall || skip_or_fw ||                                     \
     2025        fascist_firewall_allows_##what(var, FIREWALL_OR_CONNECTION,           \
     2026                                     try_ip_pref))                            \
     2027      smartlist_add(is_##first ? first##_tunnel :                             \
     2028                    is_overloaded ? overloaded_tunnel : last##_tunnel,        \
     2029                    (void*)var);                                              \
     2030    else if (!must_have_or && (skip_dir_fw ||                                 \
     2031             fascist_firewall_allows_##what(var, FIREWALL_DIR_CONNECTION,     \
     2032                                          try_ip_pref)))                      \
     2033      smartlist_add(is_##first ? first##_direct :                             \
     2034                    is_overloaded ? overloaded_direct : last##_direct,        \
     2035                    (void*)var);                                              \
     2036  STMT_END
     2037
     2038/* Set pick_from to the smartlist we should choose a router from; also
     2039 * set weighted (second arg to the chooser function) to the right
     2040 * thing based on which kind of router we decided to choose from. Our
     2041 * first two parameters name the first and third conditions we check
     2042 * for in each group (tunnel, direct) of servers examined.  The
     2043 * normal_weight and other_weight parameters account for the
     2044 * difference between the two pick_*_impl() functions: in one case we
     2045 * use a simple smartlist_choose() call for authorities in both direct
     2046 * and tunneld cases, in the other we use dirserver_choose_by_weight
     2047 * with the same weight in every case. */
     2048/* The following two FFFF comments were in router_pick_directory_server_impl()
     2049 * in last##_tunnel (third) case, below. */
     2050/* FFFF We don't distinguish between trusteds and overloaded trusteds
     2051 * yet. Maybe one day we should. */
     2052/* FFFF We also don't load balance over authorities yet. I think this
     2053 * is a feature, but it could easily be a bug. -RD */
     2054#define ROUTER_PICK_CHOOSE(first,last,normal_weight,other_weight,chooser)     \
     2055  STMT_BEGIN                                                                  \
     2056    if (smartlist_len(first##_tunnel)) {                                      \
     2057      pick_from = first##_tunnel;                                             \
     2058      weighted = normal_weight;                                               \
     2059    } else if (smartlist_len(overloaded_tunnel)) {                            \
     2060      pick_from = overloaded_tunnel;                                          \
     2061      weighted = normal_weight;                                               \
     2062    } else if (smartlist_len(last##_tunnel)) {                                \
     2063      pick_from = last##_tunnel;                                              \
     2064      weighted = other_weight;                                                \
     2065    } else if (smartlist_len(first##_direct)) {                               \
     2066      pick_from = first##_direct;                                             \
     2067      weighted = normal_weight;                                               \
     2068    } else if (smartlist_len(overloaded_direct)) {                            \
     2069      pick_from = overloaded_direct;                                          \
     2070      weighted = normal_weight;                                               \
     2071    } else {                                                                  \
     2072      pick_from = last##_direct;                                              \
     2073      weighted = other_weight;                                                \
     2074    }                                                                         \
     2075    result = chooser(pick_from, weighted);                                    \
     2076  STMT_END
     2077
     2078/* Release smartlist memory after picking a router */
     2079#define ROUTER_PICK_CLEANUP_LISTS(first,last)                                 \
     2080  STMT_BEGIN                                                                  \
     2081    smartlist_free(first##_direct);                                           \
     2082    smartlist_free(first##_tunnel);                                           \
     2083    smartlist_free(last##_direct);                                            \
     2084    smartlist_free(last##_tunnel);                                            \
     2085    smartlist_free(overloaded_direct);                                        \
     2086    smartlist_free(overloaded_tunnel);                                        \
     2087  STMT_END
     2088
     2089/* Helper function used in an invocation of ROUTER_PICK_CHOOSE(), below */
     2090static const node_t *
     2091choose_router_from_list_maybe_by_weight(smartlist_t *pick_from, int weighted)
     2092{
     2093  return
     2094      weighted ? node_sl_choose_by_bandwidth(pick_from, WEIGHT_FOR_DIR) :
     2095                 smartlist_choose(pick_from);
     2096}
     2097
    19772098/** Pick a random running valid directory server/mirror from our
    19782099 * routerlist.  Arguments are as for router_pick_directory_server(), except:
    19792100 *
    router_pick_directory_server_impl(dirinfo_type_t type, int flags, 
    19872108{
    19882109  const or_options_t *options = get_options();
    19892110  const node_t *result;
    1990   smartlist_t *direct, *tunnel;
    1991   smartlist_t *trusted_direct, *trusted_tunnel;
    1992   smartlist_t *overloaded_direct, *overloaded_tunnel;
     2111  ROUTER_PICK_DECLARE_LISTS(trusted,mirror);
     2112  int weighted;                         /* needed by ROUTER_PICK_xxx macros */
    19932113  time_t now = time(NULL);
    19942114  const networkstatus_t *consensus = networkstatus_get_latest_consensus();
    19952115  const int requireother = ! (flags & PDS_ALLOW_SELF);
    router_pick_directory_server_impl(dirinfo_type_t type, int flags, 
    20042124
    20052125 retry_search:
    20062126
    2007   direct = smartlist_new();
    2008   tunnel = smartlist_new();
    2009   trusted_direct = smartlist_new();
    2010   trusted_tunnel = smartlist_new();
    2011   overloaded_direct = smartlist_new();
    2012   overloaded_tunnel = smartlist_new();
     2127  ROUTER_PICK_INIT_LISTS(trusted,mirror);
    20132128
    20142129  const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
    20152130  const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
    router_pick_directory_server_impl(dirinfo_type_t type, int flags, 
    20572172     * address for each router (if any). (To ensure correct load-balancing
    20582173     * we try routers that only have one address both times.)
    20592174     */
    2060     if (!fascistfirewall || skip_or_fw ||
    2061         fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION,
    2062                                      try_ip_pref))
    2063       smartlist_add(is_trusted ? trusted_tunnel :
    2064                     is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
    2065     else if (!must_have_or && (skip_dir_fw ||
    2066              fascist_firewall_allows_node(node, FIREWALL_DIR_CONNECTION,
    2067                                           try_ip_pref)))
    2068       smartlist_add(is_trusted ? trusted_direct :
    2069                     is_overloaded ? overloaded_direct : direct, (void*)node);
     2175    ROUTER_PICK_ADD_TO_RIGHT_LIST(trusted,mirror,node,node);
    20702176  } SMARTLIST_FOREACH_END(node);
    20712177
    2072   if (smartlist_len(tunnel)) {
    2073     result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
    2074   } else if (smartlist_len(overloaded_tunnel)) {
    2075     result = node_sl_choose_by_bandwidth(overloaded_tunnel,
    2076                                                  WEIGHT_FOR_DIR);
    2077   } else if (smartlist_len(trusted_tunnel)) {
    2078     /* FFFF We don't distinguish between trusteds and overloaded trusteds
    2079      * yet. Maybe one day we should. */
    2080     /* FFFF We also don't load balance over authorities yet. I think this
    2081      * is a feature, but it could easily be a bug. -RD */
    2082     result = smartlist_choose(trusted_tunnel);
    2083   } else if (smartlist_len(direct)) {
    2084     result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
    2085   } else if (smartlist_len(overloaded_direct)) {
    2086     result = node_sl_choose_by_bandwidth(overloaded_direct,
    2087                                          WEIGHT_FOR_DIR);
    2088   } else {
    2089     result = smartlist_choose(trusted_direct);
    2090   }
    2091   smartlist_free(direct);
    2092   smartlist_free(tunnel);
    2093   smartlist_free(trusted_direct);
    2094   smartlist_free(trusted_tunnel);
    2095   smartlist_free(overloaded_direct);
    2096   smartlist_free(overloaded_tunnel);
     2178  ROUTER_PICK_CHOOSE(mirror,trusted,1,0,
     2179                     choose_router_from_list_maybe_by_weight);
     2180
     2181  ROUTER_PICK_CLEANUP_LISTS(trusted,mirror);
    20972182
    20982183  RETRY_ALTERNATE_IP_VERSION(retry_search);
    20992184
    dirserver_choose_by_weight(const smartlist_t *servers, double authority_weight) 
    21342219  return (i < 0) ? NULL : smartlist_get(servers, i);
    21352220}
    21362221
     2222/* Helper function used in ROUTER_PICK_CHOOSE(), below */
     2223static const routerstatus_t *
     2224choose_dirserver_status_from_list(smartlist_t *from, double weight)
     2225{
     2226  const dir_server_t *selection = dirserver_choose_by_weight(from, weight);
     2227
     2228  return selection ? &selection->fake_status : NULL;
     2229}
     2230
    21372231/** Choose randomly from among the dir_server_ts in sourcelist that
    21382232 * are up. Flags are as for router_pick_directory_server_impl().
    21392233 */
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    21432237                                  int *n_busy_out)
    21442238{
    21452239  const or_options_t *options = get_options();
    2146   smartlist_t *direct, *tunnel;
    2147   smartlist_t *overloaded_direct, *overloaded_tunnel;
     2240  ROUTER_PICK_DECLARE_LISTS(fallback,trusted);
     2241  double weighted;                      /* needed by ROUTER_PICK_xxx macros */
    21482242  const routerinfo_t *me = router_get_my_routerinfo();
    21492243  const routerstatus_t *result = NULL;
    21502244  time_t now = time(NULL);
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    21542248  const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH);
    21552249  const double auth_weight = (sourcelist == fallback_dir_servers) ?
    21562250    options->DirAuthorityFallbackRate : 1.0;
    2157   smartlist_t *pick_from;
    21582251  int n_busy = 0;
    21592252  int try_excluding = 1, n_excluded = 0;
    21602253  int try_ip_pref = 1;
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    21642257
    21652258 retry_search:
    21662259
    2167   direct = smartlist_new();
    2168   tunnel = smartlist_new();
    2169   overloaded_direct = smartlist_new();
    2170   overloaded_tunnel = smartlist_new();
     2260  ROUTER_PICK_INIT_LISTS(fallback,trusted);
    21712261
    21722262  const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref);
    21732263  const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref);
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    21772267    {
    21782268      int is_overloaded =
    21792269          d->fake_status.last_dir_503_at + DIR_503_TIMEOUT > now;
     2270      int is_fallback;
    21802271      if (!d->is_running) continue;
    21812272      if ((type & d->type) == 0)
    21822273        continue;
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    22012292        continue;
    22022293      }
    22032294
     2295      is_fallback = router_digest_is_fallback_dir(d->digest);
     2296
    22042297      /* Clients use IPv6 addresses if the server has one and the client
    22052298       * prefers IPv6.
    22062299       * Add the router if its preferred address and port are reachable.
    router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, 
    22082301       * address for each router (if any). (To ensure correct load-balancing
    22092302       * we try routers that only have one address both times.)
    22102303       */
    2211       if (!fascistfirewall || skip_or_fw ||
    2212           fascist_firewall_allows_dir_server(d, FIREWALL_OR_CONNECTION,
    2213                                              try_ip_pref))
    2214         smartlist_add(is_overloaded ? overloaded_tunnel : tunnel, (void*)d);
    2215       else if (!must_have_or && (skip_dir_fw ||
    2216                fascist_firewall_allows_dir_server(d, FIREWALL_DIR_CONNECTION,
    2217                                                   try_ip_pref)))
    2218         smartlist_add(is_overloaded ? overloaded_direct : direct, (void*)d);
     2304      ROUTER_PICK_ADD_TO_RIGHT_LIST(fallback,trusted,dir_server,d);
    22192305    }
    22202306  SMARTLIST_FOREACH_END(d);
    22212307
    2222   if (smartlist_len(tunnel)) {
    2223     pick_from = tunnel;
    2224   } else if (smartlist_len(overloaded_tunnel)) {
    2225     pick_from = overloaded_tunnel;
    2226   } else if (smartlist_len(direct)) {
    2227     pick_from = direct;
    2228   } else {
    2229     pick_from = overloaded_direct;
    2230   }
    2231 
    2232   {
    2233     const dir_server_t *selection =
    2234       dirserver_choose_by_weight(pick_from, auth_weight);
    2235 
    2236     if (selection)
    2237       result = &selection->fake_status;
    2238   }
     2308  ROUTER_PICK_CHOOSE(fallback,trusted,auth_weight,auth_weight,
     2309                     choose_dirserver_status_from_list);
    22392310
    2240   smartlist_free(direct);
    2241   smartlist_free(tunnel);
    2242   smartlist_free(overloaded_direct);
    2243   smartlist_free(overloaded_tunnel);
     2311  ROUTER_PICK_CLEANUP_LISTS(fallback,trusted);
    22442312
    22452313  RETRY_ALTERNATE_IP_VERSION(retry_search);
    22462314