mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Implement circuitmux_make_circuit_inactive(), circuitmux_make_circuit_active() and linked list helper functions in circuitmux.c
This commit is contained in:
parent
fd31dd440c
commit
38fa3b7e44
@ -85,7 +85,7 @@ struct circuitmux_s {
|
||||
* free up on this connection's outbuf. Every time we pull cells from
|
||||
* a circuit, we advance this pointer to the next circuit in the ring.
|
||||
*/
|
||||
struct circuit_t *active_circuits;
|
||||
struct circuit_t *active_circuits_head, *active_circuits_tail;
|
||||
|
||||
/*
|
||||
* Priority queue of cell_ewma_t for circuits with queued cells waiting
|
||||
@ -140,9 +140,49 @@ static INLINE unsigned int
|
||||
chanid_circid_entry_hash(chanid_circid_muxinfo_t *a);
|
||||
static chanid_circid_muxinfo_t *
|
||||
circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ);
|
||||
static void
|
||||
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
|
||||
cell_direction_t direction);
|
||||
static void
|
||||
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
|
||||
cell_direction_t direction);
|
||||
static INLINE circuit_t **
|
||||
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
||||
static INLINE circuit_t **
|
||||
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
||||
|
||||
/* Function definitions */
|
||||
|
||||
/**
|
||||
* Linked list helpers
|
||||
*/
|
||||
|
||||
static INLINE circuit_t **
|
||||
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ)
|
||||
{
|
||||
tor_assert(cmux);
|
||||
tor_assert(circ);
|
||||
|
||||
if (circ->n_mux == cmux) return &(circ->next_active_on_n_chan);
|
||||
else {
|
||||
tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux);
|
||||
return &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE circuit_t **
|
||||
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ)
|
||||
{
|
||||
tor_assert(cmux);
|
||||
tor_assert(circ);
|
||||
|
||||
if (circ->n_mux == cmux) return &(circ->prev_active_on_n_chan);
|
||||
else {
|
||||
tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux);
|
||||
return &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for chanid_circid_cell_count_map_t hash table: compare the channel
|
||||
* ID and circuit ID for a and b, and return less than, equal to, or greater
|
||||
@ -225,12 +265,16 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux)
|
||||
if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) {
|
||||
/* Clear n_mux */
|
||||
circ->n_mux = NULL;
|
||||
/* Update active_circuits et al. */
|
||||
circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_OUT);
|
||||
} else if (circ->magic == OR_CIRCUIT_MAGIC) {
|
||||
/*
|
||||
* It has a sensible p_chan and direction == CELL_DIRECTION_IN,
|
||||
* so clear p_mux.
|
||||
*/
|
||||
TO_OR_CIRCUIT(circ)->p_mux = NULL;
|
||||
/* Update active_circuits et al. */
|
||||
circuitmux_make_circuit_inactive(cmux, circ, CELL_DIRECTION_IN);
|
||||
} else {
|
||||
/* Complain and move on */
|
||||
log_warn(LD_CIRC,
|
||||
@ -239,8 +283,6 @@ circuitmux_detach_all_circuits(circuitmux_t *cmux)
|
||||
to_remove->circ_id,
|
||||
U64_PRINTF_ARG(to_remove->chan_id));
|
||||
}
|
||||
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
} else {
|
||||
/* Complain and move on */
|
||||
log_warn(LD_CIRC,
|
||||
@ -432,7 +474,6 @@ circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ)
|
||||
return n_cells;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Query total number of available cells on a circuitmux
|
||||
*/
|
||||
@ -548,14 +589,14 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
|
||||
*/
|
||||
if (hashent->muxinfo.cell_count > 0 && cell_count == 0) {
|
||||
--(cmux->n_active_circuits);
|
||||
circuitmux_make_circuit_inactive(cmux, circ, direction);
|
||||
} else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) {
|
||||
++(cmux->n_active_circuits);
|
||||
circuitmux_make_circuit_active(cmux, circ, direction);
|
||||
}
|
||||
cmux->n_cells -= hashent->muxinfo.cell_count;
|
||||
cmux->n_cells += cell_count;
|
||||
hashent->muxinfo.cell_count = cell_count;
|
||||
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
} else {
|
||||
/*
|
||||
* New circuit; add an entry and update the circuit/active circuit
|
||||
@ -601,8 +642,6 @@ circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ,
|
||||
circuitmux_make_circuit_active(cmux, circ, direction);
|
||||
}
|
||||
cmux->n_cells += cell_count;
|
||||
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,9 +690,11 @@ circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ)
|
||||
if (hashent) {
|
||||
/* Update counters */
|
||||
--(cmux->n_circuits);
|
||||
if (hashent->muxinfo.cell_count > 0) --(cmux->n_active_circuits);
|
||||
if (hashent->muxinfo.cell_count > 0) {
|
||||
--(cmux->n_active_circuits);
|
||||
circuitmux_make_circuit_inactive(cmux, circ, last_searched_direction);
|
||||
}
|
||||
cmux->n_cells -= hashent->muxinfo.cell_count;
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
|
||||
/* Consistency check: the direction must match the direction searched */
|
||||
tor_assert(last_searched_direction == hashent->muxinfo.direction);
|
||||
@ -666,6 +707,180 @@ circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a circuit active; update active list and policy-specific info, but
|
||||
* we don't mess with the counters or hash table here.
|
||||
*/
|
||||
|
||||
static void
|
||||
circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
|
||||
cell_direction_t direction)
|
||||
{
|
||||
circuit_t **next_active = NULL, **prev_active = NULL, **next_prev = NULL;
|
||||
circuitmux_t *circuit_cmux = NULL;
|
||||
channel_t *chan = NULL;
|
||||
circid_t circ_id;
|
||||
int already_active;
|
||||
|
||||
tor_assert(cmux);
|
||||
tor_assert(circ);
|
||||
tor_assert(direction == CELL_DIRECTION_OUT ||
|
||||
direction == CELL_DIRECTION_IN);
|
||||
|
||||
/* Get the right set of active list links for this direction */
|
||||
if (direction == CELL_DIRECTION_OUT) {
|
||||
next_active = &(circ->next_active_on_n_chan);
|
||||
prev_active = &(circ->prev_active_on_n_chan);
|
||||
circuit_cmux = circ->n_mux;
|
||||
chan = circ->n_chan;
|
||||
circ_id = circ->n_circ_id;
|
||||
} else {
|
||||
next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
|
||||
prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
|
||||
circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux;
|
||||
chan = TO_OR_CIRCUIT(circ)->p_chan;
|
||||
circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
||||
}
|
||||
|
||||
/* Assert that it is attached to this mux and a channel */
|
||||
tor_assert(cmux == circuit_cmux);
|
||||
tor_assert(chan != NULL);
|
||||
|
||||
/*
|
||||
* Check if the circuit really was inactive; if it's active, at least one
|
||||
* of the next_active and prev_active pointers will not be NULL, or this
|
||||
* circuit will be either the head or tail of the list for this cmux.
|
||||
*/
|
||||
already_active = (*prev_active != NULL || *next_active != NULL ||
|
||||
cmux->active_circuits_head == circ ||
|
||||
cmux->active_circuits_tail == circ);
|
||||
|
||||
/* If we're already active, log a warning and finish */
|
||||
if (already_active) {
|
||||
log_warn(LD_CIRC,
|
||||
"Circuit %d on channel " U64_FORMAT " was already active",
|
||||
circ_id, U64_PRINTF_ARG(chan->global_identifier));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is going at the head of the list; if the old head is not NULL,
|
||||
* then its prev pointer should point to this.
|
||||
*/
|
||||
*next_active = cmux->active_circuits_head; /* Next is old head */
|
||||
*prev_active = NULL; /* Prev is NULL (this will be the head) */
|
||||
if (cmux->active_circuits_head) {
|
||||
/* The list had an old head; update its prev pointer */
|
||||
next_prev =
|
||||
circuitmux_prev_active_circ_p(cmux, cmux->active_circuits_head);
|
||||
tor_assert(next_prev);
|
||||
*next_prev = circ;
|
||||
} else {
|
||||
/* The list was empty; this becomes the tail as well */
|
||||
cmux->active_circuits_tail = circ;
|
||||
}
|
||||
/* This becomes the new head of the list */
|
||||
cmux->active_circuits_head = circ;
|
||||
|
||||
/* TODO policy-specific notifications */
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a circuit inactive; update active list and policy-specific info, but
|
||||
* we don't mess with the counters or hash table here.
|
||||
*/
|
||||
|
||||
static void
|
||||
circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
|
||||
cell_direction_t direction)
|
||||
{
|
||||
circuit_t **next_active = NULL, **prev_active = NULL;
|
||||
circuit_t **next_prev = NULL, **prev_next = NULL;
|
||||
circuitmux_t *circuit_cmux = NULL;
|
||||
channel_t *chan = NULL;
|
||||
circid_t circ_id;
|
||||
int already_inactive;
|
||||
|
||||
tor_assert(cmux);
|
||||
tor_assert(circ);
|
||||
tor_assert(direction == CELL_DIRECTION_OUT ||
|
||||
direction == CELL_DIRECTION_IN);
|
||||
|
||||
/* Get the right set of active list links for this direction */
|
||||
if (direction == CELL_DIRECTION_OUT) {
|
||||
next_active = &(circ->next_active_on_n_chan);
|
||||
prev_active = &(circ->prev_active_on_n_chan);
|
||||
circuit_cmux = circ->n_mux;
|
||||
chan = circ->n_chan;
|
||||
circ_id = circ->n_circ_id;
|
||||
} else {
|
||||
next_active = &(TO_OR_CIRCUIT(circ)->next_active_on_p_chan);
|
||||
prev_active = &(TO_OR_CIRCUIT(circ)->prev_active_on_p_chan);
|
||||
circuit_cmux = TO_OR_CIRCUIT(circ)->p_mux;
|
||||
chan = TO_OR_CIRCUIT(circ)->p_chan;
|
||||
circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
||||
}
|
||||
|
||||
/* Assert that it is attached to this mux and a channel */
|
||||
tor_assert(cmux == circuit_cmux);
|
||||
tor_assert(chan != NULL);
|
||||
|
||||
/*
|
||||
* Check if the circuit really was active; if it's inactive, the
|
||||
* next_active and prev_active pointers will be NULL and this circuit
|
||||
* will not be the head or tail of the list for this cmux.
|
||||
*/
|
||||
already_inactive = (*prev_active == NULL && *next_active == NULL &&
|
||||
cmux->active_circuits_head != circ &&
|
||||
cmux->active_circuits_tail != circ);
|
||||
|
||||
/* If we're already inactive, log a warning and finish */
|
||||
if (already_inactive) {
|
||||
log_warn(LD_CIRC,
|
||||
"Circuit %d on channel " U64_FORMAT " was already inactive",
|
||||
circ_id, U64_PRINTF_ARG(chan->global_identifier));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove from the list; first get next_prev and prev_next */
|
||||
if (*next_active) {
|
||||
/*
|
||||
* If there's a next circuit, its previous circuit becomes this
|
||||
* circuit's previous circuit.
|
||||
*/
|
||||
next_prev = circuitmux_prev_active_circ_p(cmux, *next_active);
|
||||
} else {
|
||||
/* Else, the tail becomes this circuit's previous circuit */
|
||||
next_prev = &(cmux->active_circuits_tail);
|
||||
}
|
||||
|
||||
/* Got next_prev, now prev_next */
|
||||
if (*prev_active) {
|
||||
/*
|
||||
* If there's a previous circuit, its next circuit becomes this circuit's
|
||||
* next circuit.
|
||||
*/
|
||||
prev_next = circuitmux_next_active_circ_p(cmux, *prev_active);
|
||||
} else {
|
||||
/* Else, the head becomes this circuit's next circuit */
|
||||
prev_next = &(cmux->active_circuits_head);
|
||||
}
|
||||
|
||||
/* Assert that we got sensible values for the next/prev pointers */
|
||||
tor_assert(next_prev != NULL);
|
||||
tor_assert(prev_next != NULL);
|
||||
|
||||
/* Update the next/prev pointers - this removes circ from the list */
|
||||
*next_prev = *prev_active;
|
||||
*prev_next = *next_active;
|
||||
|
||||
/* Now null out prev_active/next_active */
|
||||
*prev_active = NULL;
|
||||
*next_active = NULL;
|
||||
|
||||
/* TODO policy-specific notifications */
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cell counter for a circuit on a circuitmux
|
||||
*/
|
||||
@ -705,11 +920,11 @@ circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
|
||||
*/
|
||||
if (hashent->muxinfo.cell_count > 0 && n_cells == 0) {
|
||||
--(cmux->n_active_circuits);
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
circuitmux_make_circuit_inactive(cmux, circ, hashent->muxinfo.direction);
|
||||
/* Is the old cell count == 0 and the new cell count > 0 ? */
|
||||
} else if (hashent->muxinfo.cell_count == 0 && n_cells > 0) {
|
||||
++(cmux->n_active_circuits);
|
||||
/* TODO update active_circuits / active_circuit_pqueue */
|
||||
circuitmux_make_circuit_active(cmux, circ, hashent->muxinfo.direction);
|
||||
}
|
||||
|
||||
/* Update hash entry cell counter */
|
||||
|
Loading…
Reference in New Issue
Block a user