Merge branch 'maint-0.4.8'
[tor.git] / src / core / or / circuitmux.c
blob6f8761ca39a441b15a5789a60721585e16b1796d
1 /* * Copyright (c) 2012-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /**
5 * \file circuitmux.c
6 * \brief Circuit mux/cell selection abstraction
8 * A circuitmux is responsible for <b>MU</b>ltiple<b>X</b>ing all of the
9 * circuits that are writing on a single channel. It keeps track of which of
10 * these circuits has something to write (aka, "active" circuits), and which
11 * one should write next. A circuitmux corresponds 1:1 with a channel.
13 * There can be different implementations of the circuitmux's rules (which
14 * decide which circuit is next to write).
16 * A circuitmux exposes three distinct
17 * interfaces to other components:
19 * To channels, which each have a circuitmux_t, the supported operations
20 * (invoked from relay.c) are:
22 * circuitmux_get_first_active_circuit():
24 * Pick one of the circuitmux's active circuits to send cells from.
26 * circuitmux_notify_xmit_cells():
28 * Notify the circuitmux that cells have been sent on a circuit.
30 * To circuits, the exposed operations are:
32 * circuitmux_attach_circuit():
34 * Attach a circuit to the circuitmux; this will allocate any policy-
35 * specific data wanted for this circuit and add it to the active
36 * circuits list if it has queued cells.
38 * circuitmux_detach_circuit():
40 * Detach a circuit from the circuitmux, freeing associated structures.
42 * circuitmux_clear_num_cells():
44 * Clear the circuitmux's cell counter for this circuit.
46 * circuitmux_set_num_cells():
48 * Set the circuitmux's cell counter for this circuit. One of
49 * circuitmuc_clear_num_cells() or circuitmux_set_num_cells() MUST be
50 * called when the number of cells queued on a circuit changes.
52 * See circuitmux.h for the circuitmux_policy_t data structure, which contains
53 * a table of function pointers implementing a circuit selection policy, and
54 * circuitmux_ewma.c for an example of a circuitmux policy. Circuitmux
55 * policies can be manipulated with:
57 * circuitmux_get_policy():
59 * Return the current policy for a circuitmux_t, if any.
61 * circuitmux_clear_policy():
63 * Remove a policy installed on a circuitmux_t, freeing all associated
64 * data. The circuitmux will revert to the built-in round-robin behavior.
66 * circuitmux_set_policy():
68 * Install a policy on a circuitmux_t; the appropriate callbacks will be
69 * made to attach all existing circuits to the new policy.
70 **/
72 #define CIRCUITMUX_PRIVATE
74 #include "core/or/or.h"
75 #include "core/or/channel.h"
76 #include "core/or/circuitlist.h"
77 #include "core/or/circuitmux.h"
78 #include "core/or/relay.h"
80 #include "core/or/or_circuit_st.h"
82 #include "lib/crypt_ops/crypto_util.h"
85 * Private typedefs for circuitmux.c
89 * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
90 * break the hash table code).
92 typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
95 * Anything the mux wants to store per-circuit in the map; right now just
96 * a count of queued cells.
99 typedef struct circuit_muxinfo_t circuit_muxinfo_t;
102 * This struct holds whatever we want to store per attached circuit on a
103 * circuitmux_t; right now, just the count of queued cells and the direction.
106 struct circuit_muxinfo_t {
107 /* Count of cells on this circuit at last update */
108 unsigned int cell_count;
109 /* Direction of flow */
110 cell_direction_t direction;
111 /* Policy-specific data */
112 circuitmux_policy_circ_data_t *policy_data;
113 /* Mark bit for consistency checker */
114 unsigned int mark:1;
118 * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
119 * circuit.
122 struct chanid_circid_muxinfo_t {
123 HT_ENTRY(chanid_circid_muxinfo_t) node;
124 uint64_t chan_id;
125 circid_t circ_id;
126 circuit_muxinfo_t muxinfo;
130 * Static function declarations
133 static inline int
134 chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
135 chanid_circid_muxinfo_t *b);
136 static inline unsigned int
137 chanid_circid_entry_hash(chanid_circid_muxinfo_t *a);
138 static chanid_circid_muxinfo_t *
139 circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ);
140 static void
141 circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ);
142 static void
143 circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ);
145 /* Static global variables */
147 /** Count the destroy balance to debug destroy queue logic */
148 static int64_t global_destroy_ctr = 0;
150 /* Function definitions */
153 * Helper for chanid_circid_cell_count_map_t hash table: compare the channel
154 * ID and circuit ID for a and b, and return less than, equal to, or greater
155 * than zero appropriately.
158 static inline int
159 chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
160 chanid_circid_muxinfo_t *b)
162 return a->chan_id == b->chan_id && a->circ_id == b->circ_id;
166 * Helper: return a hash based on circuit ID and channel ID in a.
169 static inline unsigned int
170 chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
172 uint8_t data[8 + 4];
173 set_uint64(data, a->chan_id);
174 set_uint32(data + 8, a->circ_id);
175 return (unsigned) siphash24g(data, sizeof(data));
178 /* Emit a bunch of hash table stuff */
179 HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
180 chanid_circid_entry_hash, chanid_circid_entries_eq);
181 HT_GENERATE2(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
182 chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6,
183 tor_reallocarray_, tor_free_);
186 * Circuitmux alloc/free functions
190 * Allocate a new circuitmux_t
193 circuitmux_t *
194 circuitmux_alloc(void)
196 circuitmux_t *rv = NULL;
198 rv = tor_malloc_zero(sizeof(*rv));
199 rv->chanid_circid_map = tor_malloc_zero(sizeof(*( rv->chanid_circid_map)));
200 HT_INIT(chanid_circid_muxinfo_map, rv->chanid_circid_map);
201 destroy_cell_queue_init(&rv->destroy_cell_queue);
203 return rv;
207 * Detach all circuits from a circuitmux (use before circuitmux_free())
209 * If <b>detached_out</b> is non-NULL, add every detached circuit_t to
210 * detached_out.
213 void
214 circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
216 chanid_circid_muxinfo_t **i = NULL, *to_remove;
217 channel_t *chan = NULL;
218 circuit_t *circ = NULL;
220 tor_assert(cmux);
222 i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
223 while (i) {
224 to_remove = *i;
226 if (! to_remove) {
227 log_warn(LD_BUG, "Somehow, an HT iterator gave us a NULL pointer.");
228 break;
229 } else {
230 /* Find a channel and circuit */
231 chan = channel_find_by_global_id(to_remove->chan_id);
232 if (chan) {
233 circ =
234 circuit_get_by_circid_channel_even_if_marked(to_remove->circ_id,
235 chan);
236 if (circ) {
237 /* Clear the circuit's mux for this direction */
238 if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) {
240 * Update active_circuits et al.; this does policy notifies, so
241 * comes before freeing policy data
244 if (to_remove->muxinfo.cell_count > 0) {
245 circuitmux_make_circuit_inactive(cmux, circ);
248 if (detached_out)
249 smartlist_add(detached_out, circ);
250 } else if (circ->magic == OR_CIRCUIT_MAGIC) {
252 * Update active_circuits et al.; this does policy notifies, so
253 * comes before freeing policy data
256 if (to_remove->muxinfo.cell_count > 0) {
257 circuitmux_make_circuit_inactive(cmux, circ);
260 if (detached_out)
261 smartlist_add(detached_out, circ);
262 } else {
263 /* Complain and move on */
264 log_warn(LD_CIRC,
265 "Circuit %u/channel %"PRIu64 " had direction == "
266 "CELL_DIRECTION_IN, but isn't an or_circuit_t",
267 (unsigned)to_remove->circ_id,
268 (to_remove->chan_id));
271 /* Free policy-specific data if we have it */
272 if (to_remove->muxinfo.policy_data) {
274 * If we have policy data, assert that we have the means to
275 * free it
277 tor_assert(cmux->policy);
278 tor_assert(cmux->policy->free_circ_data);
279 /* Call free_circ_data() */
280 cmux->policy->free_circ_data(cmux,
281 cmux->policy_data,
282 circ,
283 to_remove->muxinfo.policy_data);
284 to_remove->muxinfo.policy_data = NULL;
286 } else {
287 /* Complain and move on */
288 log_warn(LD_CIRC,
289 "Couldn't find circuit %u (for channel %"PRIu64 ")",
290 (unsigned)to_remove->circ_id,
291 (to_remove->chan_id));
293 } else {
294 /* Complain and move on */
295 log_warn(LD_CIRC,
296 "Couldn't find channel %"PRIu64 " (for circuit id %u)",
297 (to_remove->chan_id),
298 (unsigned)to_remove->circ_id);
301 /* Assert that we don't have un-freed policy data for this circuit */
302 tor_assert(to_remove->muxinfo.policy_data == NULL);
305 i = HT_NEXT_RMV(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
307 /* Free it */
308 tor_free(to_remove);
311 cmux->n_circuits = 0;
312 cmux->n_active_circuits = 0;
313 cmux->n_cells = 0;
316 /** Reclaim all circuit IDs currently marked as unusable on <b>chan</b> because
317 * of pending destroy cells in <b>cmux</b>.
319 * This function must be called AFTER circuits are unlinked from the (channel,
320 * circuid-id) map with circuit_unlink_all_from_channel(), but before calling
321 * circuitmux_free().
323 void
324 circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, channel_t *chan)
326 destroy_cell_t *cell;
327 TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
328 channel_mark_circid_usable(chan, cell->circid);
333 * Free a circuitmux_t; the circuits must be detached first with
334 * circuitmux_detach_all_circuits().
337 void
338 circuitmux_free_(circuitmux_t *cmux)
340 if (!cmux) return;
342 tor_assert(cmux->n_circuits == 0);
343 tor_assert(cmux->n_active_circuits == 0);
346 * Free policy-specific data if we have any; we don't
347 * need to do circuitmux_set_policy(cmux, NULL) to cover
348 * the circuits because they would have been handled in
349 * circuitmux_detach_all_circuits() before this was
350 * called.
352 if (cmux->policy && cmux->policy->free_cmux_data) {
353 if (cmux->policy_data) {
354 cmux->policy->free_cmux_data(cmux, cmux->policy_data);
355 cmux->policy_data = NULL;
357 } else tor_assert(cmux->policy_data == NULL);
359 if (cmux->chanid_circid_map) {
360 HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
361 tor_free(cmux->chanid_circid_map);
365 * We're throwing away some destroys; log the counter and
366 * adjust the global counter by the queue size.
368 if (cmux->destroy_cell_queue.n > 0) {
369 cmux->destroy_ctr -= cmux->destroy_cell_queue.n;
370 global_destroy_ctr -= cmux->destroy_cell_queue.n;
371 log_debug(LD_CIRC,
372 "Freeing cmux at %p with %u queued destroys; the last cmux "
373 "destroy balance was %"PRId64", global is %"PRId64,
374 cmux, cmux->destroy_cell_queue.n,
375 (cmux->destroy_ctr),
376 (global_destroy_ctr));
377 } else {
378 log_debug(LD_CIRC,
379 "Freeing cmux at %p with no queued destroys, the cmux destroy "
380 "balance was %"PRId64", global is %"PRId64,
381 cmux,
382 (cmux->destroy_ctr),
383 (global_destroy_ctr));
386 destroy_cell_queue_clear(&cmux->destroy_cell_queue);
388 tor_free(cmux);
392 * Circuitmux policy control functions
396 * Remove any policy installed on cmux; all policy data will be freed and
397 * cmux behavior will revert to the built-in round-robin active_circuits
398 * mechanism.
401 void
402 circuitmux_clear_policy(circuitmux_t *cmux)
404 tor_assert(cmux);
406 /* Internally, this is just setting policy to NULL */
407 circuitmux_set_policy(cmux, NULL);
411 * Return the policy currently installed on a circuitmux_t
414 MOCK_IMPL(const circuitmux_policy_t *,
415 circuitmux_get_policy, (circuitmux_t *cmux))
417 tor_assert(cmux);
419 return cmux->policy;
423 * Set policy; allocate for new policy, detach all circuits from old policy
424 * if any, attach them to new policy, and free old policy data.
427 void
428 circuitmux_set_policy(circuitmux_t *cmux,
429 const circuitmux_policy_t *pol)
431 const circuitmux_policy_t *old_pol = NULL, *new_pol = NULL;
432 circuitmux_policy_data_t *old_pol_data = NULL, *new_pol_data = NULL;
433 chanid_circid_muxinfo_t **i = NULL;
434 channel_t *chan = NULL;
435 uint64_t last_chan_id_searched = 0;
436 circuit_t *circ = NULL;
438 tor_assert(cmux);
440 /* Set up variables */
441 old_pol = cmux->policy;
442 old_pol_data = cmux->policy_data;
443 new_pol = pol;
445 /* Check if this is the trivial case */
446 if (old_pol == new_pol) return;
448 /* Allocate data for new policy, if any */
449 if (new_pol && new_pol->alloc_cmux_data) {
451 * If alloc_cmux_data is not null, then we expect to get some policy
452 * data. Assert that we also have free_cmux_data so we can free it
453 * when the time comes, and allocate it.
455 tor_assert(new_pol->free_cmux_data);
456 new_pol_data = new_pol->alloc_cmux_data(cmux);
457 tor_assert(new_pol_data);
460 /* Install new policy and new policy data on cmux */
461 cmux->policy = new_pol;
462 cmux->policy_data = new_pol_data;
464 /* Iterate over all circuits, attaching/detaching each one */
465 i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
466 while (i) {
467 /* Assert that this entry isn't NULL */
468 tor_assert(*i);
471 * Get the channel; since normal case is all circuits on the mux share a
472 * channel, we cache last_chan_id_searched
474 if (!chan || last_chan_id_searched != (*i)->chan_id) {
475 chan = channel_find_by_global_id((*i)->chan_id);
476 last_chan_id_searched = (*i)->chan_id;
478 tor_assert(chan);
480 /* Get the circuit */
481 circ = circuit_get_by_circid_channel_even_if_marked((*i)->circ_id, chan);
482 tor_assert(circ);
484 /* Need to tell old policy it becomes inactive (i.e., it is active) ? */
485 if (old_pol && old_pol->notify_circ_inactive &&
486 (*i)->muxinfo.cell_count > 0) {
487 old_pol->notify_circ_inactive(cmux, old_pol_data, circ,
488 (*i)->muxinfo.policy_data);
491 /* Need to free old policy data? */
492 if ((*i)->muxinfo.policy_data) {
493 /* Assert that we have the means to free it if we have policy data */
494 tor_assert(old_pol);
495 tor_assert(old_pol->free_circ_data);
496 /* Free it */
497 old_pol->free_circ_data(cmux, old_pol_data, circ,
498 (*i)->muxinfo.policy_data);
499 (*i)->muxinfo.policy_data = NULL;
502 /* Need to allocate new policy data? */
503 if (new_pol && new_pol->alloc_circ_data) {
505 * If alloc_circ_data is not null, we expect to get some per-circuit
506 * policy data. Assert that we also have free_circ_data so we can
507 * free it when the time comes, and allocate it.
509 tor_assert(new_pol->free_circ_data);
510 (*i)->muxinfo.policy_data =
511 new_pol->alloc_circ_data(cmux, new_pol_data, circ,
512 (*i)->muxinfo.direction,
513 (*i)->muxinfo.cell_count);
516 /* Need to make active on new policy? */
517 if (new_pol && new_pol->notify_circ_active &&
518 (*i)->muxinfo.cell_count > 0) {
519 new_pol->notify_circ_active(cmux, new_pol_data, circ,
520 (*i)->muxinfo.policy_data);
523 /* Advance to next circuit map entry */
524 i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
527 /* Free data for old policy, if any */
528 if (old_pol_data) {
530 * If we had old policy data, we should have an old policy and a free
531 * function for it.
533 tor_assert(old_pol);
534 tor_assert(old_pol->free_cmux_data);
535 old_pol->free_cmux_data(cmux, old_pol_data);
536 old_pol_data = NULL;
541 * Circuitmux/circuit attachment status inquiry functions
545 * Query the direction of an attached circuit
548 cell_direction_t
549 circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ)
551 chanid_circid_muxinfo_t *hashent = NULL;
553 /* Try to find a map entry */
554 hashent = circuitmux_find_map_entry(cmux, circ);
557 * This function should only be called on attached circuits; assert that
558 * we had a map entry.
560 tor_assert(hashent);
562 /* Return the direction from the map entry */
563 return hashent->muxinfo.direction;
567 * Find an entry in the cmux's map for this circuit or return NULL if there
568 * is none.
571 static chanid_circid_muxinfo_t *
572 circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ)
574 chanid_circid_muxinfo_t search, *hashent = NULL;
576 /* Sanity-check parameters */
577 tor_assert(cmux);
578 tor_assert(cmux->chanid_circid_map);
579 tor_assert(circ);
581 /* Check if we have n_chan */
582 if (circ->n_chan) {
583 /* Okay, let's see if it's attached for n_chan/n_circ_id */
584 search.chan_id = circ->n_chan->global_identifier;
585 search.circ_id = circ->n_circ_id;
587 /* Query */
588 hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
589 &search);
592 /* Found something? */
593 if (hashent) {
595 * Assert that the direction makes sense for a hashent we found by
596 * n_chan/n_circ_id before we return it.
598 tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_OUT);
599 } else {
600 /* Not there, have we got a p_chan/p_circ_id to try? */
601 if (circ->magic == OR_CIRCUIT_MAGIC) {
602 search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
603 /* Check for p_chan */
604 if (TO_OR_CIRCUIT(circ)->p_chan) {
605 search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier;
606 /* Okay, search for that */
607 hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
608 &search);
609 /* Find anything? */
610 if (hashent) {
611 /* Assert that the direction makes sense before we return it */
612 tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_IN);
618 /* Okay, hashent is it if it was there */
619 return hashent;
623 * Query whether a circuit is attached to a circuitmux
627 circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
629 chanid_circid_muxinfo_t *hashent = NULL;
631 /* Look if it's in the circuit map */
632 hashent = circuitmux_find_map_entry(cmux, circ);
634 return (hashent != NULL);
638 * Query whether a circuit is active on a circuitmux
642 circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ)
644 chanid_circid_muxinfo_t *hashent = NULL;
645 int is_active = 0;
647 tor_assert(cmux);
648 tor_assert(circ);
650 /* Look if it's in the circuit map */
651 hashent = circuitmux_find_map_entry(cmux, circ);
652 if (hashent) {
653 /* Check the number of cells on this circuit */
654 is_active = (hashent->muxinfo.cell_count > 0);
656 /* else not attached, so not active */
658 return is_active;
662 * Query number of available cells for a circuit on a circuitmux
665 unsigned int
666 circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ)
668 chanid_circid_muxinfo_t *hashent = NULL;
669 unsigned int n_cells = 0;
671 tor_assert(cmux);
672 tor_assert(circ);
674 /* Look if it's in the circuit map */
675 hashent = circuitmux_find_map_entry(cmux, circ);
676 if (hashent) {
677 /* Just get the cell count for this circuit */
678 n_cells = hashent->muxinfo.cell_count;
680 /* else not attached, so 0 cells */
682 return n_cells;
686 * Query total number of available cells on a circuitmux
689 MOCK_IMPL(unsigned int,
690 circuitmux_num_cells, (circuitmux_t *cmux))
692 tor_assert(cmux);
694 return cmux->n_cells + cmux->destroy_cell_queue.n;
698 * Query total number of circuits active on a circuitmux
701 unsigned int
702 circuitmux_num_active_circuits(circuitmux_t *cmux)
704 tor_assert(cmux);
706 return cmux->n_active_circuits;
710 * Query total number of circuits attached to a circuitmux
713 unsigned int
714 circuitmux_num_circuits(circuitmux_t *cmux)
716 tor_assert(cmux);
718 return cmux->n_circuits;
722 * Functions for circuit code to call to update circuit status
726 * Attach a circuit to a circuitmux, for the specified direction.
729 MOCK_IMPL(void,
730 circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
731 cell_direction_t direction))
733 channel_t *chan = NULL;
734 uint64_t channel_id;
735 circid_t circ_id;
736 chanid_circid_muxinfo_t search, *hashent = NULL;
737 unsigned int cell_count;
739 tor_assert(cmux);
740 tor_assert(circ);
741 tor_assert(direction == CELL_DIRECTION_IN ||
742 direction == CELL_DIRECTION_OUT);
745 * Figure out which channel we're using, and get the circuit's current
746 * cell count and circuit ID; assert that the circuit is not already
747 * attached to another mux.
749 if (direction == CELL_DIRECTION_OUT) {
750 /* It's n_chan */
751 chan = circ->n_chan;
752 cell_count = circ->n_chan_cells.n;
753 circ_id = circ->n_circ_id;
754 } else {
755 /* We want p_chan */
756 chan = TO_OR_CIRCUIT(circ)->p_chan;
757 cell_count = TO_OR_CIRCUIT(circ)->p_chan_cells.n;
758 circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
760 /* Assert that we did get a channel */
761 tor_assert(chan);
762 /* Assert that the circuit ID is sensible */
763 tor_assert(circ_id != 0);
765 /* Get the channel ID */
766 channel_id = chan->global_identifier;
768 /* See if we already have this one */
769 search.chan_id = channel_id;
770 search.circ_id = circ_id;
771 hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
772 &search);
774 if (hashent) {
776 * This circuit was already attached to this cmux; make sure the
777 * directions match and update the cell count and active circuit count.
779 log_info(LD_CIRC,
780 "Circuit %u on channel %"PRIu64 " was already attached to "
781 "(trying to attach to %p)",
782 (unsigned)circ_id, (channel_id),
783 cmux);
786 * The mux pointer on this circuit and the direction in result should
787 * match; otherwise assert.
789 tor_assert(hashent->muxinfo.direction == direction);
792 * Looks okay; just update the cell count and active circuits if we must
794 if (hashent->muxinfo.cell_count > 0 && cell_count == 0) {
795 --(cmux->n_active_circuits);
796 circuitmux_make_circuit_inactive(cmux, circ);
797 } else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) {
798 ++(cmux->n_active_circuits);
799 circuitmux_make_circuit_active(cmux, circ);
801 cmux->n_cells -= hashent->muxinfo.cell_count;
802 cmux->n_cells += cell_count;
803 hashent->muxinfo.cell_count = cell_count;
804 } else {
806 * New circuit; add an entry and update the circuit/active circuit
807 * counts.
809 log_debug(LD_CIRC,
810 "Attaching circuit %u on channel %"PRIu64 " to cmux %p",
811 (unsigned)circ_id, (channel_id), cmux);
813 /* Insert it in the map */
814 hashent = tor_malloc_zero(sizeof(*hashent));
815 hashent->chan_id = channel_id;
816 hashent->circ_id = circ_id;
817 hashent->muxinfo.cell_count = cell_count;
818 hashent->muxinfo.direction = direction;
819 /* Allocate policy specific circuit data if we need it */
820 if (cmux->policy->alloc_circ_data) {
821 /* Assert that we have the means to free policy-specific data */
822 tor_assert(cmux->policy->free_circ_data);
823 /* Allocate it */
824 hashent->muxinfo.policy_data =
825 cmux->policy->alloc_circ_data(cmux,
826 cmux->policy_data,
827 circ,
828 direction,
829 cell_count);
830 /* If we wanted policy data, it's an error not to get any */
831 tor_assert(hashent->muxinfo.policy_data);
833 HT_INSERT(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
834 hashent);
836 /* Update counters */
837 ++(cmux->n_circuits);
838 if (cell_count > 0) {
839 ++(cmux->n_active_circuits);
840 circuitmux_make_circuit_active(cmux, circ);
842 cmux->n_cells += cell_count;
847 * Detach a circuit from a circuitmux and update all counters as needed;
848 * no-op if not attached.
851 MOCK_IMPL(void,
852 circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
854 chanid_circid_muxinfo_t search, *hashent = NULL;
856 * Use this to keep track of whether we found it for n_chan or
857 * p_chan for consistency checking.
859 * The 0 initializer is not a valid cell_direction_t value.
860 * We assert that it has been replaced with a valid value before it is used.
862 cell_direction_t last_searched_direction = 0;
864 tor_assert(cmux);
865 tor_assert(cmux->chanid_circid_map);
866 tor_assert(circ);
868 /* See if we have it for n_chan/n_circ_id */
869 if (circ->n_chan) {
870 search.chan_id = circ->n_chan->global_identifier;
871 search.circ_id = circ->n_circ_id;
872 hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
873 &search);
874 last_searched_direction = CELL_DIRECTION_OUT;
877 /* Got one? If not, see if it's an or_circuit_t and try p_chan/p_circ_id */
878 if (!hashent) {
879 if (circ->magic == OR_CIRCUIT_MAGIC) {
880 search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
881 if (TO_OR_CIRCUIT(circ)->p_chan) {
882 search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier;
883 hashent = HT_FIND(chanid_circid_muxinfo_map,
884 cmux->chanid_circid_map,
885 &search);
886 last_searched_direction = CELL_DIRECTION_IN;
891 tor_assert(last_searched_direction == CELL_DIRECTION_OUT
892 || last_searched_direction == CELL_DIRECTION_IN);
895 * If hashent isn't NULL, we have a circuit to detach; don't remove it from
896 * the map until later of circuitmux_make_circuit_inactive() breaks.
898 if (hashent) {
899 /* Update counters */
900 --(cmux->n_circuits);
901 if (hashent->muxinfo.cell_count > 0) {
902 --(cmux->n_active_circuits);
903 /* This does policy notifies, so comes before freeing policy data */
904 circuitmux_make_circuit_inactive(cmux, circ);
906 cmux->n_cells -= hashent->muxinfo.cell_count;
908 /* Free policy-specific data if we have it */
909 if (hashent->muxinfo.policy_data) {
910 /* If we have policy data, assert that we have the means to free it */
911 tor_assert(cmux->policy);
912 tor_assert(cmux->policy->free_circ_data);
913 /* Call free_circ_data() */
914 cmux->policy->free_circ_data(cmux,
915 cmux->policy_data,
916 circ,
917 hashent->muxinfo.policy_data);
918 hashent->muxinfo.policy_data = NULL;
921 /* Consistency check: the direction must match the direction searched */
922 tor_assert(last_searched_direction == hashent->muxinfo.direction);
924 /* Now remove it from the map */
925 HT_REMOVE(chanid_circid_muxinfo_map, cmux->chanid_circid_map, hashent);
927 /* Wipe and free the hash entry */
928 // This isn't sensitive, but we want to be sure to know if we're accessing
929 // this accidentally.
930 memwipe(hashent, 0xef, sizeof(*hashent));
931 tor_free(hashent);
936 * Make a circuit active; update active list and policy-specific info, but
937 * we don't mess with the counters or hash table here.
940 static void
941 circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
943 tor_assert(cmux);
944 tor_assert(cmux->policy);
945 tor_assert(circ);
947 /* Policy-specific notification */
948 if (cmux->policy->notify_circ_active) {
949 /* Okay, we need to check the circuit for policy data now */
950 chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
951 /* We should have found something */
952 tor_assert(hashent);
953 /* Notify */
954 cmux->policy->notify_circ_active(cmux, cmux->policy_data,
955 circ, hashent->muxinfo.policy_data);
960 * Make a circuit inactive; update active list and policy-specific info, but
961 * we don't mess with the counters or hash table here.
964 static void
965 circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ)
967 tor_assert(cmux);
968 tor_assert(cmux->policy);
969 tor_assert(circ);
971 /* Policy-specific notification */
972 if (cmux->policy->notify_circ_inactive) {
973 /* Okay, we need to check the circuit for policy data now */
974 chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
975 /* We should have found something */
976 tor_assert(hashent);
977 /* Notify */
978 cmux->policy->notify_circ_inactive(cmux, cmux->policy_data,
979 circ, hashent->muxinfo.policy_data);
984 * Clear the cell counter for a circuit on a circuitmux
987 void
988 circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ)
990 /* This is the same as setting the cell count to zero */
991 circuitmux_set_num_cells(cmux, circ, 0);
995 * Set the cell counter for a circuit on a circuitmux
998 void
999 circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
1000 unsigned int n_cells)
1002 chanid_circid_muxinfo_t *hashent = NULL;
1004 tor_assert(cmux);
1005 tor_assert(circ);
1007 /* Search for this circuit's entry */
1008 hashent = circuitmux_find_map_entry(cmux, circ);
1009 /* Assert that we found one */
1010 tor_assert(hashent);
1012 /* Update cmux cell counter */
1013 cmux->n_cells -= hashent->muxinfo.cell_count;
1014 cmux->n_cells += n_cells;
1016 /* Do we need to notify a cmux policy? */
1017 if (cmux->policy->notify_set_n_cells) {
1018 /* Call notify_set_n_cells */
1019 cmux->policy->notify_set_n_cells(cmux,
1020 cmux->policy_data,
1021 circ,
1022 hashent->muxinfo.policy_data,
1023 n_cells);
1027 * Update cmux active circuit counter: is the old cell count > 0 and the
1028 * new cell count == 0 ?
1030 if (hashent->muxinfo.cell_count > 0 && n_cells == 0) {
1031 --(cmux->n_active_circuits);
1032 hashent->muxinfo.cell_count = n_cells;
1033 circuitmux_make_circuit_inactive(cmux, circ);
1034 /* Is the old cell count == 0 and the new cell count > 0 ? */
1035 } else if (hashent->muxinfo.cell_count == 0 && n_cells > 0) {
1036 ++(cmux->n_active_circuits);
1037 hashent->muxinfo.cell_count = n_cells;
1038 circuitmux_make_circuit_active(cmux, circ);
1039 } else {
1040 hashent->muxinfo.cell_count = n_cells;
1045 * Functions for channel code to call to get a circuit to transmit from or
1046 * notify that cells have been transmitted.
1050 * Pick a circuit to send from, using the active circuits list or a
1051 * circuitmux policy if one is available. This is called from channel.c.
1053 * If we would rather send a destroy cell, return NULL and set
1054 * *<b>destroy_queue_out</b> to the destroy queue.
1056 * If we have nothing to send, set *<b>destroy_queue_out</b> to NULL and
1057 * return NULL.
1060 circuit_t *
1061 circuitmux_get_first_active_circuit(circuitmux_t *cmux,
1062 destroy_cell_queue_t **destroy_queue_out)
1064 circuit_t *circ = NULL;
1066 tor_assert(cmux);
1067 tor_assert(cmux->policy);
1068 /* This callback is mandatory. */
1069 tor_assert(cmux->policy->pick_active_circuit);
1070 tor_assert(destroy_queue_out);
1072 *destroy_queue_out = NULL;
1074 if (cmux->destroy_cell_queue.n &&
1075 (!cmux->last_cell_was_destroy || cmux->n_active_circuits == 0)) {
1076 /* We have destroy cells to send, and either we just sent a relay cell,
1077 * or we have no relay cells to send. */
1079 /* XXXX We should let the cmux policy have some say in this eventually. */
1080 /* XXXX Alternating is not a terribly brilliant approach here. */
1081 *destroy_queue_out = &cmux->destroy_cell_queue;
1083 cmux->last_cell_was_destroy = 1;
1084 } else if (cmux->n_active_circuits > 0) {
1085 /* We also must have a cell available for this to be the case */
1086 tor_assert(cmux->n_cells > 0);
1087 /* Do we have a policy-provided circuit selector? */
1088 circ = cmux->policy->pick_active_circuit(cmux, cmux->policy_data);
1089 cmux->last_cell_was_destroy = 0;
1090 } else {
1091 tor_assert(cmux->n_cells == 0);
1092 tor_assert(cmux->destroy_cell_queue.n == 0);
1095 return circ;
1099 * Notify the circuitmux that cells have been sent on a circuit; this
1100 * is called from channel.c.
1103 void
1104 circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
1105 unsigned int n_cells)
1107 chanid_circid_muxinfo_t *hashent = NULL;
1108 int becomes_inactive = 0;
1110 tor_assert(cmux);
1111 tor_assert(circ);
1113 if (n_cells == 0) return;
1116 * To handle this, we have to:
1118 * 1.) Adjust the circuit's cell counter in the cmux hash table
1119 * 2.) Move the circuit to the tail of the active_circuits linked list
1120 * for this cmux, or make the circuit inactive if the cell count
1121 * went to zero.
1122 * 3.) Call cmux->policy->notify_xmit_cells(), if any
1125 /* Find the hash entry */
1126 hashent = circuitmux_find_map_entry(cmux, circ);
1127 /* Assert that we found one */
1128 tor_assert(hashent);
1130 /* Adjust the cell counter and assert that we had that many cells to send */
1131 tor_assert(n_cells <= hashent->muxinfo.cell_count);
1132 hashent->muxinfo.cell_count -= n_cells;
1133 /* Do we need to make the circuit inactive? */
1134 if (hashent->muxinfo.cell_count == 0) becomes_inactive = 1;
1135 /* Adjust the mux cell counter */
1136 cmux->n_cells -= n_cells;
1139 * We call notify_xmit_cells() before making the circuit inactive if needed,
1140 * so the policy can always count on this coming in on an active circuit.
1142 if (cmux->policy->notify_xmit_cells) {
1143 cmux->policy->notify_xmit_cells(cmux, cmux->policy_data, circ,
1144 hashent->muxinfo.policy_data,
1145 n_cells);
1149 * Now make the circuit inactive if needed; this will call the policy's
1150 * notify_circ_inactive() if present.
1152 if (becomes_inactive) {
1153 --(cmux->n_active_circuits);
1154 circuitmux_make_circuit_inactive(cmux, circ);
1159 * Notify the circuitmux that a destroy was sent, so we can update
1160 * the counter.
1163 void
1164 circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
1166 tor_assert(cmux);
1168 --(cmux->destroy_ctr);
1169 --(global_destroy_ctr);
1170 log_debug(LD_CIRC,
1171 "Cmux at %p sent a destroy, cmux counter is now %"PRId64", "
1172 "global counter is now %"PRId64,
1173 cmux,
1174 (cmux->destroy_ctr),
1175 (global_destroy_ctr));
1178 /*DOCDOC */
1179 void
1180 circuitmux_append_destroy_cell(channel_t *chan,
1181 circuitmux_t *cmux,
1182 circid_t circ_id,
1183 uint8_t reason)
1185 destroy_cell_queue_append(&cmux->destroy_cell_queue, circ_id, reason);
1187 /* Destroy entering the queue, update counters */
1188 ++(cmux->destroy_ctr);
1189 ++global_destroy_ctr;
1190 log_debug(LD_CIRC,
1191 "Cmux at %p queued a destroy for circ %u, cmux counter is now "
1192 "%"PRId64", global counter is now %"PRId64,
1193 cmux, circ_id,
1194 (cmux->destroy_ctr),
1195 (global_destroy_ctr));
1197 /* XXXX Duplicate code from append_cell_to_circuit_queue */
1198 if (!channel_has_queued_writes(chan)) {
1199 /* There is no data at all waiting to be sent on the outbuf. Add a
1200 * cell, so that we can notice when it gets flushed, flushed_some can
1201 * get called, and we can start putting more data onto the buffer then.
1203 log_debug(LD_GENERAL, "Primed a buffer.");
1204 channel_flush_from_first_active_circuit(chan, 1);
1208 /*DOCDOC; for debugging 12184. This runs slowly. */
1209 int64_t
1210 circuitmux_count_queued_destroy_cells(const channel_t *chan,
1211 const circuitmux_t *cmux)
1213 int64_t n_destroy_cells = cmux->destroy_ctr;
1214 int64_t destroy_queue_size = cmux->destroy_cell_queue.n;
1216 int64_t manual_total = 0;
1217 int64_t manual_total_in_map = 0;
1218 destroy_cell_t *cell;
1220 TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
1221 circid_t id;
1222 ++manual_total;
1224 id = cell->circid;
1225 if (circuit_id_in_use_on_channel(id, (channel_t*)chan))
1226 ++manual_total_in_map;
1229 if (n_destroy_cells != destroy_queue_size ||
1230 n_destroy_cells != manual_total ||
1231 n_destroy_cells != manual_total_in_map) {
1232 log_warn(LD_BUG, " Discrepancy in counts for queued destroy cells on "
1233 "circuitmux. n=%"PRId64". queue_size=%"PRId64". "
1234 "manual_total=%"PRId64". manual_total_in_map=%"PRId64".",
1235 (n_destroy_cells),
1236 (destroy_queue_size),
1237 (manual_total),
1238 (manual_total_in_map));
1241 return n_destroy_cells;
1245 * Compare cmuxes to see which is more preferred; return < 0 if
1246 * cmux_1 has higher priority (i.e., cmux_1 < cmux_2 in the scheduler's
1247 * sort order), > 0 if cmux_2 has higher priority, or 0 if they are
1248 * equally preferred.
1250 * If the cmuxes have different cmux policies or the policy does not
1251 * support the cmp_cmux method, return 0.
1254 MOCK_IMPL(int,
1255 circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2))
1257 const circuitmux_policy_t *policy;
1259 tor_assert(cmux_1);
1260 tor_assert(cmux_2);
1262 if (cmux_1 == cmux_2) {
1263 /* Equivalent because they're the same cmux */
1264 return 0;
1267 if (cmux_1->policy && cmux_2->policy) {
1268 if (cmux_1->policy == cmux_2->policy) {
1269 policy = cmux_1->policy;
1271 if (policy->cmp_cmux) {
1272 /* Okay, we can compare! */
1273 return policy->cmp_cmux(cmux_1, cmux_1->policy_data,
1274 cmux_2, cmux_2->policy_data);
1275 } else {
1277 * Equivalent because the policy doesn't know how to compare between
1278 * muxes.
1280 return 0;
1282 } else {
1283 /* Equivalent because they have different policies */
1284 return 0;
1286 } else {
1287 /* Equivalent because one or both are missing a policy */
1288 return 0;