1 /* * Copyright (c) 2012-2013, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Circuit mux/cell selection abstraction
11 #include "circuitlist.h"
12 #include "circuitmux.h"
16 * Private typedefs for circuitmux.c
20 * Map of muxinfos for circuitmux_t to use; struct is defined below (name
21 * of struct must match HT_HEAD line).
23 typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t
;
26 * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
27 * break the hash table code).
29 typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t
;
32 * Anything the mux wants to store per-circuit in the map; right now just
33 * a count of queued cells.
36 typedef struct circuit_muxinfo_s circuit_muxinfo_t
;
39 * Structures for circuitmux.c
43 * A circuitmux is a collection of circuits; it tracks which subset
44 * of the attached circuits are 'active' (i.e., have cells available
45 * to transmit) and how many cells on each. It expoes three distinct
46 * interfaces to other components:
48 * To channels, which each have a circuitmux_t, the supported operations
51 * circuitmux_get_first_active_circuit():
53 * Pick one of the circuitmux's active circuits to send cells from.
55 * circuitmux_notify_xmit_cells():
57 * Notify the circuitmux that cells have been sent on a circuit.
59 * To circuits, the exposed operations are:
61 * circuitmux_attach_circuit():
63 * Attach a circuit to the circuitmux; this will allocate any policy-
64 * specific data wanted for this circuit and add it to the active
65 * circuits list if it has queued cells.
67 * circuitmux_detach_circuit():
69 * Detach a circuit from the circuitmux, freeing associated structures.
71 * circuitmux_clear_num_cells():
73 * Clear the circuitmux's cell counter for this circuit.
75 * circuitmux_set_num_cells():
77 * Set the circuitmux's cell counter for this circuit.
79 * See circuitmux.h for the circuitmux_policy_t data structure, which contains
80 * a table of function pointers implementing a circuit selection policy, and
81 * circuitmux_ewma.c for an example of a circuitmux policy. Circuitmux
82 * policies can be manipulated with:
84 * circuitmux_get_policy():
86 * Return the current policy for a circuitmux_t, if any.
88 * circuitmux_clear_policy():
90 * Remove a policy installed on a circuitmux_t, freeing all associated
91 * data. The circuitmux will revert to the built-in round-robin behavior.
93 * circuitmux_set_policy():
95 * Install a policy on a circuitmux_t; the appropriate callbacks will be
96 * made to attach all existing circuits to the new policy.
100 struct circuitmux_s
{
101 /* Keep count of attached, active circuits */
102 unsigned int n_circuits
, n_active_circuits
;
104 /* Total number of queued cells on all circuits */
105 unsigned int n_cells
;
108 * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
110 chanid_circid_muxinfo_map_t
*chanid_circid_map
;
113 * Double-linked ring of circuits with queued cells waiting for room to
114 * free up on this connection's outbuf. Every time we pull cells from
115 * a circuit, we advance this pointer to the next circuit in the ring.
117 struct circuit_t
*active_circuits_head
, *active_circuits_tail
;
119 /** List of queued destroy cells */
120 cell_queue_t destroy_cell_queue
;
121 /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
122 * returned the destroy queue. Used to force alternation between
123 * destroy/non-destroy cells.
125 * XXXX There is no reason to think that alternating is a particularly good
126 * approach -- it's just designed to prevent destroys from starving other
129 unsigned int last_cell_was_destroy
: 1;
130 /** Destroy counter: increment this when a destroy gets queued, decrement
131 * when we unqueue it, so we can test to make sure they don't starve.
136 * Circuitmux policy; if this is non-NULL, it can override the built-
137 * in round-robin active circuits behavior. This is how EWMA works in
138 * the new circuitmux_t world.
140 const circuitmux_policy_t
*policy
;
142 /* Policy-specific data */
143 circuitmux_policy_data_t
*policy_data
;
147 * This struct holds whatever we want to store per attached circuit on a
148 * circuitmux_t; right now, just the count of queued cells and the direction.
151 struct circuit_muxinfo_s
{
152 /* Count of cells on this circuit at last update */
153 unsigned int cell_count
;
154 /* Direction of flow */
155 cell_direction_t direction
;
156 /* Policy-specific data */
157 circuitmux_policy_circ_data_t
*policy_data
;
158 /* Mark bit for consistency checker */
163 * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
167 struct chanid_circid_muxinfo_t
{
168 HT_ENTRY(chanid_circid_muxinfo_t
) node
;
171 circuit_muxinfo_t muxinfo
;
175 * Internal-use #defines
179 #define circuitmux_assert_okay_paranoid(cmux) \
180 circuitmux_assert_okay(cmux)
182 #define circuitmux_assert_okay_paranoid(cmux)
186 * Static function declarations
190 chanid_circid_entries_eq(chanid_circid_muxinfo_t
*a
,
191 chanid_circid_muxinfo_t
*b
);
192 static INLINE
unsigned int
193 chanid_circid_entry_hash(chanid_circid_muxinfo_t
*a
);
194 static chanid_circid_muxinfo_t
*
195 circuitmux_find_map_entry(circuitmux_t
*cmux
, circuit_t
*circ
);
197 circuitmux_make_circuit_active(circuitmux_t
*cmux
, circuit_t
*circ
,
198 cell_direction_t direction
);
200 circuitmux_make_circuit_inactive(circuitmux_t
*cmux
, circuit_t
*circ
,
201 cell_direction_t direction
);
203 circuitmux_move_active_circ_to_tail(circuitmux_t
*cmux
, circuit_t
*circ
,
204 cell_direction_t direction
);
205 static INLINE circuit_t
**
206 circuitmux_next_active_circ_p(circuitmux_t
*cmux
, circuit_t
*circ
);
207 static INLINE circuit_t
**
208 circuitmux_prev_active_circ_p(circuitmux_t
*cmux
, circuit_t
*circ
);
209 static void circuitmux_assert_okay_pass_one(circuitmux_t
*cmux
);
210 static void circuitmux_assert_okay_pass_two(circuitmux_t
*cmux
);
211 static void circuitmux_assert_okay_pass_three(circuitmux_t
*cmux
);
213 /* Static global variables */
215 /** Count the destroy balance to debug destroy queue logic */
216 static int64_t global_destroy_ctr
= 0;
218 /* Function definitions */
221 * Linked list helpers
225 * Move an active circuit to the tail of the cmux's active circuits list;
226 * used by circuitmux_notify_xmit_cells().
230 circuitmux_move_active_circ_to_tail(circuitmux_t
*cmux
, circuit_t
*circ
,
231 cell_direction_t direction
)
233 circuit_t
**next_p
= NULL
, **prev_p
= NULL
;
234 circuit_t
**next_prev
= NULL
, **prev_next
= NULL
;
235 circuit_t
**tail_next
= NULL
;
236 or_circuit_t
*or_circ
= NULL
;
241 circuitmux_assert_okay_paranoid(cmux
);
243 /* Figure out our next_p and prev_p for this cmux/direction */
245 if (direction
== CELL_DIRECTION_OUT
) {
246 tor_assert(circ
->n_mux
== cmux
);
247 next_p
= &(circ
->next_active_on_n_chan
);
248 prev_p
= &(circ
->prev_active_on_n_chan
);
250 or_circ
= TO_OR_CIRCUIT(circ
);
251 tor_assert(or_circ
->p_mux
== cmux
);
252 next_p
= &(or_circ
->next_active_on_p_chan
);
253 prev_p
= &(or_circ
->prev_active_on_p_chan
);
256 if (circ
->n_mux
== cmux
) {
257 next_p
= &(circ
->next_active_on_n_chan
);
258 prev_p
= &(circ
->prev_active_on_n_chan
);
259 direction
= CELL_DIRECTION_OUT
;
261 or_circ
= TO_OR_CIRCUIT(circ
);
262 tor_assert(or_circ
->p_mux
== cmux
);
263 next_p
= &(or_circ
->next_active_on_p_chan
);
264 prev_p
= &(or_circ
->prev_active_on_p_chan
);
265 direction
= CELL_DIRECTION_IN
;
271 /* Check if this really is an active circuit */
272 if ((*next_p
== NULL
&& *prev_p
== NULL
) &&
273 !(circ
== cmux
->active_circuits_head
||
274 circ
== cmux
->active_circuits_tail
)) {
275 /* Not active, no-op */
279 /* Check if this is already the tail */
280 if (circ
== cmux
->active_circuits_tail
) return;
282 /* Okay, we have to move it; figure out next_prev and prev_next */
283 if (*next_p
) next_prev
= circuitmux_prev_active_circ_p(cmux
, *next_p
);
284 if (*prev_p
) prev_next
= circuitmux_next_active_circ_p(cmux
, *prev_p
);
285 /* Adjust the previous node's next pointer, if any */
286 if (prev_next
) *prev_next
= *next_p
;
287 /* Otherwise, we were the head */
288 else cmux
->active_circuits_head
= *next_p
;
289 /* Adjust the next node's previous pointer, if any */
290 if (next_prev
) *next_prev
= *prev_p
;
291 /* We're out of the list; now re-attach at the tail */
292 /* Adjust our next and prev pointers */
294 *prev_p
= cmux
->active_circuits_tail
;
295 /* Set the next pointer of the tail, or the head if none */
296 if (cmux
->active_circuits_tail
) {
297 tail_next
= circuitmux_next_active_circ_p(cmux
,
298 cmux
->active_circuits_tail
);
301 cmux
->active_circuits_head
= circ
;
303 /* Set the tail to this circuit */
304 cmux
->active_circuits_tail
= circ
;
306 circuitmux_assert_okay_paranoid(cmux
);
309 static INLINE circuit_t
**
310 circuitmux_next_active_circ_p(circuitmux_t
*cmux
, circuit_t
*circ
)
315 if (circ
->n_mux
== cmux
) return &(circ
->next_active_on_n_chan
);
317 tor_assert(TO_OR_CIRCUIT(circ
)->p_mux
== cmux
);
318 return &(TO_OR_CIRCUIT(circ
)->next_active_on_p_chan
);
322 static INLINE circuit_t
**
323 circuitmux_prev_active_circ_p(circuitmux_t
*cmux
, circuit_t
*circ
)
328 if (circ
->n_mux
== cmux
) return &(circ
->prev_active_on_n_chan
);
330 tor_assert(TO_OR_CIRCUIT(circ
)->p_mux
== cmux
);
331 return &(TO_OR_CIRCUIT(circ
)->prev_active_on_p_chan
);
336 * Helper for chanid_circid_cell_count_map_t hash table: compare the channel
337 * ID and circuit ID for a and b, and return less than, equal to, or greater
338 * than zero appropriately.
342 chanid_circid_entries_eq(chanid_circid_muxinfo_t
*a
,
343 chanid_circid_muxinfo_t
*b
)
345 return a
->chan_id
== b
->chan_id
&& a
->circ_id
== b
->circ_id
;
349 * Helper: return a hash based on circuit ID and channel ID in a.
352 static INLINE
unsigned int
353 chanid_circid_entry_hash(chanid_circid_muxinfo_t
*a
)
355 return (((unsigned int)(a
->circ_id
) << 8) ^
356 ((unsigned int)((a
->chan_id
>> 32) & 0xffffffff)) ^
357 ((unsigned int)(a
->chan_id
& 0xffffffff)));
360 /* Declare the struct chanid_circid_muxinfo_map type */
361 HT_HEAD(chanid_circid_muxinfo_map
, chanid_circid_muxinfo_t
);
363 /* Emit a bunch of hash table stuff */
364 HT_PROTOTYPE(chanid_circid_muxinfo_map
, chanid_circid_muxinfo_t
, node
,
365 chanid_circid_entry_hash
, chanid_circid_entries_eq
);
366 HT_GENERATE(chanid_circid_muxinfo_map
, chanid_circid_muxinfo_t
, node
,
367 chanid_circid_entry_hash
, chanid_circid_entries_eq
, 0.6,
368 malloc
, realloc
, free
);
371 * Circuitmux alloc/free functions
375 * Allocate a new circuitmux_t
379 circuitmux_alloc(void)
381 circuitmux_t
*rv
= NULL
;
383 rv
= tor_malloc_zero(sizeof(*rv
));
384 rv
->chanid_circid_map
= tor_malloc_zero(sizeof(*( rv
->chanid_circid_map
)));
385 HT_INIT(chanid_circid_muxinfo_map
, rv
->chanid_circid_map
);
386 cell_queue_init(&rv
->destroy_cell_queue
);
392 * Detach all circuits from a circuitmux (use before circuitmux_free())
394 * If <b>detached_out</b> is non-NULL, add every detached circuit_t to
399 circuitmux_detach_all_circuits(circuitmux_t
*cmux
, smartlist_t
*detached_out
)
401 chanid_circid_muxinfo_t
**i
= NULL
, *to_remove
;
402 channel_t
*chan
= NULL
;
403 circuit_t
*circ
= NULL
;
407 * Don't circuitmux_assert_okay_paranoid() here; this gets called when
408 * channels are being freed and have already been unregistered, so
409 * the channel ID lookups it does will fail.
412 i
= HT_START(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
);
417 log_warn(LD_BUG
, "Somehow, an HT iterator gave us a NULL pointer.");
420 /* Find a channel and circuit */
421 chan
= channel_find_by_global_id(to_remove
->chan_id
);
424 circuit_get_by_circid_channel_even_if_marked(to_remove
->circ_id
,
427 /* Clear the circuit's mux for this direction */
428 if (to_remove
->muxinfo
.direction
== CELL_DIRECTION_OUT
) {
430 * Update active_circuits et al.; this does policy notifies, so
431 * comes before freeing policy data
434 if (to_remove
->muxinfo
.cell_count
> 0) {
435 circuitmux_make_circuit_inactive(cmux
, circ
, CELL_DIRECTION_OUT
);
442 smartlist_add(detached_out
, circ
);
443 } else if (circ
->magic
== OR_CIRCUIT_MAGIC
) {
445 * Update active_circuits et al.; this does policy notifies, so
446 * comes before freeing policy data
449 if (to_remove
->muxinfo
.cell_count
> 0) {
450 circuitmux_make_circuit_inactive(cmux
, circ
, CELL_DIRECTION_IN
);
454 * It has a sensible p_chan and direction == CELL_DIRECTION_IN,
457 TO_OR_CIRCUIT(circ
)->p_mux
= NULL
;
460 smartlist_add(detached_out
, circ
);
462 /* Complain and move on */
464 "Circuit %u/channel " U64_FORMAT
" had direction == "
465 "CELL_DIRECTION_IN, but isn't an or_circuit_t",
466 (unsigned)to_remove
->circ_id
,
467 U64_PRINTF_ARG(to_remove
->chan_id
));
470 /* Free policy-specific data if we have it */
471 if (to_remove
->muxinfo
.policy_data
) {
473 * If we have policy data, assert that we have the means to
476 tor_assert(cmux
->policy
);
477 tor_assert(cmux
->policy
->free_circ_data
);
478 /* Call free_circ_data() */
479 cmux
->policy
->free_circ_data(cmux
,
482 to_remove
->muxinfo
.policy_data
);
483 to_remove
->muxinfo
.policy_data
= NULL
;
486 /* Complain and move on */
488 "Couldn't find circuit %u (for channel " U64_FORMAT
")",
489 (unsigned)to_remove
->circ_id
,
490 U64_PRINTF_ARG(to_remove
->chan_id
));
493 /* Complain and move on */
495 "Couldn't find channel " U64_FORMAT
" (for circuit id %u)",
496 U64_PRINTF_ARG(to_remove
->chan_id
),
497 (unsigned)to_remove
->circ_id
);
500 /* Assert that we don't have un-freed policy data for this circuit */
501 tor_assert(to_remove
->muxinfo
.policy_data
== NULL
);
504 i
= HT_NEXT_RMV(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
, i
);
510 cmux
->n_circuits
= 0;
511 cmux
->n_active_circuits
= 0;
515 /** Reclaim all circuit IDs currently marked as unusable on <b>chan</b> because
516 * of pending destroy cells in <b>cmux</b>.
518 * This function must be called AFTER circuits are unlinked from the (channel,
519 * circuid-id) map with circuit_unlink_all_from_channel(), but before calling
523 circuitmux_mark_destroyed_circids_usable(circuitmux_t
*cmux
, channel_t
*chan
)
527 TOR_SIMPLEQ_FOREACH(cell
, &cmux
->destroy_cell_queue
.head
, next
) {
529 if (packed_cell_is_destroy(chan
, cell
, &circid
)) {
530 channel_mark_circid_usable(chan
, circid
);
536 log_warn(LD_BUG
, "%d cell(s) on destroy queue did not look like a "
537 "DESTROY cell.", n_bad
);
541 * Free a circuitmux_t; the circuits must be detached first with
542 * circuitmux_detach_all_circuits().
546 circuitmux_free(circuitmux_t
*cmux
)
550 tor_assert(cmux
->n_circuits
== 0);
551 tor_assert(cmux
->n_active_circuits
== 0);
554 * Free policy-specific data if we have any; we don't
555 * need to do circuitmux_set_policy(cmux, NULL) to cover
556 * the circuits because they would have been handled in
557 * circuitmux_detach_all_circuits() before this was
560 if (cmux
->policy
&& cmux
->policy
->free_cmux_data
) {
561 if (cmux
->policy_data
) {
562 cmux
->policy
->free_cmux_data(cmux
, cmux
->policy_data
);
563 cmux
->policy_data
= NULL
;
565 } else tor_assert(cmux
->policy_data
== NULL
);
567 if (cmux
->chanid_circid_map
) {
568 HT_CLEAR(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
);
569 tor_free(cmux
->chanid_circid_map
);
573 * We're throwing away some destroys; log the counter and
574 * adjust the global counter by the queue size.
576 if (cmux
->destroy_cell_queue
.n
> 0) {
577 cmux
->destroy_ctr
-= cmux
->destroy_cell_queue
.n
;
578 global_destroy_ctr
-= cmux
->destroy_cell_queue
.n
;
580 "Freeing cmux at %p with %u queued destroys; the last cmux "
581 "destroy balance was "I64_FORMAT
", global is "I64_FORMAT
,
582 cmux
, cmux
->destroy_cell_queue
.n
,
583 I64_PRINTF_ARG(cmux
->destroy_ctr
),
584 I64_PRINTF_ARG(global_destroy_ctr
));
587 "Freeing cmux at %p with no queued destroys, the cmux destroy "
588 "balance was "I64_FORMAT
", global is "I64_FORMAT
,
590 I64_PRINTF_ARG(cmux
->destroy_ctr
),
591 I64_PRINTF_ARG(global_destroy_ctr
));
594 cell_queue_clear(&cmux
->destroy_cell_queue
);
600 * Circuitmux policy control functions
604 * Remove any policy installed on cmux; all policy data will be freed and
605 * cmux behavior will revert to the built-in round-robin active_circuits
610 circuitmux_clear_policy(circuitmux_t
*cmux
)
614 /* Internally, this is just setting policy to NULL */
616 circuitmux_set_policy(cmux
, NULL
);
621 * Return the policy currently installed on a circuitmux_t
624 const circuitmux_policy_t
*
625 circuitmux_get_policy(circuitmux_t
*cmux
)
633 * Set policy; allocate for new policy, detach all circuits from old policy
634 * if any, attach them to new policy, and free old policy data.
638 circuitmux_set_policy(circuitmux_t
*cmux
,
639 const circuitmux_policy_t
*pol
)
641 const circuitmux_policy_t
*old_pol
= NULL
, *new_pol
= NULL
;
642 circuitmux_policy_data_t
*old_pol_data
= NULL
, *new_pol_data
= NULL
;
643 chanid_circid_muxinfo_t
**i
= NULL
;
644 channel_t
*chan
= NULL
;
645 uint64_t last_chan_id_searched
= 0;
646 circuit_t
*circ
= NULL
;
650 /* Set up variables */
651 old_pol
= cmux
->policy
;
652 old_pol_data
= cmux
->policy_data
;
655 /* Check if this is the trivial case */
656 if (old_pol
== new_pol
) return;
658 /* Allocate data for new policy, if any */
659 if (new_pol
&& new_pol
->alloc_cmux_data
) {
661 * If alloc_cmux_data is not null, then we expect to get some policy
662 * data. Assert that we also have free_cmux_data so we can free it
663 * when the time comes, and allocate it.
665 tor_assert(new_pol
->free_cmux_data
);
666 new_pol_data
= new_pol
->alloc_cmux_data(cmux
);
667 tor_assert(new_pol_data
);
670 /* Install new policy and new policy data on cmux */
671 cmux
->policy
= new_pol
;
672 cmux
->policy_data
= new_pol_data
;
674 /* Iterate over all circuits, attaching/detaching each one */
675 i
= HT_START(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
);
677 /* Assert that this entry isn't NULL */
681 * Get the channel; since normal case is all circuits on the mux share a
682 * channel, we cache last_chan_id_searched
684 if (!chan
|| last_chan_id_searched
!= (*i
)->chan_id
) {
685 chan
= channel_find_by_global_id((*i
)->chan_id
);
686 last_chan_id_searched
= (*i
)->chan_id
;
690 /* Get the circuit */
691 circ
= circuit_get_by_circid_channel_even_if_marked((*i
)->circ_id
, chan
);
694 /* Need to tell old policy it becomes inactive (i.e., it is active) ? */
695 if (old_pol
&& old_pol
->notify_circ_inactive
&&
696 (*i
)->muxinfo
.cell_count
> 0) {
697 old_pol
->notify_circ_inactive(cmux
, old_pol_data
, circ
,
698 (*i
)->muxinfo
.policy_data
);
701 /* Need to free old policy data? */
702 if ((*i
)->muxinfo
.policy_data
) {
703 /* Assert that we have the means to free it if we have policy data */
705 tor_assert(old_pol
->free_circ_data
);
707 old_pol
->free_circ_data(cmux
, old_pol_data
, circ
,
708 (*i
)->muxinfo
.policy_data
);
709 (*i
)->muxinfo
.policy_data
= NULL
;
712 /* Need to allocate new policy data? */
713 if (new_pol
&& new_pol
->alloc_circ_data
) {
715 * If alloc_circ_data is not null, we expect to get some per-circuit
716 * policy data. Assert that we also have free_circ_data so we can
717 * free it when the time comes, and allocate it.
719 tor_assert(new_pol
->free_circ_data
);
720 (*i
)->muxinfo
.policy_data
=
721 new_pol
->alloc_circ_data(cmux
, new_pol_data
, circ
,
722 (*i
)->muxinfo
.direction
,
723 (*i
)->muxinfo
.cell_count
);
726 /* Need to make active on new policy? */
727 if (new_pol
&& new_pol
->notify_circ_active
&&
728 (*i
)->muxinfo
.cell_count
> 0) {
729 new_pol
->notify_circ_active(cmux
, new_pol_data
, circ
,
730 (*i
)->muxinfo
.policy_data
);
733 /* Advance to next circuit map entry */
734 i
= HT_NEXT(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
, i
);
737 /* Free data for old policy, if any */
740 * If we had old policy data, we should have an old policy and a free
744 tor_assert(old_pol
->free_cmux_data
);
745 old_pol
->free_cmux_data(cmux
, old_pol_data
);
751 * Circuitmux/circuit attachment status inquiry functions
755 * Query the direction of an attached circuit
759 circuitmux_attached_circuit_direction(circuitmux_t
*cmux
, circuit_t
*circ
)
761 chanid_circid_muxinfo_t
*hashent
= NULL
;
763 /* Try to find a map entry */
764 hashent
= circuitmux_find_map_entry(cmux
, circ
);
767 * This function should only be called on attached circuits; assert that
768 * we had a map entry.
772 /* Return the direction from the map entry */
773 return hashent
->muxinfo
.direction
;
777 * Find an entry in the cmux's map for this circuit or return NULL if there
781 static chanid_circid_muxinfo_t
*
782 circuitmux_find_map_entry(circuitmux_t
*cmux
, circuit_t
*circ
)
784 chanid_circid_muxinfo_t search
, *hashent
= NULL
;
786 /* Sanity-check parameters */
788 tor_assert(cmux
->chanid_circid_map
);
791 /* Check if we have n_chan */
793 /* Okay, let's see if it's attached for n_chan/n_circ_id */
794 search
.chan_id
= circ
->n_chan
->global_identifier
;
795 search
.circ_id
= circ
->n_circ_id
;
798 hashent
= HT_FIND(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
802 /* Found something? */
805 * Assert that the direction makes sense for a hashent we found by
806 * n_chan/n_circ_id before we return it.
808 tor_assert(hashent
->muxinfo
.direction
== CELL_DIRECTION_OUT
);
810 /* Not there, have we got a p_chan/p_circ_id to try? */
811 if (circ
->magic
== OR_CIRCUIT_MAGIC
) {
812 search
.circ_id
= TO_OR_CIRCUIT(circ
)->p_circ_id
;
813 /* Check for p_chan */
814 if (TO_OR_CIRCUIT(circ
)->p_chan
) {
815 search
.chan_id
= TO_OR_CIRCUIT(circ
)->p_chan
->global_identifier
;
816 /* Okay, search for that */
817 hashent
= HT_FIND(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
821 /* Assert that the direction makes sense before we return it */
822 tor_assert(hashent
->muxinfo
.direction
== CELL_DIRECTION_IN
);
828 /* Okay, hashent is it if it was there */
833 * Query whether a circuit is attached to a circuitmux
837 circuitmux_is_circuit_attached(circuitmux_t
*cmux
, circuit_t
*circ
)
839 chanid_circid_muxinfo_t
*hashent
= NULL
;
841 /* Look if it's in the circuit map */
842 hashent
= circuitmux_find_map_entry(cmux
, circ
);
844 return (hashent
!= NULL
);
848 * Query whether a circuit is active on a circuitmux
852 circuitmux_is_circuit_active(circuitmux_t
*cmux
, circuit_t
*circ
)
854 chanid_circid_muxinfo_t
*hashent
= NULL
;
860 /* Look if it's in the circuit map */
861 hashent
= circuitmux_find_map_entry(cmux
, circ
);
863 /* Check the number of cells on this circuit */
864 is_active
= (hashent
->muxinfo
.cell_count
> 0);
866 /* else not attached, so not active */
872 * Query number of available cells for a circuit on a circuitmux
876 circuitmux_num_cells_for_circuit(circuitmux_t
*cmux
, circuit_t
*circ
)
878 chanid_circid_muxinfo_t
*hashent
= NULL
;
879 unsigned int n_cells
= 0;
884 /* Look if it's in the circuit map */
885 hashent
= circuitmux_find_map_entry(cmux
, circ
);
887 /* Just get the cell count for this circuit */
888 n_cells
= hashent
->muxinfo
.cell_count
;
890 /* else not attached, so 0 cells */
896 * Query total number of available cells on a circuitmux
900 circuitmux_num_cells(circuitmux_t
*cmux
)
904 return cmux
->n_cells
+ cmux
->destroy_cell_queue
.n
;
908 * Query total number of circuits active on a circuitmux
912 circuitmux_num_active_circuits(circuitmux_t
*cmux
)
916 return cmux
->n_active_circuits
;
920 * Query total number of circuits attached to a circuitmux
924 circuitmux_num_circuits(circuitmux_t
*cmux
)
928 return cmux
->n_circuits
;
932 * Functions for circuit code to call to update circuit status
936 * Attach a circuit to a circuitmux, for the specified direction.
940 circuitmux_attach_circuit
,(circuitmux_t
*cmux
, circuit_t
*circ
,
941 cell_direction_t direction
))
943 channel_t
*chan
= NULL
;
946 chanid_circid_muxinfo_t search
, *hashent
= NULL
;
947 unsigned int cell_count
;
951 tor_assert(direction
== CELL_DIRECTION_IN
||
952 direction
== CELL_DIRECTION_OUT
);
953 circuitmux_assert_okay_paranoid(cmux
);
956 * Figure out which channel we're using, and get the circuit's current
957 * cell count and circuit ID; assert that the circuit is not already
958 * attached to another mux.
960 if (direction
== CELL_DIRECTION_OUT
) {
963 cell_count
= circ
->n_chan_cells
.n
;
964 circ_id
= circ
->n_circ_id
;
967 chan
= TO_OR_CIRCUIT(circ
)->p_chan
;
968 cell_count
= TO_OR_CIRCUIT(circ
)->p_chan_cells
.n
;
969 circ_id
= TO_OR_CIRCUIT(circ
)->p_circ_id
;
971 /* Assert that we did get a channel */
973 /* Assert that the circuit ID is sensible */
974 tor_assert(circ_id
!= 0);
976 /* Get the channel ID */
977 channel_id
= chan
->global_identifier
;
979 /* See if we already have this one */
980 search
.chan_id
= channel_id
;
981 search
.circ_id
= circ_id
;
982 hashent
= HT_FIND(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
987 * This circuit was already attached to this cmux; make sure the
988 * directions match and update the cell count and active circuit count.
991 "Circuit %u on channel " U64_FORMAT
" was already attached to "
992 "cmux %p (trying to attach to %p)",
993 (unsigned)circ_id
, U64_PRINTF_ARG(channel_id
),
994 ((direction
== CELL_DIRECTION_OUT
) ?
995 circ
->n_mux
: TO_OR_CIRCUIT(circ
)->p_mux
),
999 * The mux pointer on this circuit and the direction in result should
1000 * match; otherwise assert.
1002 if (direction
== CELL_DIRECTION_OUT
) tor_assert(circ
->n_mux
== cmux
);
1003 else tor_assert(TO_OR_CIRCUIT(circ
)->p_mux
== cmux
);
1004 tor_assert(hashent
->muxinfo
.direction
== direction
);
1007 * Looks okay; just update the cell count and active circuits if we must
1009 if (hashent
->muxinfo
.cell_count
> 0 && cell_count
== 0) {
1010 --(cmux
->n_active_circuits
);
1011 circuitmux_make_circuit_inactive(cmux
, circ
, direction
);
1012 } else if (hashent
->muxinfo
.cell_count
== 0 && cell_count
> 0) {
1013 ++(cmux
->n_active_circuits
);
1014 circuitmux_make_circuit_active(cmux
, circ
, direction
);
1016 cmux
->n_cells
-= hashent
->muxinfo
.cell_count
;
1017 cmux
->n_cells
+= cell_count
;
1018 hashent
->muxinfo
.cell_count
= cell_count
;
1021 * New circuit; add an entry and update the circuit/active circuit
1025 "Attaching circuit %u on channel " U64_FORMAT
" to cmux %p",
1026 (unsigned)circ_id
, U64_PRINTF_ARG(channel_id
), cmux
);
1029 * Assert that the circuit doesn't already have a mux for this
1032 if (direction
== CELL_DIRECTION_OUT
) tor_assert(circ
->n_mux
== NULL
);
1033 else tor_assert(TO_OR_CIRCUIT(circ
)->p_mux
== NULL
);
1035 /* Insert it in the map */
1036 hashent
= tor_malloc_zero(sizeof(*hashent
));
1037 hashent
->chan_id
= channel_id
;
1038 hashent
->circ_id
= circ_id
;
1039 hashent
->muxinfo
.cell_count
= cell_count
;
1040 hashent
->muxinfo
.direction
= direction
;
1041 /* Allocate policy specific circuit data if we need it */
1042 if (cmux
->policy
&& cmux
->policy
->alloc_circ_data
) {
1043 /* Assert that we have the means to free policy-specific data */
1044 tor_assert(cmux
->policy
->free_circ_data
);
1046 hashent
->muxinfo
.policy_data
=
1047 cmux
->policy
->alloc_circ_data(cmux
,
1052 /* If we wanted policy data, it's an error not to get any */
1053 tor_assert(hashent
->muxinfo
.policy_data
);
1055 HT_INSERT(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
1058 /* Set the circuit's mux for this direction */
1059 if (direction
== CELL_DIRECTION_OUT
) circ
->n_mux
= cmux
;
1060 else TO_OR_CIRCUIT(circ
)->p_mux
= cmux
;
1062 /* Make sure the next/prev pointers are NULL */
1063 if (direction
== CELL_DIRECTION_OUT
) {
1064 circ
->next_active_on_n_chan
= NULL
;
1065 circ
->prev_active_on_n_chan
= NULL
;
1067 TO_OR_CIRCUIT(circ
)->next_active_on_p_chan
= NULL
;
1068 TO_OR_CIRCUIT(circ
)->prev_active_on_p_chan
= NULL
;
1071 /* Update counters */
1072 ++(cmux
->n_circuits
);
1073 if (cell_count
> 0) {
1074 ++(cmux
->n_active_circuits
);
1075 circuitmux_make_circuit_active(cmux
, circ
, direction
);
1077 cmux
->n_cells
+= cell_count
;
1080 circuitmux_assert_okay_paranoid(cmux
);
1084 * Detach a circuit from a circuitmux and update all counters as needed;
1085 * no-op if not attached.
1089 circuitmux_detach_circuit
,(circuitmux_t
*cmux
, circuit_t
*circ
))
1091 chanid_circid_muxinfo_t search
, *hashent
= NULL
;
1093 * Use this to keep track of whether we found it for n_chan or
1094 * p_chan for consistency checking.
1096 * The 0 initializer is not a valid cell_direction_t value.
1097 * We assert that it has been replaced with a valid value before it is used.
1099 cell_direction_t last_searched_direction
= 0;
1102 tor_assert(cmux
->chanid_circid_map
);
1104 circuitmux_assert_okay_paranoid(cmux
);
1106 /* See if we have it for n_chan/n_circ_id */
1108 search
.chan_id
= circ
->n_chan
->global_identifier
;
1109 search
.circ_id
= circ
->n_circ_id
;
1110 hashent
= HT_FIND(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
1112 last_searched_direction
= CELL_DIRECTION_OUT
;
1115 /* Got one? If not, see if it's an or_circuit_t and try p_chan/p_circ_id */
1117 if (circ
->magic
== OR_CIRCUIT_MAGIC
) {
1118 search
.circ_id
= TO_OR_CIRCUIT(circ
)->p_circ_id
;
1119 if (TO_OR_CIRCUIT(circ
)->p_chan
) {
1120 search
.chan_id
= TO_OR_CIRCUIT(circ
)->p_chan
->global_identifier
;
1121 hashent
= HT_FIND(chanid_circid_muxinfo_map
,
1122 cmux
->chanid_circid_map
,
1124 last_searched_direction
= CELL_DIRECTION_IN
;
1129 tor_assert(last_searched_direction
== CELL_DIRECTION_OUT
1130 || last_searched_direction
== CELL_DIRECTION_IN
);
1133 * If hashent isn't NULL, we have a circuit to detach; don't remove it from
1134 * the map until later of circuitmux_make_circuit_inactive() breaks.
1137 /* Update counters */
1138 --(cmux
->n_circuits
);
1139 if (hashent
->muxinfo
.cell_count
> 0) {
1140 --(cmux
->n_active_circuits
);
1141 /* This does policy notifies, so comes before freeing policy data */
1142 circuitmux_make_circuit_inactive(cmux
, circ
, last_searched_direction
);
1144 cmux
->n_cells
-= hashent
->muxinfo
.cell_count
;
1146 /* Free policy-specific data if we have it */
1147 if (hashent
->muxinfo
.policy_data
) {
1148 /* If we have policy data, assert that we have the means to free it */
1149 tor_assert(cmux
->policy
);
1150 tor_assert(cmux
->policy
->free_circ_data
);
1151 /* Call free_circ_data() */
1152 cmux
->policy
->free_circ_data(cmux
,
1155 hashent
->muxinfo
.policy_data
);
1156 hashent
->muxinfo
.policy_data
= NULL
;
1159 /* Consistency check: the direction must match the direction searched */
1160 tor_assert(last_searched_direction
== hashent
->muxinfo
.direction
);
1161 /* Clear the circuit's mux for this direction */
1162 if (last_searched_direction
== CELL_DIRECTION_OUT
) circ
->n_mux
= NULL
;
1163 else TO_OR_CIRCUIT(circ
)->p_mux
= NULL
;
1165 /* Now remove it from the map */
1166 HT_REMOVE(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
, hashent
);
1168 /* Free the hash entry */
1172 circuitmux_assert_okay_paranoid(cmux
);
1176 * Make a circuit active; update active list and policy-specific info, but
1177 * we don't mess with the counters or hash table here.
1181 circuitmux_make_circuit_active(circuitmux_t
*cmux
, circuit_t
*circ
,
1182 cell_direction_t direction
)
1184 circuit_t
**next_active
= NULL
, **prev_active
= NULL
, **next_prev
= NULL
;
1185 circuitmux_t
*circuit_cmux
= NULL
;
1186 chanid_circid_muxinfo_t
*hashent
= NULL
;
1187 channel_t
*chan
= NULL
;
1193 tor_assert(direction
== CELL_DIRECTION_OUT
||
1194 direction
== CELL_DIRECTION_IN
);
1196 * Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count
1197 * already got changed and we have to update the list for it to be consistent
1201 /* Get the right set of active list links for this direction */
1202 if (direction
== CELL_DIRECTION_OUT
) {
1203 next_active
= &(circ
->next_active_on_n_chan
);
1204 prev_active
= &(circ
->prev_active_on_n_chan
);
1205 circuit_cmux
= circ
->n_mux
;
1206 chan
= circ
->n_chan
;
1207 circ_id
= circ
->n_circ_id
;
1209 next_active
= &(TO_OR_CIRCUIT(circ
)->next_active_on_p_chan
);
1210 prev_active
= &(TO_OR_CIRCUIT(circ
)->prev_active_on_p_chan
);
1211 circuit_cmux
= TO_OR_CIRCUIT(circ
)->p_mux
;
1212 chan
= TO_OR_CIRCUIT(circ
)->p_chan
;
1213 circ_id
= TO_OR_CIRCUIT(circ
)->p_circ_id
;
1216 /* Assert that it is attached to this mux and a channel */
1217 tor_assert(cmux
== circuit_cmux
);
1218 tor_assert(chan
!= NULL
);
1221 * Check if the circuit really was inactive; if it's active, at least one
1222 * of the next_active and prev_active pointers will not be NULL, or this
1223 * circuit will be either the head or tail of the list for this cmux.
1225 already_active
= (*prev_active
!= NULL
|| *next_active
!= NULL
||
1226 cmux
->active_circuits_head
== circ
||
1227 cmux
->active_circuits_tail
== circ
);
1229 /* If we're already active, log a warning and finish */
1230 if (already_active
) {
1232 "Circuit %u on channel " U64_FORMAT
" was already active",
1233 (unsigned)circ_id
, U64_PRINTF_ARG(chan
->global_identifier
));
1238 * This is going at the head of the list; if the old head is not NULL,
1239 * then its prev pointer should point to this.
1241 *next_active
= cmux
->active_circuits_head
; /* Next is old head */
1242 *prev_active
= NULL
; /* Prev is NULL (this will be the head) */
1243 if (cmux
->active_circuits_head
) {
1244 /* The list had an old head; update its prev pointer */
1246 circuitmux_prev_active_circ_p(cmux
, cmux
->active_circuits_head
);
1247 tor_assert(next_prev
);
1250 /* The list was empty; this becomes the tail as well */
1251 cmux
->active_circuits_tail
= circ
;
1253 /* This becomes the new head of the list */
1254 cmux
->active_circuits_head
= circ
;
1256 /* Policy-specific notification */
1258 cmux
->policy
->notify_circ_active
) {
1259 /* Okay, we need to check the circuit for policy data now */
1260 hashent
= circuitmux_find_map_entry(cmux
, circ
);
1261 /* We should have found something */
1262 tor_assert(hashent
);
1264 cmux
->policy
->notify_circ_active(cmux
, cmux
->policy_data
,
1265 circ
, hashent
->muxinfo
.policy_data
);
1268 circuitmux_assert_okay_paranoid(cmux
);
1272 * Make a circuit inactive; update active list and policy-specific info, but
1273 * we don't mess with the counters or hash table here.
1277 circuitmux_make_circuit_inactive(circuitmux_t
*cmux
, circuit_t
*circ
,
1278 cell_direction_t direction
)
1280 circuit_t
**next_active
= NULL
, **prev_active
= NULL
;
1281 circuit_t
**next_prev
= NULL
, **prev_next
= NULL
;
1282 circuitmux_t
*circuit_cmux
= NULL
;
1283 chanid_circid_muxinfo_t
*hashent
= NULL
;
1284 channel_t
*chan
= NULL
;
1286 int already_inactive
;
1290 tor_assert(direction
== CELL_DIRECTION_OUT
||
1291 direction
== CELL_DIRECTION_IN
);
1293 * Don't circuitmux_assert_okay_paranoid(cmux) here because the cell count
1294 * already got changed and we have to update the list for it to be consistent
1298 /* Get the right set of active list links for this direction */
1299 if (direction
== CELL_DIRECTION_OUT
) {
1300 next_active
= &(circ
->next_active_on_n_chan
);
1301 prev_active
= &(circ
->prev_active_on_n_chan
);
1302 circuit_cmux
= circ
->n_mux
;
1303 chan
= circ
->n_chan
;
1304 circ_id
= circ
->n_circ_id
;
1306 next_active
= &(TO_OR_CIRCUIT(circ
)->next_active_on_p_chan
);
1307 prev_active
= &(TO_OR_CIRCUIT(circ
)->prev_active_on_p_chan
);
1308 circuit_cmux
= TO_OR_CIRCUIT(circ
)->p_mux
;
1309 chan
= TO_OR_CIRCUIT(circ
)->p_chan
;
1310 circ_id
= TO_OR_CIRCUIT(circ
)->p_circ_id
;
1313 /* Assert that it is attached to this mux and a channel */
1314 tor_assert(cmux
== circuit_cmux
);
1315 tor_assert(chan
!= NULL
);
1318 * Check if the circuit really was active; if it's inactive, the
1319 * next_active and prev_active pointers will be NULL and this circuit
1320 * will not be the head or tail of the list for this cmux.
1322 already_inactive
= (*prev_active
== NULL
&& *next_active
== NULL
&&
1323 cmux
->active_circuits_head
!= circ
&&
1324 cmux
->active_circuits_tail
!= circ
);
1326 /* If we're already inactive, log a warning and finish */
1327 if (already_inactive
) {
1329 "Circuit %d on channel " U64_FORMAT
" was already inactive",
1330 (unsigned)circ_id
, U64_PRINTF_ARG(chan
->global_identifier
));
1334 /* Remove from the list; first get next_prev and prev_next */
1337 * If there's a next circuit, its previous circuit becomes this
1338 * circuit's previous circuit.
1340 next_prev
= circuitmux_prev_active_circ_p(cmux
, *next_active
);
1342 /* Else, the tail becomes this circuit's previous circuit */
1343 next_prev
= &(cmux
->active_circuits_tail
);
1346 /* Got next_prev, now prev_next */
1349 * If there's a previous circuit, its next circuit becomes this circuit's
1352 prev_next
= circuitmux_next_active_circ_p(cmux
, *prev_active
);
1354 /* Else, the head becomes this circuit's next circuit */
1355 prev_next
= &(cmux
->active_circuits_head
);
1358 /* Assert that we got sensible values for the next/prev pointers */
1359 tor_assert(next_prev
!= NULL
);
1360 tor_assert(prev_next
!= NULL
);
1362 /* Update the next/prev pointers - this removes circ from the list */
1363 *next_prev
= *prev_active
;
1364 *prev_next
= *next_active
;
1366 /* Now null out prev_active/next_active */
1367 *prev_active
= NULL
;
1368 *next_active
= NULL
;
1370 /* Policy-specific notification */
1372 cmux
->policy
->notify_circ_inactive
) {
1373 /* Okay, we need to check the circuit for policy data now */
1374 hashent
= circuitmux_find_map_entry(cmux
, circ
);
1375 /* We should have found something */
1376 tor_assert(hashent
);
1378 cmux
->policy
->notify_circ_inactive(cmux
, cmux
->policy_data
,
1379 circ
, hashent
->muxinfo
.policy_data
);
1382 circuitmux_assert_okay_paranoid(cmux
);
1386 * Clear the cell counter for a circuit on a circuitmux
1390 circuitmux_clear_num_cells(circuitmux_t
*cmux
, circuit_t
*circ
)
1392 /* This is the same as setting the cell count to zero */
1393 circuitmux_set_num_cells(cmux
, circ
, 0);
1397 * Set the cell counter for a circuit on a circuitmux
1401 circuitmux_set_num_cells(circuitmux_t
*cmux
, circuit_t
*circ
,
1402 unsigned int n_cells
)
1404 chanid_circid_muxinfo_t
*hashent
= NULL
;
1409 circuitmux_assert_okay_paranoid(cmux
);
1411 /* Search for this circuit's entry */
1412 hashent
= circuitmux_find_map_entry(cmux
, circ
);
1413 /* Assert that we found one */
1414 tor_assert(hashent
);
1416 /* Update cmux cell counter */
1417 cmux
->n_cells
-= hashent
->muxinfo
.cell_count
;
1418 cmux
->n_cells
+= n_cells
;
1420 /* Do we need to notify a cmux policy? */
1421 if (cmux
->policy
&& cmux
->policy
->notify_set_n_cells
) {
1422 /* Call notify_set_n_cells */
1423 cmux
->policy
->notify_set_n_cells(cmux
,
1426 hashent
->muxinfo
.policy_data
,
1431 * Update cmux active circuit counter: is the old cell count > 0 and the
1432 * new cell count == 0 ?
1434 if (hashent
->muxinfo
.cell_count
> 0 && n_cells
== 0) {
1435 --(cmux
->n_active_circuits
);
1436 hashent
->muxinfo
.cell_count
= n_cells
;
1437 circuitmux_make_circuit_inactive(cmux
, circ
, hashent
->muxinfo
.direction
);
1438 /* Is the old cell count == 0 and the new cell count > 0 ? */
1439 } else if (hashent
->muxinfo
.cell_count
== 0 && n_cells
> 0) {
1440 ++(cmux
->n_active_circuits
);
1441 hashent
->muxinfo
.cell_count
= n_cells
;
1442 circuitmux_make_circuit_active(cmux
, circ
, hashent
->muxinfo
.direction
);
1445 * Update the entry cell count like this so we can put a
1446 * circuitmux_assert_okay_paranoid inside make_circuit_(in)active() too.
1448 hashent
->muxinfo
.cell_count
= n_cells
;
1451 circuitmux_assert_okay_paranoid(cmux
);
1455 * Functions for channel code to call to get a circuit to transmit from or
1456 * notify that cells have been transmitted.
1460 * Pick a circuit to send from, using the active circuits list or a
1461 * circuitmux policy if one is available. This is called from channel.c.
1463 * If we would rather send a destroy cell, return NULL and set
1464 * *<b>destroy_queue_out</b> to the destroy queue.
1466 * If we have nothing to send, set *<b>destroy_queue_out</b> to NULL and
1471 circuitmux_get_first_active_circuit(circuitmux_t
*cmux
,
1472 cell_queue_t
**destroy_queue_out
)
1474 circuit_t
*circ
= NULL
;
1477 tor_assert(destroy_queue_out
);
1479 *destroy_queue_out
= NULL
;
1481 if (cmux
->destroy_cell_queue
.n
&&
1482 (!cmux
->last_cell_was_destroy
|| cmux
->n_active_circuits
== 0)) {
1483 /* We have destroy cells to send, and either we just sent a relay cell,
1484 * or we have no relay cells to send. */
1486 /* XXXX We should let the cmux policy have some say in this eventually. */
1487 /* XXXX Alternating is not a terribly brilliant approach here. */
1488 *destroy_queue_out
= &cmux
->destroy_cell_queue
;
1490 cmux
->last_cell_was_destroy
= 1;
1491 } else if (cmux
->n_active_circuits
> 0) {
1492 /* We also must have a cell available for this to be the case */
1493 tor_assert(cmux
->n_cells
> 0);
1494 /* Do we have a policy-provided circuit selector? */
1495 if (cmux
->policy
&& cmux
->policy
->pick_active_circuit
) {
1496 circ
= cmux
->policy
->pick_active_circuit(cmux
, cmux
->policy_data
);
1498 /* Fall back on the head of the active circuits list */
1500 tor_assert(cmux
->active_circuits_head
);
1501 circ
= cmux
->active_circuits_head
;
1503 cmux
->last_cell_was_destroy
= 0;
1505 tor_assert(cmux
->n_cells
== 0);
1506 tor_assert(cmux
->destroy_cell_queue
.n
== 0);
1513 * Notify the circuitmux that cells have been sent on a circuit; this
1514 * is called from channel.c.
1518 circuitmux_notify_xmit_cells(circuitmux_t
*cmux
, circuit_t
*circ
,
1519 unsigned int n_cells
)
1521 chanid_circid_muxinfo_t
*hashent
= NULL
;
1522 int becomes_inactive
= 0;
1526 circuitmux_assert_okay_paranoid(cmux
);
1528 if (n_cells
== 0) return;
1531 * To handle this, we have to:
1533 * 1.) Adjust the circuit's cell counter in the cmux hash table
1534 * 2.) Move the circuit to the tail of the active_circuits linked list
1535 * for this cmux, or make the circuit inactive if the cell count
1537 * 3.) Call cmux->policy->notify_xmit_cells(), if any
1540 /* Find the hash entry */
1541 hashent
= circuitmux_find_map_entry(cmux
, circ
);
1542 /* Assert that we found one */
1543 tor_assert(hashent
);
1545 /* Adjust the cell counter and assert that we had that many cells to send */
1546 tor_assert(n_cells
<= hashent
->muxinfo
.cell_count
);
1547 hashent
->muxinfo
.cell_count
-= n_cells
;
1548 /* Do we need to make the circuit inactive? */
1549 if (hashent
->muxinfo
.cell_count
== 0) becomes_inactive
= 1;
1550 /* Adjust the mux cell counter */
1551 cmux
->n_cells
-= n_cells
;
1553 /* If we aren't making it inactive later, move it to the tail of the list */
1554 if (!becomes_inactive
) {
1555 circuitmux_move_active_circ_to_tail(cmux
, circ
,
1556 hashent
->muxinfo
.direction
);
1560 * We call notify_xmit_cells() before making the circuit inactive if needed,
1561 * so the policy can always count on this coming in on an active circuit.
1563 if (cmux
->policy
&& cmux
->policy
->notify_xmit_cells
) {
1564 cmux
->policy
->notify_xmit_cells(cmux
, cmux
->policy_data
, circ
,
1565 hashent
->muxinfo
.policy_data
,
1570 * Now make the circuit inactive if needed; this will call the policy's
1571 * notify_circ_inactive() if present.
1573 if (becomes_inactive
) {
1574 --(cmux
->n_active_circuits
);
1575 circuitmux_make_circuit_inactive(cmux
, circ
, hashent
->muxinfo
.direction
);
1578 circuitmux_assert_okay_paranoid(cmux
);
1582 * Notify the circuitmux that a destroy was sent, so we can update
1587 circuitmux_notify_xmit_destroy(circuitmux_t
*cmux
)
1591 --(cmux
->destroy_ctr
);
1592 --(global_destroy_ctr
);
1594 "Cmux at %p sent a destroy, cmux counter is now "I64_FORMAT
", "
1595 "global counter is now "I64_FORMAT
,
1597 I64_PRINTF_ARG(cmux
->destroy_ctr
),
1598 I64_PRINTF_ARG(global_destroy_ctr
));
1602 * Circuitmux consistency checking assertions
1606 * Check that circuitmux data structures are consistent and fail with an
1611 circuitmux_assert_okay(circuitmux_t
*cmux
)
1616 * Pass 1: iterate the hash table; for each entry:
1617 * a) Check that the circuit has this cmux for n_mux or p_mux
1618 * b) If the cell_count is > 0, set the mark bit; otherwise clear it
1619 * c) Also check activeness (cell_count > 0 should be active)
1620 * d) Count the number of circuits, active circuits and queued cells
1621 * and at the end check that they match the counters in the cmux.
1623 * Pass 2: iterate the active circuits list; for each entry,
1624 * make sure the circuit is attached to this mux and appears
1625 * in the hash table. Make sure the mark bit is 1, and clear
1626 * it in the hash table entry. Consistency-check the linked
1629 * Pass 3: iterate the hash table again; assert if any active circuits
1630 * (mark bit set to 1) are discovered that weren't cleared in pass 2
1631 * (don't appear in the linked list).
1634 circuitmux_assert_okay_pass_one(cmux
);
1635 circuitmux_assert_okay_pass_two(cmux
);
1636 circuitmux_assert_okay_pass_three(cmux
);
1640 * Do the first pass of circuitmux_assert_okay(); see the comment in that
1645 circuitmux_assert_okay_pass_one(circuitmux_t
*cmux
)
1647 chanid_circid_muxinfo_t
**i
= NULL
;
1652 or_circuit_t
*or_circ
;
1653 unsigned int circ_is_active
;
1654 circuit_t
**next_p
, **prev_p
;
1655 unsigned int n_circuits
, n_active_circuits
, n_cells
;
1658 tor_assert(cmux
->chanid_circid_map
);
1660 /* Reset the counters */
1661 n_circuits
= n_active_circuits
= n_cells
= 0;
1662 /* Start iterating the hash table */
1663 i
= HT_START(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
);
1665 /* Assert that the hash table entry isn't null */
1668 /* Get the channel and circuit id */
1669 chan_id
= (*i
)->chan_id
;
1670 circ_id
= (*i
)->circ_id
;
1672 /* Find the channel and circuit, assert that they exist */
1673 chan
= channel_find_by_global_id(chan_id
);
1675 circ
= circuit_get_by_circid_channel_even_if_marked(circ_id
, chan
);
1677 /* Clear the circ_is_active bit to start */
1680 /* Assert that we know which direction this is going */
1681 tor_assert((*i
)->muxinfo
.direction
== CELL_DIRECTION_OUT
||
1682 (*i
)->muxinfo
.direction
== CELL_DIRECTION_IN
);
1684 if ((*i
)->muxinfo
.direction
== CELL_DIRECTION_OUT
) {
1685 /* We should be n_mux on this circuit */
1686 tor_assert(cmux
== circ
->n_mux
);
1687 tor_assert(chan
== circ
->n_chan
);
1688 /* Get next and prev for next test */
1689 next_p
= &(circ
->next_active_on_n_chan
);
1690 prev_p
= &(circ
->prev_active_on_n_chan
);
1692 /* This should be an or_circuit_t and we should be p_mux */
1693 or_circ
= TO_OR_CIRCUIT(circ
);
1694 tor_assert(cmux
== or_circ
->p_mux
);
1695 tor_assert(chan
== or_circ
->p_chan
);
1696 /* Get next and prev for next test */
1697 next_p
= &(or_circ
->next_active_on_p_chan
);
1698 prev_p
= &(or_circ
->prev_active_on_p_chan
);
1702 * Should this circuit be active? I.e., does the mux know about > 0
1705 circ_is_active
= ((*i
)->muxinfo
.cell_count
> 0);
1707 /* It should be in the linked list iff it's active */
1708 if (circ_is_active
) {
1709 /* Either we have a next link or we are the tail */
1710 tor_assert(*next_p
|| (circ
== cmux
->active_circuits_tail
));
1711 /* Either we have a prev link or we are the head */
1712 tor_assert(*prev_p
|| (circ
== cmux
->active_circuits_head
));
1713 /* Increment the active circuits counter */
1714 ++n_active_circuits
;
1716 /* Shouldn't be in list, so no next or prev link */
1717 tor_assert(!(*next_p
));
1718 tor_assert(!(*prev_p
));
1719 /* And can't be head or tail */
1720 tor_assert(circ
!= cmux
->active_circuits_head
);
1721 tor_assert(circ
!= cmux
->active_circuits_tail
);
1724 /* Increment the circuits counter */
1726 /* Adjust the cell counter */
1727 n_cells
+= (*i
)->muxinfo
.cell_count
;
1729 /* Set the mark bit to circ_is_active */
1730 (*i
)->muxinfo
.mark
= circ_is_active
;
1732 /* Advance to the next entry */
1733 i
= HT_NEXT(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
, i
);
1736 /* Now check the counters */
1737 tor_assert(n_cells
== cmux
->n_cells
);
1738 tor_assert(n_circuits
== cmux
->n_circuits
);
1739 tor_assert(n_active_circuits
== cmux
->n_active_circuits
);
1743 * Do the second pass of circuitmux_assert_okay(); see the comment in that
1748 circuitmux_assert_okay_pass_two(circuitmux_t
*cmux
)
1750 circuit_t
*curr_circ
, *prev_circ
= NULL
, *next_circ
;
1751 or_circuit_t
*curr_or_circ
;
1752 uint64_t curr_chan_id
;
1753 circid_t curr_circ_id
;
1754 circuit_t
**next_p
, **prev_p
;
1756 unsigned int n_active_circuits
= 0;
1757 cell_direction_t direction
;
1758 chanid_circid_muxinfo_t search
, *hashent
= NULL
;
1761 tor_assert(cmux
->chanid_circid_map
);
1764 * Walk the linked list of active circuits in cmux; keep track of the
1765 * previous circuit seen for consistency checking purposes. Count them
1766 * to make sure the number in the linked list matches
1767 * cmux->n_active_circuits.
1769 curr_circ
= cmux
->active_circuits_head
;
1771 /* Reset some things */
1773 curr_or_circ
= NULL
;
1775 next_p
= prev_p
= NULL
;
1778 /* Figure out if this is n_mux or p_mux */
1779 if (cmux
== curr_circ
->n_mux
) {
1780 /* Get next_p and prev_p */
1781 next_p
= &(curr_circ
->next_active_on_n_chan
);
1782 prev_p
= &(curr_circ
->prev_active_on_n_chan
);
1783 /* Get the channel */
1784 chan
= curr_circ
->n_chan
;
1785 /* Get the circuit id */
1786 curr_circ_id
= curr_circ
->n_circ_id
;
1787 /* Remember the direction */
1788 direction
= CELL_DIRECTION_OUT
;
1790 /* We must be p_mux and this must be an or_circuit_t */
1791 curr_or_circ
= TO_OR_CIRCUIT(curr_circ
);
1792 tor_assert(cmux
== curr_or_circ
->p_mux
);
1793 /* Get next_p and prev_p */
1794 next_p
= &(curr_or_circ
->next_active_on_p_chan
);
1795 prev_p
= &(curr_or_circ
->prev_active_on_p_chan
);
1796 /* Get the channel */
1797 chan
= curr_or_circ
->p_chan
;
1798 /* Get the circuit id */
1799 curr_circ_id
= curr_or_circ
->p_circ_id
;
1800 /* Remember the direction */
1801 direction
= CELL_DIRECTION_IN
;
1804 /* Assert that we got a channel and get the channel ID */
1806 curr_chan_id
= chan
->global_identifier
;
1808 /* Assert that prev_p points to last circuit we saw */
1809 tor_assert(*prev_p
== prev_circ
);
1810 /* If that's NULL, assert that we are the head */
1811 if (!(*prev_p
)) tor_assert(curr_circ
== cmux
->active_circuits_head
);
1813 /* Get the next circuit */
1814 next_circ
= *next_p
;
1815 /* If it's NULL, assert that we are the tail */
1816 if (!(*next_p
)) tor_assert(curr_circ
== cmux
->active_circuits_tail
);
1818 /* Now find the hash table entry for this circuit */
1819 search
.chan_id
= curr_chan_id
;
1820 search
.circ_id
= curr_circ_id
;
1821 hashent
= HT_FIND(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
,
1824 /* Assert that we have one */
1825 tor_assert(hashent
);
1827 /* Assert that the direction matches */
1828 tor_assert(direction
== hashent
->muxinfo
.direction
);
1830 /* Assert that the hash entry got marked in pass one */
1831 tor_assert(hashent
->muxinfo
.mark
);
1833 /* Clear the mark */
1834 hashent
->muxinfo
.mark
= 0;
1836 /* Increment the counter */
1837 ++n_active_circuits
;
1839 /* Advance to the next active circuit and update prev_circ */
1840 prev_circ
= curr_circ
;
1841 curr_circ
= next_circ
;
1844 /* Assert that the counter matches the cmux */
1845 tor_assert(n_active_circuits
== cmux
->n_active_circuits
);
1849 * Do the third pass of circuitmux_assert_okay(); see the comment in that
1854 circuitmux_assert_okay_pass_three(circuitmux_t
*cmux
)
1856 chanid_circid_muxinfo_t
**i
= NULL
;
1859 tor_assert(cmux
->chanid_circid_map
);
1861 /* Start iterating the hash table */
1862 i
= HT_START(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
);
1864 /* Advance through each entry */
1866 /* Assert that it isn't null */
1870 * Assert that this entry is not marked - i.e., that either we didn't
1871 * think it should be active in pass one or we saw it in the active
1872 * circuits linked list.
1874 tor_assert(!((*i
)->muxinfo
.mark
));
1876 /* Advance to the next entry */
1877 i
= HT_NEXT(chanid_circid_muxinfo_map
, cmux
->chanid_circid_map
, i
);
1883 circuitmux_append_destroy_cell(channel_t
*chan
,
1889 memset(&cell
, 0, sizeof(cell_t
));
1890 cell
.circ_id
= circ_id
;
1891 cell
.command
= CELL_DESTROY
;
1892 cell
.payload
[0] = (uint8_t) reason
;
1894 cell_queue_append_packed_copy(NULL
, &cmux
->destroy_cell_queue
, 0, &cell
,
1895 chan
->wide_circ_ids
, 0);
1897 /* Destroy entering the queue, update counters */
1898 ++(cmux
->destroy_ctr
);
1899 ++global_destroy_ctr
;
1901 "Cmux at %p queued a destroy for circ %u, cmux counter is now "
1902 I64_FORMAT
", global counter is now "I64_FORMAT
,
1904 I64_PRINTF_ARG(cmux
->destroy_ctr
),
1905 I64_PRINTF_ARG(global_destroy_ctr
));
1907 /* XXXX Duplicate code from append_cell_to_circuit_queue */
1908 if (!channel_has_queued_writes(chan
)) {
1909 /* There is no data at all waiting to be sent on the outbuf. Add a
1910 * cell, so that we can notice when it gets flushed, flushed_some can
1911 * get called, and we can start putting more data onto the buffer then.
1913 log_debug(LD_GENERAL
, "Primed a buffer.");
1914 channel_flush_from_first_active_circuit(chan
, 1);
1918 /*DOCDOC; for debugging 12184. This runs slowly. */
1920 circuitmux_count_queued_destroy_cells(const channel_t
*chan
,
1921 const circuitmux_t
*cmux
)
1923 int64_t n_destroy_cells
= cmux
->destroy_ctr
;
1924 int64_t destroy_queue_size
= cmux
->destroy_cell_queue
.n
;
1926 int64_t manual_total
= 0;
1927 int64_t manual_total_in_map
= 0;
1928 packed_cell_t
*cell
;
1930 TOR_SIMPLEQ_FOREACH(cell
, &cmux
->destroy_cell_queue
.head
, next
) {
1934 id
= packed_cell_get_circid(cell
, chan
->wide_circ_ids
);
1935 if (circuit_id_in_use_on_channel(id
, (channel_t
*)chan
))
1936 ++manual_total_in_map
;
1939 if (n_destroy_cells
!= destroy_queue_size
||
1940 n_destroy_cells
!= manual_total
||
1941 n_destroy_cells
!= manual_total_in_map
) {
1942 log_warn(LD_BUG
, " Discrepancy in counts for queued destroy cells on "
1943 "circuitmux. n="I64_FORMAT
". queue_size="I64_FORMAT
". "
1944 "manual_total="I64_FORMAT
". manual_total_in_map="I64_FORMAT
".",
1945 I64_PRINTF_ARG(n_destroy_cells
),
1946 I64_PRINTF_ARG(destroy_queue_size
),
1947 I64_PRINTF_ARG(manual_total
),
1948 I64_PRINTF_ARG(manual_total_in_map
));
1951 return n_destroy_cells
;