Tor 0.4.9.13
Loading...
Searching...
No Matches
congestion_control_common.c
Go to the documentation of this file.
1/* Copyright (c) 2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file congestion_control_common.c
6 * \brief Common code used by all congestion control algorithms.
7 */
8
9#define TOR_CONGESTION_CONTROL_COMMON_PRIVATE
10#define TOR_CONGESTION_CONTROL_PRIVATE
11
12#include "core/or/or.h"
13
15#include "core/or/circuitlist.h"
16#include "core/or/crypt_path.h"
17#include "core/or/or_circuit_st.h"
19#include "core/or/channel.h"
21#include "core/or/sendme.h"
26#include "core/or/conflux.h"
28#include "core/or/trace_probes_cc.h"
31#include "app/config/config.h"
32
33#include "trunnel/congestion_control.h"
34#include "trunnel/extension.h"
35
36/* Consensus parameter defaults.
37 *
38 * More details for each of the parameters can be found in proposal 324,
39 * section 6.5 including tuning notes. */
40#define SENDME_INC_DFLT (TLS_RECORD_MAX_CELLS)
41#define CIRCWINDOW_INIT (4*SENDME_INC_DFLT)
42
43#define CC_ALG_DFLT (CC_ALG_VEGAS)
44#define CC_ALG_DFLT_ALWAYS (CC_ALG_VEGAS)
45
46#define CWND_INC_DFLT (1)
47#define CWND_INC_PCT_SS_DFLT (100)
48#define CWND_INC_RATE_DFLT (SENDME_INC_DFLT)
49
50#define CWND_MIN_DFLT (CIRCWINDOW_INIT)
51#define CWND_MAX_DFLT (INT32_MAX)
52
53#define BWE_SENDME_MIN_DFLT (5)
54
55#define N_EWMA_CWND_PCT_DFLT (50)
56#define N_EWMA_MAX_DFLT (10)
57#define N_EWMA_SS_DFLT (2)
58
59#define RTT_RESET_PCT_DFLT (100)
60
61/* BDP algorithms for each congestion control algorithms use the piecewise
62 * estimattor. See section 3.1.4 of proposal 324. */
63#define WESTWOOD_BDP_ALG BDP_ALG_PIECEWISE
64#define VEGAS_BDP_MIX_ALG BDP_ALG_PIECEWISE
65#define NOLA_BDP_ALG BDP_ALG_PIECEWISE
66
67/* Indicate OR connection buffer limitations used to stop or start accepting
68 * cells in its outbuf.
69 *
70 * These watermarks are historical to tor in a sense that they've been used
71 * almost from the genesis point. And were likely defined to fit the bounds of
72 * TLS records of 16KB which would be around 32 cells.
73 *
74 * These are defaults of the consensus parameter "orconn_high" and "orconn_low"
75 * values. */
76#define OR_CONN_HIGHWATER_DFLT (32*1024)
77#define OR_CONN_LOWWATER_DFLT (16*1024)
78
79/* Low and high values of circuit cell queue sizes. They are used to tell when
80 * to start or stop reading on the streams attached on the circuit.
81 *
82 * These are defaults of the consensus parameters "cellq_high" and "cellq_low".
83 */
84#define CELL_QUEUE_LOW_DFLT (10)
85#define CELL_QUEUE_HIGH_DFLT (256)
86
88 const circuit_t *,
89 uint64_t);
90/* Number of times the RTT value was reset. For MetricsPort. */
91static uint64_t num_rtt_reset;
92
93/* Number of times the clock was stalled. For MetricsPort. */
94static uint64_t num_clock_stalls;
95
96/* Consensus parameters cached. The non static ones are extern. */
97static uint32_t cwnd_max = CWND_MAX_DFLT;
98int32_t cell_queue_high = CELL_QUEUE_HIGH_DFLT;
99int32_t cell_queue_low = CELL_QUEUE_LOW_DFLT;
100uint32_t or_conn_highwater = OR_CONN_HIGHWATER_DFLT;
101uint32_t or_conn_lowwater = OR_CONN_LOWWATER_DFLT;
102uint8_t cc_sendme_inc = SENDME_INC_DFLT;
103STATIC cc_alg_t cc_alg = CC_ALG_DFLT;
104
105/**
106 * Number of cwnd worth of sendme acks to smooth RTT and BDP with,
107 * using N_EWMA */
108static uint8_t n_ewma_cwnd_pct = N_EWMA_CWND_PCT_DFLT;
109
110/**
111 * Maximum number N for the N-count EWMA averaging of RTT and BDP.
112 */
113static uint8_t n_ewma_max = N_EWMA_MAX_DFLT;
114
115/**
116 * Maximum number N for the N-count EWMA averaging of RTT in Slow Start.
117 */
118static uint8_t n_ewma_ss = N_EWMA_SS_DFLT;
119
120/**
121 * Minimum number of sendmes before we begin BDP estimates
122 */
123static uint8_t bwe_sendme_min = BWE_SENDME_MIN_DFLT;
124
125/**
126 * Percentage of the current RTT to use when resetting the minimum RTT
127 * for a circuit. (RTT is reset when the cwnd hits cwnd_min).
128 */
129static uint8_t rtt_reset_pct = RTT_RESET_PCT_DFLT;
130
131/** Metric to count the number of congestion control circuits **/
133
134/** Return the number of RTT reset that have been done. */
135uint64_t
137{
138 return num_rtt_reset;
139}
140
141/** Return the number of clock stalls that have been done. */
142uint64_t
144{
145 return num_clock_stalls;
146}
147
148/**
149 * Update global congestion control related consensus parameter values,
150 * every consensus update.
151 */
152void
154{
155#define CELL_QUEUE_HIGH_MIN (1)
156#define CELL_QUEUE_HIGH_MAX (1000)
157 cell_queue_high = networkstatus_get_param(ns, "cellq_high",
158 CELL_QUEUE_HIGH_DFLT,
159 CELL_QUEUE_HIGH_MIN,
160 CELL_QUEUE_HIGH_MAX);
161
162#define CELL_QUEUE_LOW_MIN (1)
163#define CELL_QUEUE_LOW_MAX (1000)
164 cell_queue_low = networkstatus_get_param(ns, "cellq_low",
165 CELL_QUEUE_LOW_DFLT,
166 CELL_QUEUE_LOW_MIN,
167 CELL_QUEUE_LOW_MAX);
168
169#define OR_CONN_HIGHWATER_MIN (CELL_PAYLOAD_SIZE)
170#define OR_CONN_HIGHWATER_MAX (INT32_MAX)
171 or_conn_highwater =
172 networkstatus_get_param(ns, "orconn_high",
173 OR_CONN_HIGHWATER_DFLT,
174 OR_CONN_HIGHWATER_MIN,
175 OR_CONN_HIGHWATER_MAX);
176
177#define OR_CONN_LOWWATER_MIN (CELL_PAYLOAD_SIZE)
178#define OR_CONN_LOWWATER_MAX (INT32_MAX)
179 or_conn_lowwater =
180 networkstatus_get_param(ns, "orconn_low",
181 OR_CONN_LOWWATER_DFLT,
182 OR_CONN_LOWWATER_MIN,
183 OR_CONN_LOWWATER_MAX);
184
185#define CWND_MAX_MIN 500
186#define CWND_MAX_MAX (INT32_MAX)
187 cwnd_max =
188 networkstatus_get_param(NULL, "cc_cwnd_max",
189 CWND_MAX_DFLT,
190 CWND_MAX_MIN,
191 CWND_MAX_MAX);
192
193#define RTT_RESET_PCT_MIN (0)
194#define RTT_RESET_PCT_MAX (100)
196 networkstatus_get_param(NULL, "cc_rtt_reset_pct",
197 RTT_RESET_PCT_DFLT,
198 RTT_RESET_PCT_MIN,
199 RTT_RESET_PCT_MAX);
200
201#define SENDME_INC_MIN 1
202#define SENDME_INC_MAX (254)
203 cc_sendme_inc =
204 networkstatus_get_param(NULL, "cc_sendme_inc",
205 SENDME_INC_DFLT,
206 SENDME_INC_MIN,
207 SENDME_INC_MAX);
208
209#define CC_ALG_MIN 2
210#define CC_ALG_MAX (NUM_CC_ALGS-1)
211 cc_alg =
212 networkstatus_get_param(NULL, "cc_alg",
213 CC_ALG_DFLT,
214 CC_ALG_MIN,
215 CC_ALG_MAX);
216 if (cc_alg != CC_ALG_SENDME && cc_alg != CC_ALG_VEGAS) {
217 // Does not need rate limiting because consensus updates
218 // are at most 1x/hour
219 log_warn(LD_BUG, "Unsupported congestion control algorithm %d",
220 cc_alg);
221 cc_alg = CC_ALG_DFLT;
222 }
223
224#define BWE_SENDME_MIN_MIN 2
225#define BWE_SENDME_MIN_MAX (20)
227 networkstatus_get_param(NULL, "cc_bwe_min",
228 BWE_SENDME_MIN_DFLT,
229 BWE_SENDME_MIN_MIN,
230 BWE_SENDME_MIN_MAX);
231
232#define N_EWMA_CWND_PCT_MIN 1
233#define N_EWMA_CWND_PCT_MAX (255)
235 networkstatus_get_param(NULL, "cc_ewma_cwnd_pct",
236 N_EWMA_CWND_PCT_DFLT,
237 N_EWMA_CWND_PCT_MIN,
238 N_EWMA_CWND_PCT_MAX);
239
240#define N_EWMA_MAX_MIN 2
241#define N_EWMA_MAX_MAX (INT32_MAX)
242 n_ewma_max =
243 networkstatus_get_param(NULL, "cc_ewma_max",
244 N_EWMA_MAX_DFLT,
245 N_EWMA_MAX_MIN,
246 N_EWMA_MAX_MAX);
247
248#define N_EWMA_SS_MIN 2
249#define N_EWMA_SS_MAX (INT32_MAX)
250 n_ewma_ss =
251 networkstatus_get_param(NULL, "cc_ewma_ss",
252 N_EWMA_SS_DFLT,
253 N_EWMA_SS_MIN,
254 N_EWMA_SS_MAX);
255}
256
257/**
258 * Set congestion control parameters on a circuit's congestion
259 * control object based on values from the consensus.
260 *
261 * cc_alg is the negotiated congestion control algorithm.
262 *
263 * sendme_inc is the number of packaged cells that a sendme cell
264 * acks. This parameter will come from circuit negotiation.
265 */
266static void
268 const circuit_params_t *params,
269 cc_path_t path)
270{
271 const or_options_t *opts = get_options();
272 cc->sendme_inc = params->sendme_inc_cells;
273
274#define CWND_INIT_MIN SENDME_INC_DFLT
275#define CWND_INIT_MAX (10000)
276 cc->cwnd =
277 networkstatus_get_param(NULL, "cc_cwnd_init",
278 CIRCWINDOW_INIT,
279 CWND_INIT_MIN,
280 CWND_INIT_MAX);
281
282#define CWND_INC_PCT_SS_MIN 1
283#define CWND_INC_PCT_SS_MAX (500)
284 cc->cwnd_inc_pct_ss =
285 networkstatus_get_param(NULL, "cc_cwnd_inc_pct_ss",
286 CWND_INC_PCT_SS_DFLT,
287 CWND_INC_PCT_SS_MIN,
288 CWND_INC_PCT_SS_MAX);
289
290#define CWND_INC_MIN 1
291#define CWND_INC_MAX (1000)
292 cc->cwnd_inc =
293 networkstatus_get_param(NULL, "cc_cwnd_inc",
294 CWND_INC_DFLT,
295 CWND_INC_MIN,
296 CWND_INC_MAX);
297
298#define CWND_INC_RATE_MIN 1
299#define CWND_INC_RATE_MAX (250)
300 cc->cwnd_inc_rate =
301 networkstatus_get_param(NULL, "cc_cwnd_inc_rate",
302 CWND_INC_RATE_DFLT,
303 CWND_INC_RATE_MIN,
304 CWND_INC_RATE_MAX);
305
306#define CWND_MIN_MIN SENDME_INC_DFLT
307#define CWND_MIN_MAX (1000)
308 cc->cwnd_min =
309 networkstatus_get_param(NULL, "cc_cwnd_min",
310 CWND_MIN_DFLT,
311 CWND_MIN_MIN,
312 CWND_MIN_MAX);
313
314 /* If the consensus says to use OG sendme, but torrc has
315 * always-enabled, use the default "always" alg (vegas),
316 * else use cached conensus alg. */
317 if (cc_alg == CC_ALG_SENDME && opts->AlwaysCongestionControl) {
318 cc->cc_alg = CC_ALG_DFLT_ALWAYS;
319 } else {
320 cc->cc_alg = cc_alg;
321 }
322
323 /* Algorithm-specific parameters */
324 if (cc->cc_alg == CC_ALG_VEGAS) {
326 } else {
327 // This should not happen anymore
328 log_warn(LD_BUG, "Unknown congestion control algorithm %d",
329 cc->cc_alg);
330 }
331}
332
333/** Returns true if congestion control is enabled in the most recent
334 * consensus, or if __AlwaysCongestionControl is set to true.
335 *
336 * Note that this function (and many many other functions) should not
337 * be called from the CPU worker threads when handling congestion
338 * control negotiation. Relevant values are marshaled into the
339 * `circuit_params_t` struct, in order to be used in worker threads
340 * without touching global state. Use those values in CPU worker
341 * threads, instead of calling this function.
342 *
343 * The danger is still present, in your time, as it was in ours.
344 */
345bool
347{
348 const or_options_t *opts = NULL;
349
350 tor_assert_nonfatal_once(in_main_thread());
351
352 opts = get_options();
353
354 /* If the user has set "__AlwaysCongesttionControl",
355 * then always try to negotiate congestion control, regardless
356 * of consensus param. This is to be used for testing and sbws.
357 *
358 * Note that we do *not* allow disabling congestion control
359 * if the consensus says to use it, as this is bad for queueing
360 * and fairness. */
361 if (opts->AlwaysCongestionControl)
362 return 1;
363
364 return cc_alg != CC_ALG_SENDME;
365}
366
367#ifdef TOR_UNIT_TESTS
368/**
369 * For unit tests only: set the cached consensus cc alg to
370 * specified value.
371 */
372void
373congestion_control_set_cc_enabled(void)
374{
375 cc_alg = CC_ALG_VEGAS;
376}
377
378/**
379 * For unit tests only: set the cached consensus cc alg to
380 * specified value.
381 */
382void
383congestion_control_set_cc_disabled(void)
384{
385 cc_alg = CC_ALG_SENDME;
386}
387#endif
388
389/**
390 * Allocate and initialize fields in congestion control object.
391 *
392 * cc_alg is the negotiated congestion control algorithm.
393 *
394 * sendme_inc is the number of packaged cells that a sendme cell
395 * acks. This parameter will come from circuit negotiation.
396 */
397static void
399 const circuit_params_t *params,
400 cc_path_t path)
401{
403
404 cc->in_slow_start = 1;
405 congestion_control_init_params(cc, params, path);
406
408}
409
410/** Allocate and initialize a new congestion control object */
413{
414 congestion_control_t *cc = tor_malloc_zero(sizeof(congestion_control_t));
415
416 congestion_control_init(cc, params, path);
417
419
420 return cc;
421}
422
423/**
424 * Free a congestion control object and its associated state.
425 */
426void
428{
429 if (!cc)
430 return;
431
433 smartlist_free(cc->sendme_pending_timestamps);
434
435 tor_free(cc);
436}
437
438/**
439 * Enqueue a u64 timestamp to the end of a queue of timestamps.
440 */
441STATIC inline void
442enqueue_timestamp(smartlist_t *timestamps_u64, uint64_t timestamp_usec)
443{
444 uint64_t *timestamp_ptr = tor_malloc(sizeof(uint64_t));
445 *timestamp_ptr = timestamp_usec;
446
447 smartlist_add(timestamps_u64, timestamp_ptr);
448}
449
450/**
451 * Dequeue a u64 monotime usec timestamp from the front of a
452 * smartlist of pointers to 64.
453 */
454static inline uint64_t
455dequeue_timestamp(smartlist_t *timestamps_u64_usecs)
456{
457 uint64_t *timestamp_ptr;
458 uint64_t timestamp_u64;
459
460 if (BUG(!timestamps_u64_usecs)) {
461 return 0;
462 }
463
464 if (BUG(0 == smartlist_len(timestamps_u64_usecs))) {
465 log_err(LD_CIRC, "Congestion control timestamp list became empty!");
466 return 0;
467 }
468
469 timestamp_ptr = smartlist_get(timestamps_u64_usecs, 0);
470 if (BUG(timestamp_ptr == NULL)) {
471 return 0;
472 }
473
474 timestamp_u64 = *timestamp_ptr;
475 smartlist_del_keeporder(timestamps_u64_usecs, 0);
476 tor_free(timestamp_ptr);
477
478 return timestamp_u64;
479}
480
481/**
482 * Returns the number N of N-count EWMA, for averaging RTT and BDP over
483 * N SENDME acks.
484 *
485 * This N is bracketed between a divisor of the number of acks in a CWND
486 * and a max value. It is always at least 2.
487 */
488static inline uint64_t
490{
491 uint64_t ewma_cnt = 0;
492
493 if (cc->in_slow_start) {
494 /* In slow-start, we check the Vegas condition every sendme,
495 * so much lower ewma counts are needed. */
496 ewma_cnt = n_ewma_ss;
497 } else {
498 /* After slow-start, we check the Vegas condition only once per
499 * CWND, so it is better to average over longer periods. */
500 ewma_cnt = MIN(CWND_UPDATE_RATE(cc)*n_ewma_cwnd_pct/100,
501 n_ewma_max);
502 }
503 ewma_cnt = MAX(ewma_cnt, 2);
504 return ewma_cnt;
505}
506
507/**
508 * Get a package window from either old sendme logic, or congestion control.
509 *
510 * A package window is how many cells you can still send.
511 */
512int
514 const crypt_path_t *cpath)
515{
516 int package_window;
518
519 tor_assert(circ);
520
521 if (cpath) {
522 package_window = cpath->package_window;
523 cc = cpath->ccontrol;
524 } else {
525 package_window = circ->package_window;
526 cc = circ->ccontrol;
527 }
528
529 if (!cc) {
530 return package_window;
531 } else {
532 /* Inflight can be above cwnd if cwnd was just reduced */
533 if (cc->inflight > cc->cwnd)
534 return 0;
535 /* In the extremely unlikely event that cwnd-inflight is larger than
536 * INT32_MAX, just return that cap, so old code doesn't explode. */
537 else if (cc->cwnd - cc->inflight > INT32_MAX)
538 return INT32_MAX;
539 else
540 return (int)(cc->cwnd - cc->inflight);
541 }
542}
543
544/**
545 * Returns the number of cells that are acked by every sendme.
546 */
547int
548sendme_get_inc_count(const circuit_t *circ, const crypt_path_t *layer_hint)
549{
550 int sendme_inc = CIRCWINDOW_INCREMENT;
551 congestion_control_t *cc = NULL;
552
553 if (layer_hint) {
554 cc = layer_hint->ccontrol;
555 } else {
556 cc = circ->ccontrol;
557 }
558
559 if (cc) {
560 sendme_inc = cc->sendme_inc;
561 }
562
563 return sendme_inc;
564}
565
566/** Return true iff the next cell we send will result in the other endpoint
567 * sending a SENDME.
568 *
569 * We are able to know that because the package or inflight window value minus
570 * one cell (the possible SENDME cell) should be a multiple of the
571 * cells-per-sendme increment value (set via consensus parameter, negotiated
572 * for the circuit, and passed in as sendme_inc).
573 *
574 * This function is used when recording a cell digest and this is done quite
575 * low in the stack when decrypting or encrypting a cell. The window is only
576 * updated once the cell is actually put in the outbuf.
577 */
578bool
580 const crypt_path_t *layer_hint)
581{
583 int window;
584
585 tor_assert(circ);
586
587 if (layer_hint) {
588 window = layer_hint->package_window;
589 cc = layer_hint->ccontrol;
590 } else {
591 window = circ->package_window;
592 cc = circ->ccontrol;
593 }
594
595 /* If we are using congestion control and the alg is not
596 * old-school 'fixed', then use cc->inflight to determine
597 * when sendmes will be sent */
598 if (cc) {
599 if (!cc->inflight)
600 return false;
601
602 /* This check must be +1 because this function is called *before*
603 * inflight is incremented for the sent cell */
604 if ((cc->inflight+1) % cc->sendme_inc != 0)
605 return false;
606
607 return true;
608 }
609
610 /* At the start of the window, no SENDME will be expected. */
611 if (window == CIRCWINDOW_START) {
612 return false;
613 }
614
615 /* Are we at the limit of the increment and if not, we don't expect next
616 * cell is a SENDME.
617 *
618 * We test against the window minus 1 because when we are looking if the
619 * next cell is a SENDME, the window (either package or deliver) hasn't been
620 * decremented just yet so when this is called, we are currently processing
621 * the "window - 1" cell.
622 */
623 if (((window - 1) % CIRCWINDOW_INCREMENT) != 0) {
624 return false;
625 }
626
627 /* Next cell is expected to be a SENDME. */
628 return true;
629}
630
631/**
632 * Call-in to tell congestion control code that this circuit sent a cell.
633 *
634 * This updates the 'inflight' counter, and if this is a cell that will
635 * cause the other end to send a SENDME, record the current time in a list
636 * of pending timestamps, so that we can later compute the circuit RTT when
637 * the SENDME comes back. */
638void
640 const circuit_t *circ,
641 const crypt_path_t *cpath)
642{
643 tor_assert(circ);
644 tor_assert(cc);
645
646 /* Is this the last cell before a SENDME? The idea is that if the
647 * package_window reaches a multiple of the increment, after this cell, we
648 * should expect a SENDME. Note that this function must be called *before*
649 * we account for the sent cell. */
650 if (!circuit_sent_cell_for_sendme(circ, cpath)) {
651 cc->inflight++;
652 return;
653 }
654
655 cc->inflight++;
656
657 /* Record this cell time for RTT computation when SENDME arrives */
660}
661
662/**
663 * Upon receipt of a SENDME, pop the oldest timestamp off the timestamp
664 * list, and use this to update RTT.
665 *
666 * Returns true if circuit estimates were successfully updated, false
667 * otherwise.
668 */
669bool
671 const circuit_t *circ)
672{
673 uint64_t now_usec = monotime_absolute_usec();
674
675 /* Update RTT first, then BDP. BDP needs fresh RTT */
676 uint64_t curr_rtt_usec = congestion_control_update_circuit_rtt(cc, now_usec);
677 return congestion_control_update_circuit_bdp(cc, circ, curr_rtt_usec);
678}
679
680/**
681 * Returns true if we have enough time data to use heuristics
682 * to compare RTT to a baseline.
683 */
684static bool
686{
687 /* If we have exited slow start and also have an EWMA RTT, we
688 * should have processed at least a cwnd worth of RTTs */
689 if (!cc->in_slow_start && cc->ewma_rtt_usec) {
690 return true;
691 }
692
693 /* Not enough data to estimate clock jumps */
694 return false;
695}
696
697STATIC bool is_monotime_clock_broken = false;
698
699/**
700 * Returns true if the monotime delta is 0, or is significantly
701 * different than the previous delta. Either case indicates
702 * that the monotime time source stalled or jumped.
703 *
704 * Also caches the clock state in the is_monotime_clock_broken flag,
705 * so we can also provide a is_monotime_clock_reliable() function,
706 * used by flow control rate timing.
707 */
708STATIC bool
710 uint64_t old_delta, uint64_t new_delta)
711{
712#define DELTA_DISCREPENCY_RATIO_MAX 5000
713 /* If we have a 0 new_delta, that is definitely a monotime stall */
714 if (new_delta == 0) {
715 static ratelim_t stall_info_limit = RATELIM_INIT(60);
716 log_fn_ratelim(&stall_info_limit, LOG_INFO, LD_CIRC,
717 "Congestion control cannot measure RTT due to monotime stall.");
718
719 is_monotime_clock_broken = true;
720 return true;
721 }
722
723 /*
724 * For the heuristic cases, we need at least a few timestamps,
725 * to average out any previous partial stalls or jumps. So until
726 * that point, let's just assume its OK.
727 */
729 return false;
730 }
731
732 /* If old_delta is significantly larger than new_delta, then
733 * this means that the monotime clock could have recently
734 * stopped moving forward. However, use the cache for this
735 * value, because it may also be caused by network activity,
736 * or by a previous clock jump that was not detected.
737 *
738 * So if we have not gotten a 0-delta recently, we will
739 * still allow this new low RTT, but just yell about it. */
740 if (old_delta > new_delta * DELTA_DISCREPENCY_RATIO_MAX) {
741 static ratelim_t dec_notice_limit = RATELIM_INIT(300);
742 log_fn_ratelim(&dec_notice_limit, LOG_NOTICE, LD_CIRC,
743 "Sudden decrease in circuit RTT (%"PRIu64" vs %"PRIu64
744 "), likely due to clock jump.",
745 new_delta/1000, old_delta/1000);
746
747 return is_monotime_clock_broken;
748 }
749
750 /* If new_delta is significantly larger than old_delta, then
751 * this means that the monotime clock suddenly jumped forward.
752 * However, do not cache this value, because it may also be caused
753 * by network activity.
754 */
755 if (new_delta > old_delta * DELTA_DISCREPENCY_RATIO_MAX) {
756 static ratelim_t dec_notice_limit = RATELIM_INIT(300);
757 log_fn_ratelim(&dec_notice_limit, LOG_PROTOCOL_WARN, LD_CIRC,
758 "Sudden increase in circuit RTT (%"PRIu64" vs %"PRIu64
759 "), likely due to clock jump or suspended remote endpoint.",
760 new_delta/1000, old_delta/1000);
761
762 return true;
763 }
764
765 /* All good! Update cached status, too */
766 is_monotime_clock_broken = false;
767
768 return false;
769}
770
771/**
772 * Is the monotime clock stalled according to any circuits?
773 */
774bool
776{
777 return !is_monotime_clock_broken;
778}
779
780/**
781 * Called when we get a SENDME. Updates circuit RTT by pulling off a
782 * timestamp of when we sent the CIRCWINDOW_INCREMENT-th cell from
783 * the queue of such timestamps, and comparing that to current time.
784 *
785 * Also updates min, max, and EWMA of RTT.
786 *
787 * Returns the current circuit RTT in usecs, or 0 if it could not be
788 * measured (due to clock jump, stall, etc).
789 */
790STATIC uint64_t
792 uint64_t now_usec)
793{
794 uint64_t rtt, ewma_cnt;
795 uint64_t sent_at_timestamp;
796
797 tor_assert(cc);
798
799 /* Get the time that we sent the cell that resulted in the other
800 * end sending this sendme. Use this to calculate RTT */
801 sent_at_timestamp = dequeue_timestamp(cc->sendme_pending_timestamps);
802
803 rtt = now_usec - sent_at_timestamp;
804
805 /* Do not update RTT at all if it looks fishy */
807 num_clock_stalls++; /* Accounting */
808 return 0;
809 }
810
811 ewma_cnt = n_ewma_count(cc);
812
813 cc->ewma_rtt_usec = n_count_ewma(rtt, cc->ewma_rtt_usec, ewma_cnt);
814
815 if (rtt > cc->max_rtt_usec) {
816 cc->max_rtt_usec = rtt;
817 }
818
819 if (cc->min_rtt_usec == 0) {
820 // If we do not have a min_rtt yet, use current ewma
821 cc->min_rtt_usec = cc->ewma_rtt_usec;
822 } else if (cc->cwnd == cc->cwnd_min && !cc->in_slow_start) {
823 // Raise min rtt if cwnd hit cwnd_min. This gets us out of a wedge state
824 // if we hit cwnd_min due to an abnormally low rtt.
825 uint64_t new_rtt = percent_max_mix(cc->ewma_rtt_usec, cc->min_rtt_usec,
827
828 static ratelim_t rtt_notice_limit = RATELIM_INIT(300);
829 log_fn_ratelim(&rtt_notice_limit, LOG_NOTICE, LD_CIRC,
830 "Resetting circ RTT from %"PRIu64" to %"PRIu64" due to low cwnd",
831 cc->min_rtt_usec/1000, new_rtt/1000);
832
833 cc->min_rtt_usec = new_rtt;
834 num_rtt_reset++; /* Accounting */
835 } else if (cc->ewma_rtt_usec < cc->min_rtt_usec) {
836 // Using the EWMA for min instead of current RTT helps average out
837 // effects from other conns
838 cc->min_rtt_usec = cc->ewma_rtt_usec;
839 }
840
841 return rtt;
842}
843
844/**
845 * Called when we get a SENDME. Updates the bandwidth-delay-product (BDP)
846 * estimates of a circuit. Several methods of computing BDP are used,
847 * depending on scenario. While some congestion control algorithms only
848 * use one of these methods, we update them all because it's quick and easy.
849 *
850 * - now_usec is the current monotime in usecs.
851 * - curr_rtt_usec is the current circuit RTT in usecs. It may be 0 if no
852 * RTT could bemeasured.
853 *
854 * Returns true if we were able to update BDP, false otherwise.
855 */
856static bool
858 const circuit_t *circ,
859 uint64_t curr_rtt_usec)
860{
861 int chan_q = 0;
862 unsigned int blocked_on_chan = 0;
863
864 tor_assert(cc);
865
866 if (CIRCUIT_IS_ORIGIN(circ)) {
867 /* origin circs use n_chan */
868 chan_q = circ->n_chan_cells.n;
869 blocked_on_chan = circ->circuit_blocked_on_n_chan;
870 } else {
871 /* Both onion services and exits use or_circuit and p_chan */
872 chan_q = CONST_TO_OR_CIRCUIT(circ)->p_chan_cells.n;
873 blocked_on_chan = circ->circuit_blocked_on_p_chan;
874 }
875
876 /* If we have no EWMA RTT, it is because monotime has been stalled
877 * or messed up the entire time so far. Set our BDP estimates directly
878 * to current cwnd */
879 if (!cc->ewma_rtt_usec) {
880 uint64_t cwnd = cc->cwnd;
881
882 tor_assert_nonfatal(cc->cwnd <= cwnd_max);
883
884 /* If the channel is blocked, keep subtracting off the chan_q
885 * until we hit the min cwnd. */
886 if (blocked_on_chan) {
887 /* Cast is fine because we're less than int32 */
888 if (chan_q >= (int64_t)cwnd) {
889 log_notice(LD_CIRC,
890 "Clock stall with large chanq: %d %"PRIu64, chan_q, cwnd);
891 cwnd = cc->cwnd_min;
892 } else {
893 cwnd = MAX(cwnd - chan_q, cc->cwnd_min);
894 }
895 cc->blocked_chan = 1;
896 } else {
897 cc->blocked_chan = 0;
898 }
899
900 cc->bdp = cwnd;
901
902 static ratelim_t dec_notice_limit = RATELIM_INIT(300);
903 log_fn_ratelim(&dec_notice_limit, LOG_NOTICE, LD_CIRC,
904 "Our clock has been stalled for the entire lifetime of a circuit. "
905 "Performance may be sub-optimal.");
906
907 return blocked_on_chan;
908 }
909
910 /* Congestion window based BDP will respond to changes in RTT only, and is
911 * relative to cwnd growth. It is useful for correcting for BDP
912 * overestimation, but if BDP is higher than the current cwnd, it will
913 * underestimate it.
914 *
915 * We multiply here first to avoid precision issues from min_RTT being
916 * close to ewma RTT. Since all fields are u64, there is plenty of
917 * room here to multiply first.
918 */
919 cc->bdp = cc->cwnd*cc->min_rtt_usec/cc->ewma_rtt_usec;
920
921 /* The orconn is blocked; use smaller of inflight vs SENDME */
922 if (blocked_on_chan) {
923 log_info(LD_CIRC, "CC: Streams blocked on circ channel. Chanq: %d",
924 chan_q);
925
926 /* A blocked channel is an immediate congestion signal, but it still
927 * happens only once per cwnd */
928 if (!cc->blocked_chan) {
929 cc->next_cc_event = 0;
930 cc->blocked_chan = 1;
931 }
932 } else {
933 /* If we were previously blocked, emit a new congestion event
934 * now that we are unblocked, to re-evaluate cwnd */
935 if (cc->blocked_chan) {
936 cc->blocked_chan = 0;
937 cc->next_cc_event = 0;
938 log_info(LD_CIRC, "CC: Streams un-blocked on circ channel. Chanq: %d",
939 chan_q);
940 }
941 }
942
943 if (cc->next_cc_event == 0) {
944 if (CIRCUIT_IS_ORIGIN(circ)) {
945 log_info(LD_CIRC,
946 "CC: Circuit %d "
947 "SENDME RTT: %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", "
948 "BDP estimate: %"PRIu64,
949 CONST_TO_ORIGIN_CIRCUIT(circ)->global_identifier,
950 cc->min_rtt_usec/1000,
951 curr_rtt_usec/1000,
952 cc->ewma_rtt_usec/1000,
953 cc->max_rtt_usec/1000,
954 cc->bdp);
955 } else {
956 log_info(LD_CIRC,
957 "CC: Circuit %"PRIu64":%d "
958 "SENDME RTT: %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", "
959 "%"PRIu64,
960 CONST_TO_OR_CIRCUIT(circ)->p_chan->global_identifier,
961 CONST_TO_OR_CIRCUIT(circ)->p_circ_id,
962 cc->min_rtt_usec/1000,
963 curr_rtt_usec/1000,
964 cc->ewma_rtt_usec/1000,
965 cc->max_rtt_usec/1000,
966 cc->bdp);
967 }
968 }
969
970 /* We updated BDP this round if either we had a blocked channel, or
971 * the curr_rtt_usec was not 0. */
972 bool ret = (blocked_on_chan || curr_rtt_usec != 0);
973 if (ret) {
974 tor_trace(TR_SUBSYS(cc), TR_EV(bdp_update), circ, cc, curr_rtt_usec);
975 }
976 return ret;
977}
978
979/**
980 * Dispatch the sendme to the appropriate congestion control algorithm.
981 */
982int
984 circuit_t *circ)
985{
986 int ret = -END_CIRC_REASON_INTERNAL;
987
988 tor_assert_nonfatal_once(cc->cc_alg == CC_ALG_VEGAS);
990
991 if (cc->cwnd > cwnd_max) {
992 static ratelim_t cwnd_limit = RATELIM_INIT(60);
993 log_fn_ratelim(&cwnd_limit, LOG_NOTICE, LD_CIRC,
994 "Congestion control cwnd %"PRIu64" exceeds max %d, clamping.",
995 cc->cwnd, cwnd_max);
996 cc->cwnd = cwnd_max;
997 }
998
999 /* If we have a non-zero RTT measurement, update conflux. */
1000 if (circ->conflux && cc->ewma_rtt_usec)
1001 conflux_update_rtt(circ->conflux, circ, cc->ewma_rtt_usec);
1002
1003 return ret;
1004}
1005
1006/**
1007 * Build an extension field request to negotiate congestion control.
1008 *
1009 * If congestion control is enabled, field TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST
1010 * added to ext. It is a single 0-length field that signifies that we
1011 * want to use congestion control.
1012 *
1013 * If congestion control is not enabled, no extension is added.
1014 *
1015 * If there is a failure building the request, -1 is returned, else 0.
1016 */
1017int
1019{
1020 trn_extension_field_t *field = NULL;
1021
1022 /* With congestion control enabled, add the request, else it is an empty
1023 * request in the payload. */
1024
1026 /* Build the extension field that will hold the CC field. */
1027 field = trn_extension_field_new();
1028 trn_extension_field_set_field_type(field,
1029 TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST);
1030
1031 /* No payload indicating a request to use congestion control. */
1032 trn_extension_field_set_field_len(field, 0);
1033
1034 /* Build final extension. */
1035 trn_extension_add_fields(ext, field);
1036 }
1037
1038 return 0;
1039}
1040
1041/**
1042 * Parse a congestion control ntorv3 request payload for extensions.
1043 *
1044 * On parsing failure, -1 is returned.
1045 *
1046 * If congestion control request is present, return 1. If it is not present,
1047 * return 0.
1048 *
1049 * WARNING: Called from CPU worker! Must not access any global state.
1050 */
1051int
1052congestion_control_parse_ext_request(const trn_extension_t *ext)
1053{
1054 ssize_t ret = 0;
1055
1056 if (trn_extension_find(ext, TRUNNEL_EXT_TYPE_CC_FIELD_REQUEST) == NULL) {
1057 /* No extension implies no support for congestion control. In this case, we
1058 * simply return 0 to indicate CC is disabled. */
1059 ret = 0;
1060 } else {
1061 /* For congestion control to be enabled, we only need the field type. */
1062 ret = 1;
1063 }
1064
1065 return (int)ret;
1066}
1067
1068/**
1069 * Given our observed parameters for circuits and congestion control,
1070 * as well as the parameters for the resulting circuit, build a response
1071 * payload using extension fields into *msg_out, with length specified in
1072 * *msg_out_len.
1073 *
1074 * If congestion control will be enabled, the extension field for
1075 * TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE will contain the sendme_inc value.
1076 *
1077 * If congestion control won't be enabled, an extension payload with 0
1078 * fields will be created.
1079 *
1080 * Return 0 if an extension payload was created in *msg_out, and -1 on
1081 * error.
1082 *
1083 * *msg_out must be freed if the return value is 0.
1084 *
1085 * WARNING: Called from CPU worker! Must not access any global state.
1086 */
1087int
1089 const circuit_params_t *circ_params,
1090 uint8_t **msg_out, size_t *msg_len_out)
1091{
1092 ssize_t ret;
1093 uint8_t *request = NULL;
1094 trn_extension_t *ext = NULL;
1095 trn_extension_field_t *field = NULL;
1096 trn_extension_field_cc_t *cc_field = NULL;
1097
1098 tor_assert(our_params);
1099 tor_assert(circ_params);
1100 tor_assert(msg_out);
1101 tor_assert(msg_len_out);
1102
1103 ext = trn_extension_new();
1104
1105 if (circ_params->cc_enabled) {
1106 /* Build the extension field that will hold the CC field. */
1107 field = trn_extension_field_new();
1108 trn_extension_field_set_field_type(field,
1109 TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE);
1110
1111 /* Build the congestion control field response. */
1112 cc_field = trn_extension_field_cc_new();
1113 trn_extension_field_cc_set_sendme_inc(cc_field,
1114 our_params->sendme_inc_cells);
1115
1116 ret = trn_extension_field_cc_encoded_len(cc_field);
1117 if (BUG(ret <= 0)) {
1118 trn_extension_field_free(field);
1119 goto err;
1120 }
1121 size_t field_len = ret;
1122 trn_extension_field_set_field_len(field, field_len);
1123 trn_extension_field_setlen_field(field, field_len);
1124
1125 uint8_t *field_array = trn_extension_field_getarray_field(field);
1126 ret = trn_extension_field_cc_encode(field_array,
1127 trn_extension_field_getlen_field(field), cc_field);
1128 if (BUG(ret <= 0)) {
1129 trn_extension_field_free(field);
1130 goto err;
1131 }
1132
1133 /* Build final extension. */
1134 trn_extension_add_fields(ext, field);
1135 trn_extension_set_num(ext, 1);
1136 }
1137
1138 /* Encode extension. */
1139 ret = trn_extension_encoded_len(ext);
1140 if (BUG(ret < 0)) {
1141 goto err;
1142 }
1143 size_t request_len = ret;
1144 request = tor_malloc_zero(request_len);
1145 ret = trn_extension_encode(request, request_len, ext);
1146 if (BUG(ret < 0)) {
1147 tor_free(request);
1148 goto err;
1149 }
1150 *msg_out = request;
1151 *msg_len_out = request_len;
1152
1153 /* We've just encoded the extension, clean everything. */
1154 ret = 0;
1155
1156 err:
1157 trn_extension_free(ext);
1158 trn_extension_field_cc_free(cc_field);
1159 return (int)ret;
1160}
1161
1162/** Return true iff the given sendme increment is within the acceptable
1163 * margins. */
1164bool
1166{
1167 /* We will only accept this response (and this circuit) if sendme_inc
1168 * is within +/- 1 of the current consensus value. We should not need
1169 * to change cc_sendme_inc much, and if we do, we can spread out those
1170 * changes over smaller increments once every 4 hours. Exits that
1171 * violate this range should just not be used. */
1172
1173 if (sendme_inc == 0)
1174 return false;
1175
1176 if (sendme_inc > (congestion_control_sendme_inc() + 1) ||
1177 sendme_inc < (congestion_control_sendme_inc() - 1)) {
1178 return false;
1179 }
1180 return true;
1181}
1182
1183/** Return 1 if CC is enabled which also will set the SENDME increment into our
1184 * params_out. Return 0 if CC is disabled. Else, return -1 on error. */
1185int
1186congestion_control_parse_ext_response(const trn_extension_t *ext,
1187 circuit_params_t *params_out)
1188{
1189 ssize_t ret = 0;
1190 const trn_extension_field_t *field = NULL;
1191 trn_extension_field_cc_t *cc_field = NULL;
1192
1193 /* We will only accept this response (and this circuit) if sendme_inc
1194 * is within a factor of 2 of our consensus value. We should not need
1195 * to change cc_sendme_inc much, and if we do, we can spread out those
1196 * changes over smaller increments once every 4 hours. Exits that
1197 * violate this range should just not be used. */
1198#define MAX_SENDME_INC_NEGOTIATE_FACTOR 2
1199
1200 field = trn_extension_find(ext, TRUNNEL_EXT_TYPE_CC_FIELD_RESPONSE);
1201
1202 if (field == NULL) {
1203 if (params_out->cc_requested) {
1204 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
1205 "Sent CC_REQUEST but received no CC_RESPONSE. "
1206 "Rejecting.");
1207 ret = -1;
1208 goto end;
1209 } else {
1210 ret = 0;
1211 }
1212 } else if (! params_out->cc_requested) {
1213 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
1214 "Received CC_RESPONSE without having sent CC_REQUEST. "
1215 "Rejecting.");
1216 ret = -1;
1217 goto end;
1218 } else {
1219 /* Parse the field into the congestion control field. */
1220 ret = trn_extension_field_cc_parse(&cc_field,
1221 trn_extension_field_getconstarray_field(field),
1222 trn_extension_field_getlen_field(field));
1223 if (ret < 0) {
1224 goto end;
1225 }
1226
1227 uint8_t sendme_inc_cells =
1228 trn_extension_field_cc_get_sendme_inc(cc_field);
1229 if (!congestion_control_validate_sendme_increment(sendme_inc_cells)) {
1230 ret = -1;
1231 goto end;
1232 }
1233
1234 /* All good. Get value and break */
1235 params_out->sendme_inc_cells = sendme_inc_cells;
1236 ret = 1;
1237 }
1238
1239 end:
1240 trn_extension_field_cc_free(cc_field);
1241
1242 return (int)ret;
1243}
1244
1245/**
1246 * Returns a formatted string of fields containing congestion
1247 * control information, for the CIRC_BW control port event.
1248 *
1249 * An origin circuit can have a ccontrol object directly on it,
1250 * if it is an onion service, or onion client. Exit-bound clients
1251 * will have the ccontrol on the cpath associated with their exit
1252 * (the last one in the cpath list).
1253 *
1254 * WARNING: This function does not support leaky-pipe topology. It
1255 * is to be used for control port information only.
1256 */
1257char *
1259{
1260 const congestion_control_t *ccontrol = NULL;
1261 char *ret = NULL;
1262 int len;
1263
1264 if (TO_CIRCUIT(circ)->ccontrol) {
1265 ccontrol = TO_CIRCUIT(circ)->ccontrol;
1266 } else if (circ->cpath && circ->cpath->prev->ccontrol) {
1267 /* Get ccontrol for last hop (exit) if it exists */
1268 ccontrol = circ->cpath->prev->ccontrol;
1269 }
1270
1271 if (!ccontrol)
1272 return NULL;
1273
1274 len = tor_asprintf(&ret,
1275 " SS=%d CWND=%"PRIu64" RTT=%"PRIu64" MIN_RTT=%"PRIu64,
1276 ccontrol->in_slow_start, ccontrol->cwnd,
1277 ccontrol->ewma_rtt_usec/1000,
1278 ccontrol->min_rtt_usec/1000);
1279 if (len < 0) {
1280 log_warn(LD_BUG, "Unable to format event for controller.");
1281 return NULL;
1282 }
1283
1284 return ret;
1285}
Header file for channel.c.
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
int in_main_thread(void)
uint64_t monotime_absolute_usec(void)
Functions and types for monotonic times.
const or_options_t * get_options(void)
Definition config.c:949
Header file for config.c.
void conflux_update_rtt(conflux_t *cfx, circuit_t *circ, uint64_t rtt_usec)
Definition conflux.c:708
Public APIs for conflux multipath support.
Header file for conflux_util.c.
bool congestion_control_validate_sendme_increment(uint8_t sendme_inc)
bool congestion_control_update_circuit_estimates(congestion_control_t *cc, const circuit_t *circ)
int congestion_control_parse_ext_response(const trn_extension_t *ext, circuit_params_t *params_out)
static uint64_t n_ewma_count(const congestion_control_t *cc)
int sendme_get_inc_count(const circuit_t *circ, const crypt_path_t *layer_hint)
static uint64_t dequeue_timestamp(smartlist_t *timestamps_u64_usecs)
congestion_control_t * congestion_control_new(const circuit_params_t *params, cc_path_t path)
static uint8_t rtt_reset_pct
static uint8_t n_ewma_max
int congestion_control_build_ext_request(trn_extension_t *ext)
void congestion_control_free_(congestion_control_t *cc)
STATIC bool time_delta_stalled_or_jumped(const congestion_control_t *cc, uint64_t old_delta, uint64_t new_delta)
static void congestion_control_init(congestion_control_t *cc, const circuit_params_t *params, cc_path_t path)
bool circuit_sent_cell_for_sendme(const circuit_t *circ, const crypt_path_t *layer_hint)
uint64_t congestion_control_get_num_clock_stalls(void)
static bool time_delta_should_use_heuristics(const congestion_control_t *cc)
uint64_t congestion_control_get_num_rtt_reset(void)
void congestion_control_note_cell_sent(congestion_control_t *cc, const circuit_t *circ, const crypt_path_t *cpath)
int congestion_control_build_ext_response(const circuit_params_t *our_params, const circuit_params_t *circ_params, uint8_t **msg_out, size_t *msg_len_out)
static bool congestion_control_update_circuit_bdp(congestion_control_t *, const circuit_t *, uint64_t)
static void congestion_control_init_params(congestion_control_t *cc, const circuit_params_t *params, cc_path_t path)
static uint8_t bwe_sendme_min
STATIC void enqueue_timestamp(smartlist_t *timestamps_u64, uint64_t timestamp_usec)
bool congestion_control_enabled(void)
int congestion_control_dispatch_cc_alg(congestion_control_t *cc, circuit_t *circ)
uint64_t cc_stats_circs_created
char * congestion_control_get_control_port_fields(const origin_circuit_t *circ)
bool is_monotime_clock_reliable(void)
static uint8_t n_ewma_ss
int congestion_control_get_package_window(const circuit_t *circ, const crypt_path_t *cpath)
static uint8_t n_ewma_cwnd_pct
void congestion_control_new_consensus_params(const networkstatus_t *ns)
int congestion_control_parse_ext_request(const trn_extension_t *ext)
STATIC uint64_t congestion_control_update_circuit_rtt(congestion_control_t *cc, uint64_t now_usec)
Public APIs for congestion control.
static uint64_t n_count_ewma(uint64_t curr, uint64_t prev, uint64_t N)
static uint64_t percent_max_mix(uint64_t a, uint64_t b, uint8_t pct_max)
static uint8_t congestion_control_sendme_inc(void)
Structure definitions for congestion control.
static uint64_t CWND_UPDATE_RATE(const struct congestion_control_t *cc)
@ CC_ALG_SENDME
void congestion_control_vegas_set_params(congestion_control_t *cc, cc_path_t path)
int congestion_control_vegas_process_sendme(congestion_control_t *cc, const circuit_t *circ)
Private-ish APIs for the TOR_VEGAS congestion control algorithm.
Header file for connection.c.
Header file for crypt_path.c.
#define TR_SUBSYS(name)
Definition events.h:45
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition log.h:288
#define LD_PROTOCOL
Definition log.h:72
#define LD_BUG
Definition log.h:86
#define LOG_NOTICE
Definition log.h:50
#define LD_CIRC
Definition log.h:82
#define LOG_INFO
Definition log.h:45
#define tor_free(p)
Definition malloc.h:56
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
const trn_extension_field_t * trn_extension_find(const trn_extension_t *ext, uint8_t ext_type)
Header file for onion_crypto.c.
Master header file for Tor-specific functionality.
#define TO_CIRCUIT(x)
Definition or.h:951
#define CIRCWINDOW_START
Definition or.h:446
#define CIRCWINDOW_INCREMENT
Definition or.h:450
Origin circuit structure.
int tor_asprintf(char **strp, const char *fmt,...)
Definition printf.c:75
Header file for sendme.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_del_keeporder(smartlist_t *sl, int idx)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
uint8_t sendme_inc_cells
unsigned int circuit_blocked_on_n_chan
Definition circuit_st.h:92
unsigned int circuit_blocked_on_p_chan
Definition circuit_st.h:95
cell_queue_t n_chan_cells
Definition circuit_st.h:82
struct conflux_t * conflux
Definition circuit_st.h:282
int package_window
Definition circuit_st.h:117
struct congestion_control_t * ccontrol
Definition circuit_st.h:269
smartlist_t * sendme_pending_timestamps
struct crypt_path_t * prev
struct congestion_control_t * ccontrol
cell_queue_t p_chan_cells
int AlwaysCongestionControl
crypt_path_t * cpath
#define STATIC
Definition testsupport.h:32
#define tor_assert(expr)
Definition util_bug.h:103