scheduler.h (8421B)
1 /* * Copyright (c) 2017-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 4 /** 5 * \file scheduler.h 6 * \brief Header file for scheduler*.c 7 **/ 8 9 #ifndef TOR_SCHEDULER_H 10 #define TOR_SCHEDULER_H 11 12 #include "core/or/or.h" 13 #include "core/or/channel.h" 14 #include "lib/testsupport/testsupport.h" 15 16 /** Scheduler type, we build an ordered list with those values from the 17 * parsed strings in Schedulers. The reason to do such a thing is so we can 18 * quickly and without parsing strings select the scheduler at anytime. */ 19 typedef enum { 20 SCHEDULER_NONE = -1, 21 SCHEDULER_VANILLA = 1, 22 SCHEDULER_KIST = 2, 23 SCHEDULER_KIST_LITE = 3, 24 } scheduler_types_t; 25 26 /** 27 * A scheduler implementation is a collection of function pointers. If you 28 * would like to add a new scheduler called foo, create scheduler_foo.c, 29 * implement at least the mandatory ones, and implement get_foo_scheduler() 30 * that returns a complete scheduler_t for your foo scheduler. See 31 * scheduler_kist.c for an example. 32 * 33 * These function pointers SHOULD NOT be used anywhere outside of the 34 * scheduling source files. The rest of Tor should communicate with the 35 * scheduling system through the functions near the bottom of this file, and 36 * those functions will call into the current scheduler implementation as 37 * necessary. 38 * 39 * If your scheduler doesn't need to implement something (for example: it 40 * doesn't create any state for itself, thus it has nothing to free when Tor 41 * is shutting down), then set that function pointer to NULL. 42 */ 43 typedef struct scheduler_t { 44 /* Scheduler type. This is used for logging when the scheduler is switched 45 * during runtime. */ 46 scheduler_types_t type; 47 48 /* (Optional) To be called when we want to prepare a scheduler for use. 49 * Perhaps Tor just started and we are the lucky chosen scheduler, or 50 * perhaps Tor is switching to this scheduler. No matter the case, this is 51 * where we would prepare any state and initialize parameters. You might 52 * think of this as the opposite of free_all(). */ 53 void (*init)(void); 54 55 /* (Optional) To be called when we want to tell the scheduler to delete all 56 * of its state (if any). Perhaps Tor is shutting down or perhaps we are 57 * switching schedulers. */ 58 void (*free_all)(void); 59 60 /* (Mandatory) Libevent controls the main event loop in Tor, and this is 61 * where we register with libevent the next execution of run_sched_ev [which 62 * ultimately calls run()]. */ 63 void (*schedule)(void); 64 65 /* (Mandatory) This is the heart of a scheduler! This is where the 66 * excitement happens! Here libevent has given us the chance to execute, and 67 * we should do whatever we need to do in order to move some cells from 68 * their circuit queues to output buffers in an intelligent manner. We 69 * should do this quickly. When we are done, we'll try to schedule() ourself 70 * if more work needs to be done to setup the next scheduling run. */ 71 void (*run)(void); 72 73 /* 74 * External event not related to the scheduler but that can influence it. 75 */ 76 77 /* (Optional) To be called whenever Tor finds out about a new consensus. 78 * First the scheduling system as a whole will react to the new consensus 79 * and change the scheduler if needed. After that, the current scheduler 80 * (which might be new) will call this so it has the chance to react to the 81 * new consensus too. If there's a consensus parameter that your scheduler 82 * wants to keep an eye on, this is where you should check for it. */ 83 void (*on_new_consensus)(void); 84 85 /* (Optional) To be called when a channel is being freed. Sometimes channels 86 * go away (for example: the relay on the other end is shutting down). If 87 * the scheduler keeps any channel-specific state and has memory to free 88 * when channels go away, implement this and free it here. */ 89 void (*on_channel_free)(const channel_t *); 90 91 /* (Optional) To be called whenever Tor is reloading configuration options. 92 * For example: SIGHUP was issued and Tor is rereading its torrc. A 93 * scheduler should use this as an opportunity to parse and cache torrc 94 * options so that it doesn't have to call get_options() all the time. */ 95 void (*on_new_options)(void); 96 } scheduler_t; 97 98 /***************************************************************************** 99 * Globally visible scheduler variables/values 100 * 101 * These are variables/constants that all of Tor should be able to see. 102 *****************************************************************************/ 103 104 /* Default interval that KIST runs (in ms). */ 105 #define KIST_SCHED_RUN_INTERVAL_DEFAULT 2 106 /* Minimum interval that KIST runs. */ 107 #define KIST_SCHED_RUN_INTERVAL_MIN 2 108 /* Maximum interval that KIST runs (in ms). */ 109 #define KIST_SCHED_RUN_INTERVAL_MAX 100 110 111 /***************************************************************************** 112 * Globally visible scheduler functions 113 * 114 * These functions are how the rest of Tor communicates with the scheduling 115 * system. 116 *****************************************************************************/ 117 118 void scheduler_init(void); 119 void scheduler_free_all(void); 120 void scheduler_conf_changed(void); 121 void scheduler_notify_networkstatus_changed(void); 122 MOCK_DECL(void, scheduler_release_channel, (channel_t *chan)); 123 124 /* 125 * Ways for a channel to interact with the scheduling system. A channel only 126 * really knows (i) whether or not it has cells it wants to send, and 127 * (ii) whether or not it would like to write. 128 */ 129 void scheduler_channel_wants_writes(channel_t *chan); 130 MOCK_DECL(void, scheduler_channel_doesnt_want_writes, (channel_t *chan)); 131 MOCK_DECL(void, scheduler_channel_has_waiting_cells, (channel_t *chan)); 132 133 /***************************************************************************** 134 * Private scheduler functions 135 * 136 * These functions are only visible to the scheduling system, the current 137 * scheduler implementation, and tests. 138 *****************************************************************************/ 139 #ifdef SCHEDULER_PRIVATE 140 141 #include "ext/ht.h" 142 143 /********************************* 144 * Defined in scheduler.c 145 *********************************/ 146 147 void scheduler_set_channel_state(channel_t *chan, int new_state); 148 const char *get_scheduler_state_string(int scheduler_state); 149 150 /* Triggers a BUG() and extra information with chan if available. */ 151 #define SCHED_BUG(cond, chan) \ 152 (PREDICT_UNLIKELY(cond) ? \ 153 ((BUG(cond)) ? (scheduler_bug_occurred(chan), 1) : 0) : 0) 154 155 void scheduler_bug_occurred(const channel_t *chan); 156 157 smartlist_t *get_channels_pending(void); 158 MOCK_DECL(int, scheduler_compare_channels, 159 (const void *c1_v, const void *c2_v)); 160 void scheduler_ev_active(void); 161 void scheduler_ev_add(const struct timeval *next_run); 162 163 #ifdef TOR_UNIT_TESTS 164 extern smartlist_t *channels_pending; 165 extern struct mainloop_event_t *run_sched_ev; 166 extern const scheduler_t *the_scheduler; 167 void scheduler_touch_channel(channel_t *chan); 168 #endif /* defined(TOR_UNIT_TESTS) */ 169 170 /********************************* 171 * Defined in scheduler_kist.c 172 *********************************/ 173 174 #ifdef SCHEDULER_KIST_PRIVATE 175 176 /* Socket table entry which holds information of a channel's socket and kernel 177 * TCP information. Only used by KIST. */ 178 typedef struct socket_table_ent_t { 179 HT_ENTRY(socket_table_ent_t) node; 180 const channel_t *chan; 181 /* Amount written this scheduling run */ 182 uint64_t written; 183 /* Amount that can be written this scheduling run */ 184 uint64_t limit; 185 /* TCP info from the kernel */ 186 uint32_t cwnd; 187 uint32_t unacked; 188 uint32_t mss; 189 uint32_t notsent; 190 } socket_table_ent_t; 191 192 typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_t) outbuf_table_t; 193 194 MOCK_DECL(int, channel_should_write_to_kernel, 195 (outbuf_table_t *table, channel_t *chan)); 196 MOCK_DECL(void, channel_write_to_kernel, (channel_t *chan)); 197 MOCK_DECL(void, update_socket_info_impl, (socket_table_ent_t *ent)); 198 199 int scheduler_can_use_kist(void); 200 void scheduler_kist_set_full_mode(void); 201 void scheduler_kist_set_lite_mode(void); 202 scheduler_t *get_kist_scheduler(void); 203 int kist_scheduler_run_interval(void); 204 205 #ifdef TOR_UNIT_TESTS 206 extern int32_t sched_run_interval; 207 #endif /* TOR_UNIT_TESTS */ 208 209 #endif /* defined(SCHEDULER_KIST_PRIVATE) */ 210 211 /********************************* 212 * Defined in scheduler_vanilla.c 213 *********************************/ 214 215 scheduler_t *get_vanilla_scheduler(void); 216 217 #endif /* defined(SCHEDULER_PRIVATE) */ 218 219 #endif /* !defined(TOR_SCHEDULER_H) */