tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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) */