Line data Source code
1 : /* * Copyright (c) 2012-2021, The Tor Project, Inc. */ 2 : /* See LICENSE for licensing information */ 3 : 4 : /** 5 : * \file circuitmux_ewma.h 6 : * \brief Header file for circuitmux_ewma.c 7 : **/ 8 : 9 : #ifndef TOR_CIRCUITMUX_EWMA_H 10 : #define TOR_CIRCUITMUX_EWMA_H 11 : 12 : #include "core/or/or.h" 13 : #include "core/or/circuitmux.h" 14 : 15 : /* The public EWMA policy callbacks object. */ 16 : extern circuitmux_policy_t ewma_policy; 17 : 18 : /* Externally visible EWMA functions */ 19 : void cmux_ewma_set_options(const or_options_t *options, 20 : const networkstatus_t *consensus); 21 : 22 : void circuitmux_ewma_free_all(void); 23 : 24 : #ifdef CIRCUITMUX_EWMA_PRIVATE 25 : 26 : /*** EWMA structures ***/ 27 : 28 : typedef struct cell_ewma_t cell_ewma_t; 29 : typedef struct ewma_policy_data_t ewma_policy_data_t; 30 : typedef struct ewma_policy_circ_data_t ewma_policy_circ_data_t; 31 : 32 : /** 33 : * The cell_ewma_t structure keeps track of how many cells a circuit has 34 : * transferred recently. It keeps an EWMA (exponentially weighted moving 35 : * average) of the number of cells flushed from the circuit queue onto a 36 : * connection in channel_flush_from_first_active_circuit(). 37 : */ 38 : 39 : struct cell_ewma_t { 40 : /** The last 'tick' at which we recalibrated cell_count. 41 : * 42 : * A cell sent at exactly the start of this tick has weight 1.0. Cells sent 43 : * since the start of this tick have weight greater than 1.0; ones sent 44 : * earlier have less weight. */ 45 : unsigned int last_adjusted_tick; 46 : /** The EWMA of the cell count. */ 47 : double cell_count; 48 : /** True iff this is the cell count for a circuit's previous 49 : * channel. */ 50 : unsigned int is_for_p_chan : 1; 51 : /** The position of the circuit within the OR connection's priority 52 : * queue. */ 53 : int heap_index; 54 : }; 55 : 56 : struct ewma_policy_data_t { 57 : circuitmux_policy_data_t base_; 58 : 59 : /** 60 : * Priority queue of cell_ewma_t for circuits with queued cells waiting 61 : * for room to free up on the channel that owns this circuitmux. Kept 62 : * in heap order according to EWMA. This was formerly in channel_t, and 63 : * in or_connection_t before that. 64 : */ 65 : smartlist_t *active_circuit_pqueue; 66 : 67 : /** 68 : * The tick on which the cell_ewma_ts in active_circuit_pqueue last had 69 : * their ewma values rescaled. This was formerly in channel_t, and in 70 : * or_connection_t before that. 71 : */ 72 : unsigned int active_circuit_pqueue_last_recalibrated; 73 : }; 74 : 75 : struct ewma_policy_circ_data_t { 76 : circuitmux_policy_circ_data_t base_; 77 : 78 : /** 79 : * The EWMA count for the number of cells flushed from this circuit 80 : * onto this circuitmux. Used to determine which circuit to flush 81 : * from next. This was formerly in circuit_t and or_circuit_t. 82 : */ 83 : cell_ewma_t cell_ewma; 84 : 85 : /** 86 : * Pointer back to the circuit_t this is for; since we're separating 87 : * out circuit selection policy like this, we can't attach cell_ewma_t 88 : * to the circuit_t any more, so we can't use SUBTYPE_P directly to a 89 : * circuit_t like before; instead get it here. 90 : */ 91 : circuit_t *circ; 92 : }; 93 : 94 : #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU 95 : #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U 96 : 97 : /*** Downcasts for the above types ***/ 98 : 99 : /** 100 : * Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert 101 : * if the cast is impossible. 102 : */ 103 : 104 : static inline ewma_policy_data_t * 105 274 : TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol) 106 : { 107 274 : if (!pol) return NULL; 108 : else { 109 274 : tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC, 110 : "Mismatch: %"PRIu32" != %"PRIu32, 111 : pol->magic, EWMA_POL_DATA_MAGIC); 112 : return DOWNCAST(ewma_policy_data_t, pol); 113 : } 114 : } 115 : 116 : /** 117 : * Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t 118 : * and assert if the cast is impossible. 119 : */ 120 : 121 : static inline ewma_policy_circ_data_t * 122 59 : TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol) 123 : { 124 59 : if (!pol) return NULL; 125 : else { 126 59 : tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC, 127 : "Mismatch: %"PRIu32" != %"PRIu32, 128 : pol->magic, EWMA_POL_CIRC_DATA_MAGIC); 129 : return DOWNCAST(ewma_policy_circ_data_t, pol); 130 : } 131 : } 132 : 133 : STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out); 134 : STATIC void cell_ewma_initialize_ticks(void); 135 : 136 : #endif /* defined(CIRCUITMUX_EWMA_PRIVATE) */ 137 : 138 : #endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */