diff options
-rw-r--r-- | src/or/circuitmux.c | 59 | ||||
-rw-r--r-- | src/or/circuitmux.h | 57 |
2 files changed, 100 insertions, 16 deletions
diff --git a/src/or/circuitmux.c b/src/or/circuitmux.c index 77bb56891c..860ba64e5d 100644 --- a/src/or/circuitmux.c +++ b/src/or/circuitmux.c @@ -88,21 +88,14 @@ struct circuitmux_s { struct circuit_t *active_circuits_head, *active_circuits_tail; /* - * Priority queue of cell_ewma_t for circuits with queued cells waiting - * for room to free up on this connection's outbuf. Kept in heap order - * according to EWMA. - * - * This is redundant with active_circuits; if we ever decide only to use - * the cell_ewma algorithm for choosing circuits, we can remove - * active_circuits. + * Circuitmux policy; if this is non-NULL, it can override the built- + * in round-robin active circuits behavior. This is how EWMA works in + * the new circuitmux_t world. */ - smartlist_t *active_circuit_pqueue; + const circuitmux_policy_t *policy; - /* - * The tick on which the cell_ewma_ts in active_circuit_pqueue last had - * their ewma values rescaled. - */ - unsigned int active_circuit_pqueue_last_recalibrated; + /* Policy-specific data */ + circuitmux_policy_data_t *policy_data; }; /* @@ -115,6 +108,8 @@ struct circuit_muxinfo_s { unsigned int cell_count; /* Direction of flow */ cell_direction_t direction; + /* Policy-specific data */ + circuitmux_policy_circ_data_t *policy_data; }; /* @@ -321,7 +316,13 @@ circuitmux_free(circuitmux_t *cmux) tor_assert(cmux->n_circuits == 0); tor_assert(cmux->n_active_circuits == 0); - smartlist_free(cmux->active_circuit_pqueue); + /* Free policy-specific data if we have any */ + if (cmux->policy && cmux->policy->free_cmux_data) { + if (cmux->policy_data) { + cmux->policy->free_cmux_data(cmux, cmux->policy_data); + cmux->policy_data = NULL; + } + } else tor_assert(cmux->policy_data == NULL); if (cmux->chanid_circid_map) { HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map); @@ -718,6 +719,7 @@ circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ, { circuit_t **next_active = NULL, **prev_active = NULL, **next_prev = NULL; circuitmux_t *circuit_cmux = NULL; + chanid_circid_muxinfo_t *hashent = NULL; channel_t *chan = NULL; circid_t circ_id; int already_active; @@ -782,7 +784,19 @@ circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ, /* This becomes the new head of the list */ cmux->active_circuits_head = circ; - /* TODO policy-specific notifications */ + /* Policy-specific notification */ + if (cmux->policy && + cmux->policy->notify_circ_active && + cmux->policy_data) { + /* Okay, we need to check the circuit for policy data now */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* We should have found something */ + tor_assert(hashent); + /* Check for policy data for the circuit and notify */ + if (hashent->muxinfo.policy_data) + cmux->policy->notify_circ_active(cmux, cmux->policy_data, + circ, hashent->muxinfo.policy_data); + } } /** @@ -797,6 +811,7 @@ circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ, circuit_t **next_active = NULL, **prev_active = NULL; circuit_t **next_prev = NULL, **prev_next = NULL; circuitmux_t *circuit_cmux = NULL; + chanid_circid_muxinfo_t *hashent = NULL; channel_t *chan = NULL; circid_t circ_id; int already_inactive; @@ -878,7 +893,19 @@ circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ, *prev_active = NULL; *next_active = NULL; - /* TODO policy-specific notifications */ + /* Policy-specific notification */ + if (cmux->policy && + cmux->policy->notify_circ_inactive && + cmux->policy_data) { + /* Okay, we need to check the circuit for policy data now */ + hashent = circuitmux_find_map_entry(cmux, circ); + /* We should have found something */ + tor_assert(hashent); + /* Check for policy data for the circuit and notify */ + if (hashent->muxinfo.policy_data) + cmux->policy->notify_circ_inactive(cmux, cmux->policy_data, + circ, hashent->muxinfo.policy_data); + } } /** diff --git a/src/or/circuitmux.h b/src/or/circuitmux.h index ade544f3b2..e344b6ed91 100644 --- a/src/or/circuitmux.h +++ b/src/or/circuitmux.h @@ -11,6 +11,57 @@ #include "or.h" +typedef struct circuitmux_policy_s circuitmux_policy_t; +typedef struct circuitmux_policy_data_s circuitmux_policy_data_t; +typedef struct circuitmux_policy_circ_data_s circuitmux_policy_circ_data_t; + +struct circuitmux_policy_s { + /* Allocate cmux-wide policy-specific data */ + circuitmux_policy_data_t * (*alloc_cmux_data)(circuitmux_t *cmux); + /* Free cmux-wide policy-specific data */ + void (*free_cmux_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data); + /* Allocate circuit policy-specific data for a newly attached circuit */ + circuitmux_policy_circ_data_t * + (*alloc_circ_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + cell_direction_t direction, + unsigned int cell_count); + /* Free circuit policy-specific data */ + void (*free_circ_data)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); + /* Notify that a circuit has become active/inactive */ + void (*notify_circ_active)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); + void (*notify_circ_inactive)(circuitmux_t *cmux, + circuitmux_policy_data_t *pol_data, + circuit_t *circ, + circuitmux_policy_circ_data_t *pol_circ_data); +}; + +/* + * Circuitmux policy implementations can subclass this to store circuitmux- + * wide data; it just has the magic number in the base struct. + */ + +struct circuitmux_policy_data_s { + uint32_t magic; +}; + +/* + * Circuitmux policy implementations can subclass this to store circuit- + * specific data; it just has the magic number in the base struct. + */ + +struct circuitmux_policy_circ_data_s { + uint32_t magic; +}; + /* Consistency check */ void circuitmux_assert_okay(circuitmux_t *cmux); @@ -19,6 +70,12 @@ circuitmux_t * circuitmux_alloc(void); void circuitmux_detach_all_circuits(circuitmux_t *cmux); void circuitmux_free(circuitmux_t *cmux); +/* Policy control */ +void circuitmux_clear_policy(circuitmux_t *cmux); +const circuitmux_policy_t * circuitmux_get_policy(circuitmux_t *cmux); +void circuitmux_set_policy(circuitmux_t *cmux, + const circuitmux_policy_t *pol); + /* Status inquiries */ cell_direction_t circuitmux_attached_circuit_direction( circuitmux_t *cmux, |