commit 76bdadce121b0c33f46bb3d4e5eb0e8dc3277614 Author: Mike Perry mikeperry-git@torproject.org Date: Thu Nov 4 00:46:11 2021 +0000
Hook up client usage of congestion control negotiation --- src/core/or/circuitbuild.c | 52 ++++++++++++++++++++++++++++++++------- src/core/or/circuituse.c | 6 +++-- src/core/or/command.c | 4 +-- src/core/or/extend_info_st.h | 7 +++--- src/core/or/extendinfo.c | 20 +++++++++------ src/core/or/extendinfo.h | 6 +++-- src/feature/control/control_cmd.c | 5 +++- 7 files changed, 72 insertions(+), 28 deletions(-)
diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 53582d2829..61d67c350d 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -72,6 +72,7 @@ #include "feature/stats/predict_ports.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/trace/events.h" +#include "core/or/congestion_control_common.h"
#include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" @@ -80,6 +81,7 @@ #include "feature/nodelist/node_st.h" #include "core/or/or_circuit_st.h" #include "core/or/origin_circuit_st.h" +#include "trunnel/circ_params.h"
static int circuit_send_first_onion_skin(origin_circuit_t *circ); static int circuit_build_no_more_hops(origin_circuit_t *circ); @@ -841,7 +843,10 @@ circuit_pick_create_handshake(uint8_t *cell_type_out, * using the TAP handshake, and CREATE2 otherwise. */ if (extend_info_supports_ntor(ei)) { *cell_type_out = CELL_CREATE2; - if (ei->supports_ntor3_and_param_negotiation) + /* Only use ntor v3 with exits that support congestion control, + * and only when it is enabled. */ + if (ei->exit_supports_congestion_control && + congestion_control_enabled()) *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3; else *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; @@ -1263,12 +1268,14 @@ circuit_finish_handshake(origin_circuit_t *circ,
onion_handshake_state_release(&hop->handshake_state);
- // XXXX TODO-324: use `params` to initialize the congestion control. - if (cpath_init_circuit_crypto(hop, keys, sizeof(keys), 0, 0)<0) { return -END_CIRC_REASON_TORPROTOCOL; }
+ if (params.cc_enabled) { + hop->ccontrol = congestion_control_new(¶ms); + } + hop->state = CPATH_STATE_OPEN; log_info(LD_CIRC,"Finished building circuit hop:"); circuit_log_path(LOG_INFO,LD_CIRC,circ); @@ -2068,7 +2075,10 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei, log_warn(LD_CIRC,"Failed to choose an exit server"); return -1; } - exit_ei = extend_info_from_node(node, state->onehop_tunnel); + exit_ei = extend_info_from_node(node, state->onehop_tunnel, + /* for_exit_use */ + !state->is_internal && TO_CIRCUIT(circ)->purpose == + CIRCUIT_PURPOSE_C_GENERAL); if (BUG(exit_ei == NULL)) return -1; } @@ -2464,7 +2474,7 @@ onion_extend_cpath(origin_circuit_t *circ) primary address, for potentially connecting to an IPv6 OR port. Servers always want the primary (IPv4) address. */ int client = (server_mode(get_options()) == 0); - info = extend_info_from_node(r, client); + info = extend_info_from_node(r, client, false); /* Clients can fail to find an allowed address */ tor_assert_nonfatal(info || client); } @@ -2472,7 +2482,7 @@ onion_extend_cpath(origin_circuit_t *circ) const node_t *r = choose_good_middle_server(purpose, state, circ->cpath, cur_len); if (r) { - info = extend_info_from_node(r, 0); + info = extend_info_from_node(r, 0, false); } }
@@ -2597,9 +2607,33 @@ client_circ_negotiation_message(const extend_info_t *ei, size_t *msg_len_out) { tor_assert(ei && msg_out && msg_len_out); - if (! ei->supports_ntor3_and_param_negotiation) + circ_params_request_t params = {0}; + ssize_t msg_len = 0; + + if (! ei->exit_supports_congestion_control) return -1;
- /* TODO-324: fill in the client message that gets sent. */ - tor_assert_unreached(); + circ_params_request_set_version(¶ms, 0); + + circ_params_request_set_cc_supported(¶ms, + congestion_control_enabled()); + + msg_len = circ_params_request_encoded_len(¶ms); + + if (msg_len < 0) { + return -1; + } + + *msg_out = tor_malloc_zero(msg_len); + + msg_len = circ_params_request_encode(*msg_out, msg_len, ¶ms); + + if (msg_len < 0) { + tor_free(*msg_out); + return -1; + } + + *msg_len_out = (size_t)msg_len; + + return 0; } diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index 104e898d6c..a259957d37 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -2427,7 +2427,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, /* We might want to connect to an IPv6 bridge for loading descriptors so we use the preferred address rather than the primary. */ - extend_info = extend_info_from_node(r, conn->want_onehop ? 1 : 0); + extend_info = extend_info_from_node(r, conn->want_onehop ? 1 : 0, + desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL); if (!extend_info) { log_warn(LD_CIRC,"Could not make a one-hop connection to %s. " "Discarding this circuit.", conn->chosen_exit_name); @@ -2463,7 +2464,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, NULL, /* Ed25519 ID */ NULL, NULL, /* onion keys */ &addr, conn->socks_request->port, - NULL); + NULL, + false); } else { /* ! (want_onehop && conn->chosen_exit_name[0] == '$') */ /* We will need an onion key for the router, and we * don't have one. Refuse or relax requirements. */ diff --git a/src/core/or/command.c b/src/core/or/command.c index 12e4c26768..ffdd1f19d9 100644 --- a/src/core/or/command.c +++ b/src/core/or/command.c @@ -367,6 +367,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan) create_cell->onionskin, create_cell->handshake_len, NULL, + NULL, created_cell.reply, sizeof(created_cell.reply), keys, CPATH_KEY_MATERIAL_LEN, @@ -381,9 +382,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan) created_cell.cell_type = CELL_CREATED_FAST; created_cell.handshake_len = len;
- // TODO-324: We should in theory look at params here, though it will - // always tell us to use the old-fashioned congestion control. - if (onionskin_answer(circ, &created_cell, (const char *)keys, sizeof(keys), rend_circ_nonce)<0) { diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h index 1666b168ad..2ab0beb7e6 100644 --- a/src/core/or/extend_info_st.h +++ b/src/core/or/extend_info_st.h @@ -38,9 +38,10 @@ struct extend_info_t { crypto_pk_t *onion_key; /** Ntor onion key for this hop. */ curve25519_public_key_t curve25519_onion_key; - /** True if this hop supports NtorV3 _and_ negotiation of at least one - * relevant circuit parameter (currently only congestion control). */ - bool supports_ntor3_and_param_negotiation; + /** True if this hop is to be used as an _exit_, + * and it also supports supports NtorV3 _and_ negotiation + * of congestion control parameters */ + bool exit_supports_congestion_control; };
#endif /* !defined(EXTEND_INFO_ST_H) */ diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c index ca2288e0a4..ca623f09ce 100644 --- a/src/core/or/extendinfo.c +++ b/src/core/or/extendinfo.c @@ -36,7 +36,8 @@ extend_info_new(const char *nickname, crypto_pk_t *onion_key, const curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port, - const protover_summary_flags_t *pv) + const protover_summary_flags_t *pv, + bool for_exit_use) { extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t)); if (rsa_id_digest) @@ -58,9 +59,9 @@ extend_info_new(const char *nickname, extend_info_add_orport(info, addr, port); }
- if (pv) { - info->supports_ntor3_and_param_negotiation = - pv->supports_ntor3_and_param_negotiation; + if (pv && for_exit_use) { + info->exit_supports_congestion_control = + pv->supports_congestion_control; }
return info; @@ -96,7 +97,8 @@ extend_info_add_orport(extend_info_t *ei, * and IP version config. **/ extend_info_t * -extend_info_from_node(const node_t *node, int for_direct_connect) +extend_info_from_node(const node_t *node, int for_direct_connect, + bool for_exit) { crypto_pk_t *rsa_pubkey = NULL; extend_info_t *info = NULL; @@ -157,7 +159,8 @@ extend_info_from_node(const node_t *node, int for_direct_connect) curve_pubkey, &ap.addr, ap.port, - &node->ri->pv); + &node->ri->pv, + for_exit); } else if (valid_addr && node->rs && node->md) { info = extend_info_new(node->rs->nickname, node->identity, @@ -166,7 +169,8 @@ extend_info_from_node(const node_t *node, int for_direct_connect) curve_pubkey, &ap.addr, ap.port, - &node->rs->pv); + &node->rs->pv, + for_exit); }
crypto_pk_free(rsa_pubkey); @@ -225,7 +229,7 @@ extend_info_supports_ntor_v3(const extend_info_t *ei) { tor_assert(ei); return extend_info_supports_ntor(ei) && - ei->supports_ntor3_and_param_negotiation; + ei->exit_supports_congestion_control; }
/* Does ei have an onion key which it would prefer to use? diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h index 8781cc7047..6d1f20597b 100644 --- a/src/core/or/extendinfo.h +++ b/src/core/or/extendinfo.h @@ -18,8 +18,10 @@ extend_info_t *extend_info_new(const char *nickname, crypto_pk_t *onion_key, const struct curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port, - const struct protover_summary_flags_t *pv); -extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect); + const struct protover_summary_flags_t *pv, + bool for_exit_use); +extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect, + bool for_exit); extend_info_t *extend_info_dup(extend_info_t *info); void extend_info_free_(extend_info_t *info); #define extend_info_free(info) \ diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index b19935e456..dd0cde4f7d 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -823,7 +823,10 @@ handle_control_extendcircuit(control_connection_t *conn, first_node = zero_circ; SMARTLIST_FOREACH(nodes, const node_t *, node, { - extend_info_t *info = extend_info_from_node(node, first_node); + /* We treat every hop as an exit to try to negotiate congestion + * control, because we have no idea which hop the controller wil + * try to use for streams and when */ + extend_info_t *info = extend_info_from_node(node, first_node, true); if (!info) { tor_assert_nonfatal(first_node); log_warn(LD_CONTROL,