10#define TOR_CONFLUX_PRIVATE
32#define USEC_PER_SEC 1000000
35 uint64_t in_usec, uint64_t our_usec);
41static uint64_t total_ooo_q_bytes = 0;
61 switch (relay_command) {
64 case RELAY_COMMAND_BEGIN:
65 case RELAY_COMMAND_DATA:
66 case RELAY_COMMAND_END:
67 case RELAY_COMMAND_CONNECTED:
72 case RELAY_COMMAND_SENDME:
73 case RELAY_COMMAND_EXTEND:
74 case RELAY_COMMAND_EXTENDED:
75 case RELAY_COMMAND_TRUNCATE:
76 case RELAY_COMMAND_TRUNCATED:
77 case RELAY_COMMAND_DROP:
82 case RELAY_COMMAND_RESOLVE:
83 case RELAY_COMMAND_RESOLVED:
87 case RELAY_COMMAND_BEGIN_DIR:
88 case RELAY_COMMAND_EXTEND2:
89 case RELAY_COMMAND_EXTENDED2:
90 case RELAY_COMMAND_ESTABLISH_INTRO:
91 case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
92 case RELAY_COMMAND_INTRODUCE1:
93 case RELAY_COMMAND_INTRODUCE2:
94 case RELAY_COMMAND_RENDEZVOUS1:
95 case RELAY_COMMAND_RENDEZVOUS2:
96 case RELAY_COMMAND_INTRO_ESTABLISHED:
97 case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
98 case RELAY_COMMAND_INTRODUCE_ACK:
99 case RELAY_COMMAND_PADDING_NEGOTIATE:
100 case RELAY_COMMAND_PADDING_NEGOTIATED:
105 case RELAY_COMMAND_XOFF:
106 case RELAY_COMMAND_XON:
112 case RELAY_COMMAND_CONFLUX_SWITCH:
113 case RELAY_COMMAND_CONFLUX_LINK:
114 case RELAY_COMMAND_CONFLUX_LINKED:
115 case RELAY_COMMAND_CONFLUX_LINKED_ACK:
119 log_warn(
LD_BUG,
"Conflux asked to multiplex unknown relay command %d",
135 if (leg->circ == circ) {
139 } CONFLUX_FOR_EACH_LEG_END(leg);
150 uint64_t max_seq_sent = 0;
153 if (leg->last_seq_sent > max_seq_sent) {
154 max_seq_sent = leg->last_seq_sent;
156 } CONFLUX_FOR_EACH_LEG_END(leg);
167 uint64_t max_seq_recv = 0;
170 if (leg->last_seq_recv > max_seq_recv) {
171 max_seq_recv = leg->last_seq_recv;
173 } CONFLUX_FOR_EACH_LEG_END(leg);
184 return smartlist_len(circ->
conflux->
ooo_q) *
sizeof(
void*)
196 return total_ooo_q_bytes;
203 (void) bytes_to_remove;
209 log_info(
LD_CIRC,
"OOM handler triggered. OOO queus allocation: %" PRIu64,
225 size_t cost = conflux_msg_alloc_cost(msg);
226 if (BUG(cost > total_ooo_q_bytes)) {
227 total_ooo_q_bytes = 0;
229 total_ooo_q_bytes -= cost;
231 conflux_relay_msg_free(msg);
244 bool cc_sendable =
true;
277 uint64_t min_rtt = UINT64_MAX;
286 if (leg->circ_rtts_usec && leg->circ_rtts_usec < min_rtt) {
288 min_rtt = leg->circ_rtts_usec;
290 } CONFLUX_FOR_EACH_LEG_END(leg);
309 uint64_t low_rtt = UINT64_MAX;
322 if (leg->circ_rtts_usec && leg->circ_rtts_usec < low_rtt) {
323 low_rtt = leg->circ_rtts_usec;
326 } CONFLUX_FOR_EACH_LEG_END(leg);
336static inline uint64_t
354static inline uint64_t
362 if (our_usec == 0 || in_usec == 0) {
364 "cwnd_sendable: Missing RTT data. in_usec: %" PRIu64
365 " our_usec: %" PRIu64, in_usec, our_usec);
366 return cwnd_adjusted;
370 return cwnd_adjusted;
378 uint64_t sendable = cwnd_adjusted*in_usec/our_usec;
379 return MIN(cc->
cwnd, sendable);
411 conflux_params_get_drain_pct()*ccontrol->
cwnd) {
434 uint64_t min_rtt = UINT64_MAX;
443 if (l->circ_rtts_usec && l->circ_rtts_usec < min_rtt) {
444 min_rtt = l->circ_rtts_usec;
447 } CONFLUX_FOR_EACH_LEG_END(l);
464 if (l->circ_rtts_usec &&
468 } CONFLUX_FOR_EACH_LEG_END(l);
491 uint8_t relay_command)
505 if (!new_circ && relay_command != RELAY_COMMAND_DATA) {
509 log_warn(
LD_BUG,
"No current leg for conflux with relay command %d",
545 static ratelim_t rlimit = RATELIM_INIT(60 * 60);
547 "Current conflux leg last_seq_sent=%"PRIu64
548 " is above previous leg at %" PRIu64
". Closing set.",
552 END_CIRC_REASON_TORPROTOCOL);
563 END_CIRC_REASON_TORPROTOCOL);
588 log_fn(LOG_PROTOCOL_WARN,
LD_BUG,
"No Conflux leg after sending a cell");
612 if (leg->circ_rtts_usec > 0) {
617 } CONFLUX_FOR_EACH_LEG_END(leg);
623 if (BUG(smartlist_len(cfx->
legs) <= 0)) {
626 log_warn(
LD_BUG,
"Matching client sets:");
628 log_warn(
LD_BUG,
"Matching server sets:");
630 log_warn(
LD_BUG,
"End conflux set dump");
634 min_leg = smartlist_get(cfx->
legs, 0);
637 log_warn(
LD_BUG,
"Conflux has no legs with non-zero RTT. "
688 log_info(
LD_CIRC,
"Conflux can't switch; no circuit to send on.");
692 switch (cfx->
params.alg) {
693 case CONFLUX_ALG_MINRTT:
695 case CONFLUX_ALG_LOWRTT:
697 case CONFLUX_ALG_CWNDRTT:
713 log_warn(
LD_BUG,
"Got RTT update for circuit not in conflux");
742 if (cell_a->
seq < cell_b->
seq) {
744 }
else if (cell_a->
seq > cell_b->
seq) {
766 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath);
767 tor_assert(CONST_TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
782#define CONFLUX_MIN_LINK_INCREMENT 31
795 uint32_t relative_seq;
798 if (!conflux_is_enabled(in_circ)) {
799 circuit_mark_for_close(in_circ, END_CIRC_REASON_TORPROTOCOL);
806 log_warn(
LD_BUG,
"Got a conflux switch command on a circuit without "
807 "conflux negotiated. Closing circuit.");
809 circuit_mark_for_close(in_circ, END_CIRC_REASON_TORPROTOCOL);
822 log_warn(
LD_BUG,
"Got a conflux switch command on a circuit without "
823 "conflux leg. Closing circuit.");
824 circuit_mark_for_close(in_circ, END_CIRC_REASON_INTERNAL);
830 log_warn(
LD_BUG,
"Got a conflux switch command on a circuit with "
831 "invalid source hop. Closing circuit.");
832 circuit_mark_for_close(in_circ, END_CIRC_REASON_TORPROTOCOL);
894 log_warn(
LD_BUG,
"Got a conflux cell on a circuit without "
895 "conflux leg. Closing circuit.");
896 circuit_mark_for_close(in_circ, END_CIRC_REASON_INTERNAL);
903 circuit_mark_for_close(in_circ, END_CIRC_REASON_TORPROTOCOL);
919 "Got a conflux cell with a sequence number "
920 "less than the last delivered. Closing circuit.");
921 circuit_mark_for_close(in_circ, END_CIRC_REASON_INTERNAL);
928 static ratelim_t rlimit = RATELIM_INIT(60 * 60);
930 "Conflux OOO queue is at maximum. Currently at "
931 "%"TOR_PRIuSZ
" bytes, maximum allowed is %u bytes. "
934 circuit_mark_for_close(in_circ, END_CIRC_REASON_RESOURCELIMIT);
951 total_ooo_q_bytes += cost;
977 static ratelim_t rlim = RATELIM_INIT(60 * 60);
980 "Circuit was closed at %s:%u when dequeuing from OOO",
986 static ratelim_t rlim = RATELIM_INIT(60 * 60);
988 "Bug: Non marked for close circuit with NULL conflux");
991 if (cfx->
ooo_q == NULL) {
992 static ratelim_t rlim = RATELIM_INIT(60 * 60);
994 "Bug: Non marked for close circuit with NULL OOO queue");
998 if (smartlist_len(cfx->
ooo_q) == 0)
1001 top = smartlist_get(cfx->
ooo_q, 0);
1010 total_ooo_q_bytes -= cost;
1025 relay_msg_free(msg->
msg);
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
Header file for circuituse.c.
Functions and types for monotonic times.
Header file for config.c.
void conflux_note_cell_sent(conflux_t *cfx, circuit_t *circ, uint8_t relay_command)
static uint64_t cwnd_sendable(const circuit_t *on_circ, uint64_t in_usec, uint64_t our_usec)
static bool conflux_pick_first_leg(conflux_t *cfx)
void conflux_update_rtt(conflux_t *cfx, circuit_t *circ, uint64_t rtt_usec)
bool conflux_should_multiplex(int relay_command)
circuit_t * conflux_decide_next_circ(conflux_t *cfx)
static int conflux_queue_cmp(const void *a, const void *b)
static const circuit_t * conflux_decide_circ_lowrtt(const conflux_t *cfx)
static uint64_t cwnd_available(const circuit_t *on_circ)
uint64_t conflux_get_circ_bytes_allocation(const circuit_t *circ)
const congestion_control_t * circuit_ccontrol(const circuit_t *circ)
conflux_msg_t * conflux_dequeue_relay_msg(circuit_t *circ)
size_t conflux_msg_alloc_cost(conflux_msg_t *msg)
uint64_t conflux_get_max_seq_recv(const conflux_t *cfx)
uint64_t conflux_get_max_seq_sent(const conflux_t *cfx)
void conflux_relay_msg_free_(conflux_msg_t *msg)
void conflux_clear_ooo_q(conflux_t *cfx)
static bool conflux_can_switch(const conflux_t *cfx)
circuit_t * conflux_decide_circ_for_send(conflux_t *cfx, circuit_t *orig_circ, uint8_t relay_command)
static const circuit_t * conflux_decide_circ_cwndrtt(const conflux_t *cfx)
conflux_leg_t * conflux_get_leg(conflux_t *cfx, const circuit_t *circ)
bool conflux_process_relay_msg(conflux_t *cfx, circuit_t *in_circ, crypt_path_t *layer_hint, const relay_msg_t *msg)
static const circuit_t * conflux_decide_circ_minrtt(const conflux_t *cfx)
int conflux_process_switch_command(circuit_t *in_circ, crypt_path_t *layer_hint, const relay_msg_t *msg)
size_t conflux_handle_oom(size_t bytes_to_remove)
static bool circuit_ready_to_send(const circuit_t *circ)
uint64_t conflux_get_total_bytes_allocation(void)
Public APIs for conflux multipath support.
#define CONFLUX_FOR_EACH_LEG_BEGIN(cfx, var)
#define CONFLUX_NUM_LEGS(cfx)
uint32_t conflux_cell_parse_switch(const relay_msg_t *msg)
bool conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq)
Header file for conflux_cell.c.
Header file for conflux_params.c.
void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
void conflux_mark_all_for_close(const uint8_t *nonce, bool is_client, int reason)
Header file for conflux_pool.c.
Structure definitions for conflux multipath.
void conflux_validate_stream_lists(const conflux_t *cfx)
void conflux_validate_legs(const conflux_t *cfx)
bool conflux_validate_source_hop(circuit_t *in_circ, crypt_path_t *layer_hint)
Header file for conflux_util.c.
Public APIs for congestion control.
Structure definitions for congestion control.
#define log_fn(severity, domain, args,...)
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Master header file for Tor-specific functionality.
Origin circuit structure.
relay_msg_t * relay_msg_copy(const relay_msg_t *msg)
Header file for relay_msg.c.
Header file for sendme.c.
void * smartlist_pqueue_pop(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset)
void smartlist_pqueue_add(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset, void *item)
void smartlist_clear(smartlist_t *sl)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
unsigned int circuit_blocked_on_n_chan
unsigned int circuit_blocked_on_p_chan
uint16_t marked_for_close
struct conflux_t * conflux
const char * marked_for_close_file
struct congestion_control_t * ccontrol
uint64_t linked_sent_usec
struct conflux_leg_t * curr_leg
struct conflux_params_t params
struct conflux_leg_t * prev_leg
uint8_t nonce[DIGEST256_LEN]
uint64_t cells_until_switch
uint64_t last_seq_delivered
struct crypt_path_t * prev
struct congestion_control_t * ccontrol