Fix a number of clang analyzer false-positives
[tor.git] / src / or / circuitmux.c
blobe4571ff9446b624d89ce3ed029ad378fbfe43470
1 /* * Copyright (c) 2012-2013, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file circuitmux.c
6 * \brief Circuit mux/cell selection abstraction
7 **/
9 #include "or.h"
10 #include "channel.h"
11 #include "circuitlist.h"
12 #include "circuitmux.h"
13 #include "relay.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
49 * are:
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
127 * cells completely.
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.
133 int64_t destroy_ctr;
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 */
159 unsigned int mark:1;
163 * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
164 * circuit.
167 struct chanid_circid_muxinfo_t {
168 HT_ENTRY(chanid_circid_muxinfo_t) node;
169 uint64_t chan_id;
170 circid_t circ_id;
171 circuit_muxinfo_t muxinfo;
175 * Internal-use #defines
178 #ifdef CMUX_PARANOIA
179 #define circuitmux_assert_okay_paranoid(cmux) \
180 circuitmux_assert_okay(cmux)
181 #else
182 #define circuitmux_assert_okay_paranoid(cmux)
183 #endif
186 * Static function declarations
189 static INLINE int
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);
196 static void
197 circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ,
198 cell_direction_t direction);
199 static void
200 circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ,
201 cell_direction_t direction);
202 static INLINE void
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().
229 static INLINE void
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;
238 tor_assert(cmux);
239 tor_assert(circ);
241 circuitmux_assert_okay_paranoid(cmux);
243 /* Figure out our next_p and prev_p for this cmux/direction */
244 if (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);
249 } else {
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);
255 } else {
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;
260 } else {
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;
268 tor_assert(next_p);
269 tor_assert(prev_p);
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 */
276 return;
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 */
293 *next_p = NULL;
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);
299 *tail_next = circ;
300 } else {
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)
312 tor_assert(cmux);
313 tor_assert(circ);
315 if (circ->n_mux == cmux) return &(circ->next_active_on_n_chan);
316 else {
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)
325 tor_assert(cmux);
326 tor_assert(circ);
328 if (circ->n_mux == cmux) return &(circ->prev_active_on_n_chan);
329 else {
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.
341 static INLINE int
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
378 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);
388 return rv;
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
395 * detached_out.
398 void
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;
405 tor_assert(cmux);
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);
413 while (i) {
414 to_remove = *i;
416 if (! to_remove) {
417 log_warn(LD_BUG, "Somehow, an HT iterator gave us a NULL pointer.");
418 break;
419 } else {
420 /* Find a channel and circuit */
421 chan = channel_find_by_global_id(to_remove->chan_id);
422 if (chan) {
423 circ =
424 circuit_get_by_circid_channel_even_if_marked(to_remove->circ_id,
425 chan);
426 if (circ) {
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);
438 /* Clear n_mux */
439 circ->n_mux = NULL;
441 if (detached_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,
455 * so clear p_mux.
457 TO_OR_CIRCUIT(circ)->p_mux = NULL;
459 if (detached_out)
460 smartlist_add(detached_out, circ);
461 } else {
462 /* Complain and move on */
463 log_warn(LD_CIRC,
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
474 * free it
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,
480 cmux->policy_data,
481 circ,
482 to_remove->muxinfo.policy_data);
483 to_remove->muxinfo.policy_data = NULL;
485 } else {
486 /* Complain and move on */
487 log_warn(LD_CIRC,
488 "Couldn't find circuit %u (for channel " U64_FORMAT ")",
489 (unsigned)to_remove->circ_id,
490 U64_PRINTF_ARG(to_remove->chan_id));
492 } else {
493 /* Complain and move on */
494 log_warn(LD_CIRC,
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);
506 /* Free it */
507 tor_free(to_remove);
510 cmux->n_circuits = 0;
511 cmux->n_active_circuits = 0;
512 cmux->n_cells = 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
520 * circuitmux_free().
522 void
523 circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, channel_t *chan)
525 packed_cell_t *cell;
526 int n_bad = 0;
527 TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
528 circid_t circid = 0;
529 if (packed_cell_is_destroy(chan, cell, &circid)) {
530 channel_mark_circid_usable(chan, circid);
531 } else {
532 ++n_bad;
535 if (n_bad)
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().
545 void
546 circuitmux_free(circuitmux_t *cmux)
548 if (!cmux) return;
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
558 * called.
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;
579 log_debug(LD_CIRC,
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));
585 } else {
586 log_debug(LD_CIRC,
587 "Freeing cmux at %p with no queued destroys, the cmux destroy "
588 "balance was "I64_FORMAT", global is "I64_FORMAT,
589 cmux,
590 I64_PRINTF_ARG(cmux->destroy_ctr),
591 I64_PRINTF_ARG(global_destroy_ctr));
594 cell_queue_clear(&cmux->destroy_cell_queue);
596 tor_free(cmux);
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
606 * mechanism.
609 void
610 circuitmux_clear_policy(circuitmux_t *cmux)
612 tor_assert(cmux);
614 /* Internally, this is just setting policy to NULL */
615 if (cmux->policy) {
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)
627 tor_assert(cmux);
629 return cmux->policy;
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.
637 void
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;
648 tor_assert(cmux);
650 /* Set up variables */
651 old_pol = cmux->policy;
652 old_pol_data = cmux->policy_data;
653 new_pol = pol;
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);
676 while (i) {
677 /* Assert that this entry isn't NULL */
678 tor_assert(*i);
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;
688 tor_assert(chan);
690 /* Get the circuit */
691 circ = circuit_get_by_circid_channel_even_if_marked((*i)->circ_id, chan);
692 tor_assert(circ);
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 */
704 tor_assert(old_pol);
705 tor_assert(old_pol->free_circ_data);
706 /* Free it */
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 */
738 if (old_pol_data) {
740 * If we had old policy data, we should have an old policy and a free
741 * function for it.
743 tor_assert(old_pol);
744 tor_assert(old_pol->free_cmux_data);
745 old_pol->free_cmux_data(cmux, old_pol_data);
746 old_pol_data = NULL;
751 * Circuitmux/circuit attachment status inquiry functions
755 * Query the direction of an attached circuit
758 cell_direction_t
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.
770 tor_assert(hashent);
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
778 * is none.
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 */
787 tor_assert(cmux);
788 tor_assert(cmux->chanid_circid_map);
789 tor_assert(circ);
791 /* Check if we have n_chan */
792 if (circ->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;
797 /* Query */
798 hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
799 &search);
802 /* Found something? */
803 if (hashent) {
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);
809 } else {
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,
818 &search);
819 /* Find anything? */
820 if (hashent) {
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 */
829 return hashent;
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;
855 int is_active = 0;
857 tor_assert(cmux);
858 tor_assert(circ);
860 /* Look if it's in the circuit map */
861 hashent = circuitmux_find_map_entry(cmux, circ);
862 if (hashent) {
863 /* Check the number of cells on this circuit */
864 is_active = (hashent->muxinfo.cell_count > 0);
866 /* else not attached, so not active */
868 return is_active;
872 * Query number of available cells for a circuit on a circuitmux
875 unsigned int
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;
881 tor_assert(cmux);
882 tor_assert(circ);
884 /* Look if it's in the circuit map */
885 hashent = circuitmux_find_map_entry(cmux, circ);
886 if (hashent) {
887 /* Just get the cell count for this circuit */
888 n_cells = hashent->muxinfo.cell_count;
890 /* else not attached, so 0 cells */
892 return n_cells;
896 * Query total number of available cells on a circuitmux
899 unsigned int
900 circuitmux_num_cells(circuitmux_t *cmux)
902 tor_assert(cmux);
904 return cmux->n_cells + cmux->destroy_cell_queue.n;
908 * Query total number of circuits active on a circuitmux
911 unsigned int
912 circuitmux_num_active_circuits(circuitmux_t *cmux)
914 tor_assert(cmux);
916 return cmux->n_active_circuits;
920 * Query total number of circuits attached to a circuitmux
923 unsigned int
924 circuitmux_num_circuits(circuitmux_t *cmux)
926 tor_assert(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.
939 MOCK_IMPL(void,
940 circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
941 cell_direction_t direction))
943 channel_t *chan = NULL;
944 uint64_t channel_id;
945 circid_t circ_id;
946 chanid_circid_muxinfo_t search, *hashent = NULL;
947 unsigned int cell_count;
949 tor_assert(cmux);
950 tor_assert(circ);
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) {
961 /* It's n_chan */
962 chan = circ->n_chan;
963 cell_count = circ->n_chan_cells.n;
964 circ_id = circ->n_circ_id;
965 } else {
966 /* We want p_chan */
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 */
972 tor_assert(chan);
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,
983 &search);
985 if (hashent) {
987 * This circuit was already attached to this cmux; make sure the
988 * directions match and update the cell count and active circuit count.
990 log_info(LD_CIRC,
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),
996 cmux);
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;
1019 } else {
1021 * New circuit; add an entry and update the circuit/active circuit
1022 * counts.
1024 log_debug(LD_CIRC,
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
1030 * direction.
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);
1045 /* Allocate it */
1046 hashent->muxinfo.policy_data =
1047 cmux->policy->alloc_circ_data(cmux,
1048 cmux->policy_data,
1049 circ,
1050 direction,
1051 cell_count);
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,
1056 hashent);
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;
1066 } else {
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.
1088 MOCK_IMPL(void,
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;
1101 tor_assert(cmux);
1102 tor_assert(cmux->chanid_circid_map);
1103 tor_assert(circ);
1104 circuitmux_assert_okay_paranoid(cmux);
1106 /* See if we have it for n_chan/n_circ_id */
1107 if (circ->n_chan) {
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,
1111 &search);
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 */
1116 if (!hashent) {
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,
1123 &search);
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.
1136 if (hashent) {
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,
1153 cmux->policy_data,
1154 circ,
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 */
1169 tor_free(hashent);
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.
1180 static void
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;
1188 circid_t circ_id;
1189 int already_active;
1191 tor_assert(cmux);
1192 tor_assert(circ);
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
1198 * again.
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;
1208 } else {
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) {
1231 log_warn(LD_CIRC,
1232 "Circuit %u on channel " U64_FORMAT " was already active",
1233 (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier));
1234 return;
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 */
1245 next_prev =
1246 circuitmux_prev_active_circ_p(cmux, cmux->active_circuits_head);
1247 tor_assert(next_prev);
1248 *next_prev = circ;
1249 } else {
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 */
1257 if (cmux->policy &&
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);
1263 /* Notify */
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.
1276 static void
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;
1285 circid_t circ_id;
1286 int already_inactive;
1288 tor_assert(cmux);
1289 tor_assert(circ);
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
1295 * again.
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;
1305 } else {
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) {
1328 log_warn(LD_CIRC,
1329 "Circuit %d on channel " U64_FORMAT " was already inactive",
1330 (unsigned)circ_id, U64_PRINTF_ARG(chan->global_identifier));
1331 return;
1334 /* Remove from the list; first get next_prev and prev_next */
1335 if (*next_active) {
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);
1341 } else {
1342 /* Else, the tail becomes this circuit's previous circuit */
1343 next_prev = &(cmux->active_circuits_tail);
1346 /* Got next_prev, now prev_next */
1347 if (*prev_active) {
1349 * If there's a previous circuit, its next circuit becomes this circuit's
1350 * next circuit.
1352 prev_next = circuitmux_next_active_circ_p(cmux, *prev_active);
1353 } else {
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 */
1371 if (cmux->policy &&
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);
1377 /* Notify */
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
1389 void
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
1400 void
1401 circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
1402 unsigned int n_cells)
1404 chanid_circid_muxinfo_t *hashent = NULL;
1406 tor_assert(cmux);
1407 tor_assert(circ);
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,
1424 cmux->policy_data,
1425 circ,
1426 hashent->muxinfo.policy_data,
1427 n_cells);
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);
1443 } else {
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
1467 * return NULL.
1470 circuit_t *
1471 circuitmux_get_first_active_circuit(circuitmux_t *cmux,
1472 cell_queue_t **destroy_queue_out)
1474 circuit_t *circ = NULL;
1476 tor_assert(cmux);
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 */
1499 if (!circ) {
1500 tor_assert(cmux->active_circuits_head);
1501 circ = cmux->active_circuits_head;
1503 cmux->last_cell_was_destroy = 0;
1504 } else {
1505 tor_assert(cmux->n_cells == 0);
1506 tor_assert(cmux->destroy_cell_queue.n == 0);
1509 return circ;
1513 * Notify the circuitmux that cells have been sent on a circuit; this
1514 * is called from channel.c.
1517 void
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;
1524 tor_assert(cmux);
1525 tor_assert(circ);
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
1536 * went to zero.
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,
1566 n_cells);
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
1583 * the counter.
1586 void
1587 circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
1589 tor_assert(cmux);
1591 --(cmux->destroy_ctr);
1592 --(global_destroy_ctr);
1593 log_debug(LD_CIRC,
1594 "Cmux at %p sent a destroy, cmux counter is now "I64_FORMAT", "
1595 "global counter is now "I64_FORMAT,
1596 cmux,
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
1607 * assert if not.
1610 void
1611 circuitmux_assert_okay(circuitmux_t *cmux)
1613 tor_assert(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
1627 * list pointers.
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
1641 * function.
1644 static void
1645 circuitmux_assert_okay_pass_one(circuitmux_t *cmux)
1647 chanid_circid_muxinfo_t **i = NULL;
1648 uint64_t chan_id;
1649 channel_t *chan;
1650 circid_t circ_id;
1651 circuit_t *circ;
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;
1657 tor_assert(cmux);
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);
1664 while (i) {
1665 /* Assert that the hash table entry isn't null */
1666 tor_assert(*i);
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);
1674 tor_assert(chan);
1675 circ = circuit_get_by_circid_channel_even_if_marked(circ_id, chan);
1676 tor_assert(circ);
1677 /* Clear the circ_is_active bit to start */
1678 circ_is_active = 0;
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);
1691 } else {
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
1703 * cells on it?
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;
1715 } else {
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 */
1725 ++n_circuits;
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
1744 * function.
1747 static void
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;
1755 channel_t *chan;
1756 unsigned int n_active_circuits = 0;
1757 cell_direction_t direction;
1758 chanid_circid_muxinfo_t search, *hashent = NULL;
1760 tor_assert(cmux);
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;
1770 while (curr_circ) {
1771 /* Reset some things */
1772 chan = NULL;
1773 curr_or_circ = NULL;
1774 next_circ = NULL;
1775 next_p = prev_p = NULL;
1776 direction = 0;
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;
1789 } else {
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 */
1805 tor_assert(chan);
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,
1822 &search);
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
1850 * function.
1853 static void
1854 circuitmux_assert_okay_pass_three(circuitmux_t *cmux)
1856 chanid_circid_muxinfo_t **i = NULL;
1858 tor_assert(cmux);
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 */
1865 while (i) {
1866 /* Assert that it isn't null */
1867 tor_assert(*i);
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);
1881 /*DOCDOC */
1882 void
1883 circuitmux_append_destroy_cell(channel_t *chan,
1884 circuitmux_t *cmux,
1885 circid_t circ_id,
1886 uint8_t reason)
1888 cell_t cell;
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;
1900 log_debug(LD_CIRC,
1901 "Cmux at %p queued a destroy for circ %u, cmux counter is now "
1902 I64_FORMAT", global counter is now "I64_FORMAT,
1903 cmux, circ_id,
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. */
1919 int64_t
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) {
1931 circid_t id;
1932 ++manual_total;
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;