mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Implement circuitmux_assert_okay() and helper functions in circuitmux.c
This commit is contained in:
parent
4a14c6aa67
commit
34591c61ef
@ -110,6 +110,8 @@ struct circuit_muxinfo_s {
|
|||||||
cell_direction_t direction;
|
cell_direction_t direction;
|
||||||
/* Policy-specific data */
|
/* Policy-specific data */
|
||||||
circuitmux_policy_circ_data_t *policy_data;
|
circuitmux_policy_circ_data_t *policy_data;
|
||||||
|
/* Mark bit for consistency checker */
|
||||||
|
unsigned int mark:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -148,6 +150,9 @@ static INLINE circuit_t **
|
|||||||
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
circuitmux_next_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
||||||
static INLINE circuit_t **
|
static INLINE circuit_t **
|
||||||
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
circuitmux_prev_active_circ_p(circuitmux_t *cmux, circuit_t *circ);
|
||||||
|
static void circuitmux_assert_okay_pass_one(circuitmux_t *cmux);
|
||||||
|
static void circuitmux_assert_okay_pass_two(circuitmux_t *cmux);
|
||||||
|
static void circuitmux_assert_okay_pass_three(circuitmux_t *cmux);
|
||||||
|
|
||||||
/* Function definitions */
|
/* Function definitions */
|
||||||
|
|
||||||
@ -1346,3 +1351,284 @@ circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Circuitmux consistency checking assertions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that circuitmux data structures are consistent and fail with an
|
||||||
|
* assert if not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
circuitmux_assert_okay(circuitmux_t *cmux)
|
||||||
|
{
|
||||||
|
tor_assert(cmux);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass 1: iterate the hash table; for each entry:
|
||||||
|
* a) Check that the circuit has this cmux for n_mux or p_mux
|
||||||
|
* b) If the cell_count is > 0, set the mark bit; otherwise clear it
|
||||||
|
* c) Also check activeness (cell_count > 0 should be active)
|
||||||
|
* d) Count the number of circuits, active circuits and queued cells
|
||||||
|
* and at the end check that they match the counters in the cmux.
|
||||||
|
*
|
||||||
|
* Pass 2: iterate the active circuits list; for each entry,
|
||||||
|
* make sure the circuit is attached to this mux and appears
|
||||||
|
* in the hash table. Make sure the mark bit is 1, and clear
|
||||||
|
* it in the hash table entry. Consistency-check the linked
|
||||||
|
* list pointers.
|
||||||
|
*
|
||||||
|
* Pass 3: iterate the hash table again; assert if any active circuits
|
||||||
|
* (mark bit set to 1) are discovered that weren't cleared in pass 2
|
||||||
|
* (don't appear in the linked list).
|
||||||
|
*/
|
||||||
|
|
||||||
|
circuitmux_assert_okay_pass_one(cmux);
|
||||||
|
circuitmux_assert_okay_pass_two(cmux);
|
||||||
|
circuitmux_assert_okay_pass_three(cmux);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the first pass of circuitmux_assert_okay(); see the comment in that
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
circuitmux_assert_okay_pass_one(circuitmux_t *cmux)
|
||||||
|
{
|
||||||
|
chanid_circid_muxinfo_t **i = NULL;
|
||||||
|
uint64_t chan_id;
|
||||||
|
channel_t *chan;
|
||||||
|
circid_t circ_id;
|
||||||
|
circuit_t *circ;
|
||||||
|
or_circuit_t *or_circ;
|
||||||
|
unsigned int circ_is_active;
|
||||||
|
circuit_t **next_p, **prev_p;
|
||||||
|
unsigned int n_circuits, n_active_circuits, n_cells;
|
||||||
|
|
||||||
|
tor_assert(cmux);
|
||||||
|
tor_assert(cmux->chanid_circid_map);
|
||||||
|
|
||||||
|
/* Reset the counters */
|
||||||
|
n_circuits = n_active_circuits = n_cells = 0;
|
||||||
|
/* Start iterating the hash table */
|
||||||
|
i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
|
||||||
|
while (i) {
|
||||||
|
/* Assert that the hash table entry isn't null */
|
||||||
|
tor_assert(*i);
|
||||||
|
|
||||||
|
/* Get the channel and circuit id */
|
||||||
|
chan_id = (*i)->chan_id;
|
||||||
|
circ_id = (*i)->circ_id;
|
||||||
|
|
||||||
|
/* Find the channel and circuit, assert that they exist */
|
||||||
|
chan = channel_find_by_global_id(chan_id);
|
||||||
|
tor_assert(chan);
|
||||||
|
circ = circuit_get_by_circid_channel(circ_id, chan);
|
||||||
|
tor_assert(circ);
|
||||||
|
|
||||||
|
/* Clear the circ_is_active bit to start */
|
||||||
|
circ_is_active = 0;
|
||||||
|
|
||||||
|
/* Assert that we know which direction this is going */
|
||||||
|
tor_assert((*i)->muxinfo.direction == CELL_DIRECTION_OUT ||
|
||||||
|
(*i)->muxinfo.direction == CELL_DIRECTION_IN);
|
||||||
|
|
||||||
|
if ((*i)->muxinfo.direction == CELL_DIRECTION_OUT) {
|
||||||
|
/* We should be n_mux on this circuit */
|
||||||
|
tor_assert(cmux == circ->n_mux);
|
||||||
|
tor_assert(chan == circ->n_chan);
|
||||||
|
/* Get next and prev for next test */
|
||||||
|
next_p = &(circ->next_active_on_n_chan);
|
||||||
|
prev_p = &(circ->prev_active_on_n_chan);
|
||||||
|
} else {
|
||||||
|
/* This should be an or_circuit_t and we should be p_mux */
|
||||||
|
or_circ = TO_OR_CIRCUIT(circ);
|
||||||
|
tor_assert(cmux == or_circ->p_mux);
|
||||||
|
tor_assert(chan == or_circ->p_chan);
|
||||||
|
/* Get next and prev for next test */
|
||||||
|
next_p = &(or_circ->next_active_on_p_chan);
|
||||||
|
prev_p = &(or_circ->prev_active_on_p_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Should this circuit be active? I.e., does the mux know about > 0
|
||||||
|
* cells on it?
|
||||||
|
*/
|
||||||
|
circ_is_active = ((*i)->muxinfo.cell_count > 0);
|
||||||
|
|
||||||
|
/* It should be in the linked list iff it's active */
|
||||||
|
if (circ_is_active) {
|
||||||
|
/* Either we have a next link or we are the tail */
|
||||||
|
tor_assert(*next_p || (circ == cmux->active_circuits_tail));
|
||||||
|
/* Either we have a prev link or we are the head */
|
||||||
|
tor_assert(*prev_p || (circ == cmux->active_circuits_head));
|
||||||
|
/* Increment the active circuits counter */
|
||||||
|
++n_active_circuits;
|
||||||
|
} else {
|
||||||
|
/* Shouldn't be in list, so no next or prev link */
|
||||||
|
tor_assert(!(*next_p));
|
||||||
|
tor_assert(!(*prev_p));
|
||||||
|
/* And can't be head or tail */
|
||||||
|
tor_assert(circ != cmux->active_circuits_head);
|
||||||
|
tor_assert(circ != cmux->active_circuits_tail);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increment the circuits counter */
|
||||||
|
++n_circuits;
|
||||||
|
/* Adjust the cell counter */
|
||||||
|
n_cells += (*i)->muxinfo.cell_count;
|
||||||
|
|
||||||
|
/* Set the mark bit to circ_is_active */
|
||||||
|
(*i)->muxinfo.mark = circ_is_active;
|
||||||
|
|
||||||
|
/* Advance to the next entry */
|
||||||
|
i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now check the counters */
|
||||||
|
tor_assert(n_cells == cmux->n_cells);
|
||||||
|
tor_assert(n_circuits == cmux->n_circuits);
|
||||||
|
tor_assert(n_active_circuits == cmux->n_active_circuits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the second pass of circuitmux_assert_okay(); see the comment in that
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
circuitmux_assert_okay_pass_two(circuitmux_t *cmux)
|
||||||
|
{
|
||||||
|
circuit_t *curr_circ, *prev_circ = NULL, *next_circ;
|
||||||
|
or_circuit_t *curr_or_circ;
|
||||||
|
uint64_t curr_chan_id;
|
||||||
|
circid_t curr_circ_id;
|
||||||
|
circuit_t **next_p, **prev_p;
|
||||||
|
channel_t *chan;
|
||||||
|
unsigned int n_active_circuits = 0;
|
||||||
|
cell_direction_t direction;
|
||||||
|
chanid_circid_muxinfo_t search, *hashent = NULL;
|
||||||
|
|
||||||
|
tor_assert(cmux);
|
||||||
|
tor_assert(cmux->chanid_circid_map);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk the linked list of active circuits in cmux; keep track of the
|
||||||
|
* previous circuit seen for consistency checking purposes. Count them
|
||||||
|
* to make sure the number in the linked list matches
|
||||||
|
* cmux->n_active_circuits.
|
||||||
|
*/
|
||||||
|
curr_circ = cmux->active_circuits_head;
|
||||||
|
while (curr_circ) {
|
||||||
|
/* Reset some things */
|
||||||
|
chan = NULL;
|
||||||
|
curr_or_circ = NULL;
|
||||||
|
next_circ = NULL;
|
||||||
|
next_p = prev_p = NULL;
|
||||||
|
direction = 0;
|
||||||
|
|
||||||
|
/* Figure out if this is n_mux or p_mux */
|
||||||
|
if (cmux == curr_circ->n_mux) {
|
||||||
|
/* Get next_p and prev_p */
|
||||||
|
next_p = &(curr_circ->next_active_on_n_chan);
|
||||||
|
prev_p = &(curr_circ->prev_active_on_n_chan);
|
||||||
|
/* Get the channel */
|
||||||
|
chan = curr_circ->n_chan;
|
||||||
|
/* Get the circuit id */
|
||||||
|
curr_circ_id = curr_circ->n_circ_id;
|
||||||
|
/* Remember the direction */
|
||||||
|
direction = CELL_DIRECTION_OUT;
|
||||||
|
} else {
|
||||||
|
/* We must be p_mux and this must be an or_circuit_t */
|
||||||
|
curr_or_circ = TO_OR_CIRCUIT(curr_circ);
|
||||||
|
tor_assert(cmux == curr_or_circ->p_mux);
|
||||||
|
/* Get next_p and prev_p */
|
||||||
|
next_p = &(curr_or_circ->next_active_on_p_chan);
|
||||||
|
prev_p = &(curr_or_circ->prev_active_on_p_chan);
|
||||||
|
/* Get the channel */
|
||||||
|
chan = curr_or_circ->p_chan;
|
||||||
|
/* Get the circuit id */
|
||||||
|
curr_circ_id = curr_or_circ->p_circ_id;
|
||||||
|
/* Remember the direction */
|
||||||
|
direction = CELL_DIRECTION_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assert that we got a channel and get the channel ID */
|
||||||
|
tor_assert(chan);
|
||||||
|
curr_chan_id = chan->global_identifier;
|
||||||
|
|
||||||
|
/* Assert that prev_p points to last circuit we saw */
|
||||||
|
tor_assert(*prev_p == prev_circ);
|
||||||
|
/* If that's NULL, assert that we are the head */
|
||||||
|
if (!(*prev_p)) tor_assert(curr_circ == cmux->active_circuits_head);
|
||||||
|
|
||||||
|
/* Get the next circuit */
|
||||||
|
next_circ = *next_p;
|
||||||
|
/* If it's NULL, assert that we are the tail */
|
||||||
|
if (!(*next_p)) tor_assert(curr_circ == cmux->active_circuits_tail);
|
||||||
|
|
||||||
|
/* Now find the hash table entry for this circuit */
|
||||||
|
search.chan_id = curr_chan_id;
|
||||||
|
search.circ_id = curr_circ_id;
|
||||||
|
hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
|
||||||
|
&search);
|
||||||
|
|
||||||
|
/* Assert that we have one */
|
||||||
|
tor_assert(hashent);
|
||||||
|
|
||||||
|
/* Assert that the direction matches */
|
||||||
|
tor_assert(direction == hashent->muxinfo.direction);
|
||||||
|
|
||||||
|
/* Assert that the hash entry got marked in pass one */
|
||||||
|
tor_assert(hashent->muxinfo.mark);
|
||||||
|
|
||||||
|
/* Clear the mark */
|
||||||
|
hashent->muxinfo.mark = 0;
|
||||||
|
|
||||||
|
/* Increment the counter */
|
||||||
|
++n_active_circuits;
|
||||||
|
|
||||||
|
/* Advance to the next active circuit and update prev_circ */
|
||||||
|
prev_circ = curr_circ;
|
||||||
|
curr_circ = next_circ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Assert that the counter matches the cmux */
|
||||||
|
tor_assert(n_active_circuits == cmux->n_active_circuits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do the third pass of circuitmux_assert_okay(); see the comment in that
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
circuitmux_assert_okay_pass_three(circuitmux_t *cmux)
|
||||||
|
{
|
||||||
|
chanid_circid_muxinfo_t **i = NULL;
|
||||||
|
|
||||||
|
tor_assert(cmux);
|
||||||
|
tor_assert(cmux->chanid_circid_map);
|
||||||
|
|
||||||
|
/* Start iterating the hash table */
|
||||||
|
i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
|
||||||
|
|
||||||
|
/* Advance through each entry */
|
||||||
|
while (i) {
|
||||||
|
/* Assert that it isn't null */
|
||||||
|
tor_assert(*i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assert that this entry is not marked - i.e., that either we didn't
|
||||||
|
* think it should be active in pass one or we saw it in the active
|
||||||
|
* circuits linked list.
|
||||||
|
*/
|
||||||
|
tor_assert(!((*i)->muxinfo.mark));
|
||||||
|
|
||||||
|
/* Advance to the next entry */
|
||||||
|
i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user