Tor  0.4.8.0-alpha-dev
circuitmux.c
Go to the documentation of this file.
1 /* * Copyright (c) 2012-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
4 /**
5  * \file circuitmux.c
6  * \brief Circuit mux/cell selection abstraction
7  *
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.
12  *
13  * There can be different implementations of the circuitmux's rules (which
14  * decide which circuit is next to write).
15  *
16  * A circuitmux exposes three distinct
17  * interfaces to other components:
18  *
19  * To channels, which each have a circuitmux_t, the supported operations
20  * (invoked from relay.c) are:
21  *
22  * circuitmux_get_first_active_circuit():
23  *
24  * Pick one of the circuitmux's active circuits to send cells from.
25  *
26  * circuitmux_notify_xmit_cells():
27  *
28  * Notify the circuitmux that cells have been sent on a circuit.
29  *
30  * To circuits, the exposed operations are:
31  *
32  * circuitmux_attach_circuit():
33  *
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.
37  *
38  * circuitmux_detach_circuit():
39  *
40  * Detach a circuit from the circuitmux, freeing associated structures.
41  *
42  * circuitmux_clear_num_cells():
43  *
44  * Clear the circuitmux's cell counter for this circuit.
45  *
46  * circuitmux_set_num_cells():
47  *
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.
51  *
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:
56  *
57  * circuitmux_get_policy():
58  *
59  * Return the current policy for a circuitmux_t, if any.
60  *
61  * circuitmux_clear_policy():
62  *
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.
65  *
66  * circuitmux_set_policy():
67  *
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  **/
71 
72 #define CIRCUITMUX_PRIVATE
73 
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"
79 
80 #include "core/or/or_circuit_st.h"
81 
83 
84 /*
85  * Private typedefs for circuitmux.c
86  */
87 
88 /*
89  * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
90  * break the hash table code).
91  */
93 
94 /*
95  * Anything the mux wants to store per-circuit in the map; right now just
96  * a count of queued cells.
97  */
98 
100 
101 /*
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.
104  */
105 
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;
115 };
116 
117 /*
118  * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
119  * circuit.
120  */
121 
123  HT_ENTRY(chanid_circid_muxinfo_t) node;
124  uint64_t chan_id;
125  circid_t circ_id;
126  circuit_muxinfo_t muxinfo;
127 };
128 
129 /*
130  * Static function declarations
131  */
132 
133 static inline int
136 static inline unsigned int
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);
144 
145 /* Static global variables */
146 
147 /** Count the destroy balance to debug destroy queue logic */
148 static int64_t global_destroy_ctr = 0;
149 
150 /* Function definitions */
151 
152 /**
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.
156  */
157 
158 static inline int
161 {
162  return a->chan_id == b->chan_id && a->circ_id == b->circ_id;
163 }
164 
165 /**
166  * Helper: return a hash based on circuit ID and channel ID in a.
167  */
168 
169 static inline unsigned int
171 {
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));
176 }
177 
178 /* Emit a bunch of hash table stuff */
179 HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
181 HT_GENERATE2(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
184 
185 /*
186  * Circuitmux alloc/free functions
187  */
188 
189 /**
190  * Allocate a new circuitmux_t
191  */
192 
193 circuitmux_t *
195 {
196  circuitmux_t *rv = NULL;
197 
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);
202 
203  return rv;
204 }
205 
206 /**
207  * Detach all circuits from a circuitmux (use before circuitmux_free())
208  *
209  * If <b>detached_out</b> is non-NULL, add every detached circuit_t to
210  * detached_out.
211  */
212 
213 void
214 circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
215 {
216  chanid_circid_muxinfo_t **i = NULL, *to_remove;
217  channel_t *chan = NULL;
218  circuit_t *circ = NULL;
219 
220  tor_assert(cmux);
221 
222  i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
223  while (i) {
224  to_remove = *i;
225 
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 =
235  chan);
236  if (circ) {
237  /* Clear the circuit's mux for this direction */
238  if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) {
239  /*
240  * Update active_circuits et al.; this does policy notifies, so
241  * comes before freeing policy data
242  */
243 
244  if (to_remove->muxinfo.cell_count > 0) {
246  }
247 
248  if (detached_out)
249  smartlist_add(detached_out, circ);
250  } else if (circ->magic == OR_CIRCUIT_MAGIC) {
251  /*
252  * Update active_circuits et al.; this does policy notifies, so
253  * comes before freeing policy data
254  */
255 
256  if (to_remove->muxinfo.cell_count > 0) {
258  }
259 
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));
269  }
270 
271  /* Free policy-specific data if we have it */
272  if (to_remove->muxinfo.policy_data) {
273  /*
274  * If we have policy data, assert that we have the means to
275  * free it
276  */
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;
285  }
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));
292  }
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);
299  }
300 
301  /* Assert that we don't have un-freed policy data for this circuit */
302  tor_assert(to_remove->muxinfo.policy_data == NULL);
303  }
304 
305  i = HT_NEXT_RMV(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
306 
307  /* Free it */
308  tor_free(to_remove);
309  }
310 
311  cmux->n_circuits = 0;
312  cmux->n_active_circuits = 0;
313  cmux->n_cells = 0;
314 }
315 
316 /** Reclaim all circuit IDs currently marked as unusable on <b>chan</b> because
317  * of pending destroy cells in <b>cmux</b>.
318  *
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().
322  */
323 void
325 {
326  destroy_cell_t *cell;
327  TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
328  channel_mark_circid_usable(chan, cell->circid);
329  }
330 }
331 
332 /**
333  * Free a circuitmux_t; the circuits must be detached first with
334  * circuitmux_detach_all_circuits().
335  */
336 
337 void
338 circuitmux_free_(circuitmux_t *cmux)
339 {
340  if (!cmux) return;
341 
342  tor_assert(cmux->n_circuits == 0);
343  tor_assert(cmux->n_active_circuits == 0);
344 
345  /*
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.
351  */
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;
356  }
357  } else tor_assert(cmux->policy_data == NULL);
358 
359  if (cmux->chanid_circid_map) {
360  HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
361  tor_free(cmux->chanid_circid_map);
362  }
363 
364  /*
365  * We're throwing away some destroys; log the counter and
366  * adjust the global counter by the queue size.
367  */
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),
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),
384  }
385 
386  destroy_cell_queue_clear(&cmux->destroy_cell_queue);
387 
388  tor_free(cmux);
389 }
390 
391 /*
392  * Circuitmux policy control functions
393  */
394 
395 /**
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.
399  */
400 
401 void
402 circuitmux_clear_policy(circuitmux_t *cmux)
403 {
404  tor_assert(cmux);
405 
406  /* Internally, this is just setting policy to NULL */
407  circuitmux_set_policy(cmux, NULL);
408 }
409 
410 /**
411  * Return the policy currently installed on a circuitmux_t
412  */
413 
415 circuitmux_get_policy, (circuitmux_t *cmux))
416 {
417  tor_assert(cmux);
418 
419  return cmux->policy;
420 }
421 
422 /**
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.
425  */
426 
427 void
428 circuitmux_set_policy(circuitmux_t *cmux,
429  const circuitmux_policy_t *pol)
430 {
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;
437 
438  tor_assert(cmux);
439 
440  /* Set up variables */
441  old_pol = cmux->policy;
442  old_pol_data = cmux->policy_data;
443  new_pol = pol;
444 
445  /* Check if this is the trivial case */
446  if (old_pol == new_pol) return;
447 
448  /* Allocate data for new policy, if any */
449  if (new_pol && new_pol->alloc_cmux_data) {
450  /*
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.
454  */
455  tor_assert(new_pol->free_cmux_data);
456  new_pol_data = new_pol->alloc_cmux_data(cmux);
457  tor_assert(new_pol_data);
458  }
459 
460  /* Install new policy and new policy data on cmux */
461  cmux->policy = new_pol;
462  cmux->policy_data = new_pol_data;
463 
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);
469 
470  /*
471  * Get the channel; since normal case is all circuits on the mux share a
472  * channel, we cache last_chan_id_searched
473  */
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;
477  }
478  tor_assert(chan);
479 
480  /* Get the circuit */
481  circ = circuit_get_by_circid_channel_even_if_marked((*i)->circ_id, chan);
482  tor_assert(circ);
483 
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);
489  }
490 
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;
500  }
501 
502  /* Need to allocate new policy data? */
503  if (new_pol && new_pol->alloc_circ_data) {
504  /*
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.
508  */
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);
514  }
515 
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);
521  }
522 
523  /* Advance to next circuit map entry */
524  i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
525  }
526 
527  /* Free data for old policy, if any */
528  if (old_pol_data) {
529  /*
530  * If we had old policy data, we should have an old policy and a free
531  * function for it.
532  */
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;
537  }
538 }
539 
540 /*
541  * Circuitmux/circuit attachment status inquiry functions
542  */
543 
544 /**
545  * Query the direction of an attached circuit
546  */
547 
550 {
551  chanid_circid_muxinfo_t *hashent = NULL;
552 
553  /* Try to find a map entry */
554  hashent = circuitmux_find_map_entry(cmux, circ);
555 
556  /*
557  * This function should only be called on attached circuits; assert that
558  * we had a map entry.
559  */
560  tor_assert(hashent);
561 
562  /* Return the direction from the map entry */
563  return hashent->muxinfo.direction;
564 }
565 
566 /**
567  * Find an entry in the cmux's map for this circuit or return NULL if there
568  * is none.
569  */
570 
572 circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ)
573 {
574  chanid_circid_muxinfo_t search, *hashent = NULL;
575 
576  /* Sanity-check parameters */
577  tor_assert(cmux);
578  tor_assert(cmux->chanid_circid_map);
579  tor_assert(circ);
580 
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;
586 
587  /* Query */
588  hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
589  &search);
590  }
591 
592  /* Found something? */
593  if (hashent) {
594  /*
595  * Assert that the direction makes sense for a hashent we found by
596  * n_chan/n_circ_id before we return it.
597  */
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);
613  }
614  }
615  }
616  }
617 
618  /* Okay, hashent is it if it was there */
619  return hashent;
620 }
621 
622 /**
623  * Query whether a circuit is attached to a circuitmux
624  */
625 
626 int
627 circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
628 {
629  chanid_circid_muxinfo_t *hashent = NULL;
630 
631  /* Look if it's in the circuit map */
632  hashent = circuitmux_find_map_entry(cmux, circ);
633 
634  return (hashent != NULL);
635 }
636 
637 /**
638  * Query whether a circuit is active on a circuitmux
639  */
640 
641 int
642 circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ)
643 {
644  chanid_circid_muxinfo_t *hashent = NULL;
645  int is_active = 0;
646 
647  tor_assert(cmux);
648  tor_assert(circ);
649 
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);
655  }
656  /* else not attached, so not active */
657 
658  return is_active;
659 }
660 
661 /**
662  * Query number of available cells for a circuit on a circuitmux
663  */
664 
665 unsigned int
666 circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ)
667 {
668  chanid_circid_muxinfo_t *hashent = NULL;
669  unsigned int n_cells = 0;
670 
671  tor_assert(cmux);
672  tor_assert(circ);
673 
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;
679  }
680  /* else not attached, so 0 cells */
681 
682  return n_cells;
683 }
684 
685 /**
686  * Query total number of available cells on a circuitmux
687  */
688 
689 MOCK_IMPL(unsigned int,
690 circuitmux_num_cells, (circuitmux_t *cmux))
691 {
692  tor_assert(cmux);
693 
694  return cmux->n_cells + cmux->destroy_cell_queue.n;
695 }
696 
697 /**
698  * Query total number of circuits active on a circuitmux
699  */
700 
701 unsigned int
703 {
704  tor_assert(cmux);
705 
706  return cmux->n_active_circuits;
707 }
708 
709 /**
710  * Query total number of circuits attached to a circuitmux
711  */
712 
713 unsigned int
714 circuitmux_num_circuits(circuitmux_t *cmux)
715 {
716  tor_assert(cmux);
717 
718  return cmux->n_circuits;
719 }
720 
721 /*
722  * Functions for circuit code to call to update circuit status
723  */
724 
725 /**
726  * Attach a circuit to a circuitmux, for the specified direction.
727  */
728 
729 MOCK_IMPL(void,
730 circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
731  cell_direction_t direction))
732 {
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;
738 
739  tor_assert(cmux);
740  tor_assert(circ);
741  tor_assert(direction == CELL_DIRECTION_IN ||
742  direction == CELL_DIRECTION_OUT);
743 
744  /*
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.
748  */
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;
759  }
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);
764 
765  /* Get the channel ID */
766  channel_id = chan->global_identifier;
767 
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);
773 
774  if (hashent) {
775  /*
776  * This circuit was already attached to this cmux; make sure the
777  * directions match and update the cell count and active circuit count.
778  */
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);
784 
785  /*
786  * The mux pointer on this circuit and the direction in result should
787  * match; otherwise assert.
788  */
789  tor_assert(hashent->muxinfo.direction == direction);
790 
791  /*
792  * Looks okay; just update the cell count and active circuits if we must
793  */
794  if (hashent->muxinfo.cell_count > 0 && cell_count == 0) {
795  --(cmux->n_active_circuits);
797  } else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) {
798  ++(cmux->n_active_circuits);
799  circuitmux_make_circuit_active(cmux, circ);
800  }
801  cmux->n_cells -= hashent->muxinfo.cell_count;
802  cmux->n_cells += cell_count;
803  hashent->muxinfo.cell_count = cell_count;
804  } else {
805  /*
806  * New circuit; add an entry and update the circuit/active circuit
807  * counts.
808  */
809  log_debug(LD_CIRC,
810  "Attaching circuit %u on channel %"PRIu64 " to cmux %p",
811  (unsigned)circ_id, (channel_id), cmux);
812 
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);
832  }
833  HT_INSERT(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
834  hashent);
835 
836  /* Update counters */
837  ++(cmux->n_circuits);
838  if (cell_count > 0) {
839  ++(cmux->n_active_circuits);
840  circuitmux_make_circuit_active(cmux, circ);
841  }
842  cmux->n_cells += cell_count;
843  }
844 }
845 
846 /**
847  * Detach a circuit from a circuitmux and update all counters as needed;
848  * no-op if not attached.
849  */
850 
851 MOCK_IMPL(void,
852 circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
853 {
854  chanid_circid_muxinfo_t search, *hashent = NULL;
855  /*
856  * Use this to keep track of whether we found it for n_chan or
857  * p_chan for consistency checking.
858  *
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.
861  */
862  cell_direction_t last_searched_direction = 0;
863 
864  tor_assert(cmux);
865  tor_assert(cmux->chanid_circid_map);
866  tor_assert(circ);
867 
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;
875  }
876 
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;
887  }
888  }
889  }
890 
891  tor_assert(last_searched_direction == CELL_DIRECTION_OUT
892  || last_searched_direction == CELL_DIRECTION_IN);
893 
894  /*
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.
897  */
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 */
905  }
906  cmux->n_cells -= hashent->muxinfo.cell_count;
907 
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;
919  }
920 
921  /* Consistency check: the direction must match the direction searched */
922  tor_assert(last_searched_direction == hashent->muxinfo.direction);
923 
924  /* Now remove it from the map */
925  HT_REMOVE(chanid_circid_muxinfo_map, cmux->chanid_circid_map, hashent);
926 
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);
932  }
933 }
934 
935 /**
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.
938  */
939 
940 static void
941 circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
942 {
943  tor_assert(cmux);
944  tor_assert(cmux->policy);
945  tor_assert(circ);
946 
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);
956  }
957 }
958 
959 /**
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.
962  */
963 
964 static void
965 circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ)
966 {
967  tor_assert(cmux);
968  tor_assert(cmux->policy);
969  tor_assert(circ);
970 
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);
980  }
981 }
982 
983 /**
984  * Clear the cell counter for a circuit on a circuitmux
985  */
986 
987 void
988 circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ)
989 {
990  /* This is the same as setting the cell count to zero */
991  circuitmux_set_num_cells(cmux, circ, 0);
992 }
993 
994 /**
995  * Set the cell counter for a circuit on a circuitmux
996  */
997 
998 void
999 circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
1000  unsigned int n_cells)
1001 {
1002  chanid_circid_muxinfo_t *hashent = NULL;
1003 
1004  tor_assert(cmux);
1005  tor_assert(circ);
1006 
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);
1011 
1012  /* Update cmux cell counter */
1013  cmux->n_cells -= hashent->muxinfo.cell_count;
1014  cmux->n_cells += n_cells;
1015 
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);
1024  }
1025 
1026  /*
1027  * Update cmux active circuit counter: is the old cell count > 0 and the
1028  * new cell count == 0 ?
1029  */
1030  if (hashent->muxinfo.cell_count > 0 && n_cells == 0) {
1031  --(cmux->n_active_circuits);
1032  hashent->muxinfo.cell_count = n_cells;
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;
1041  }
1042 }
1043 
1044 /*
1045  * Functions for channel code to call to get a circuit to transmit from or
1046  * notify that cells have been transmitted.
1047  */
1048 
1049 /**
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.
1052  *
1053  * If we would rather send a destroy cell, return NULL and set
1054  * *<b>destroy_queue_out</b> to the destroy queue.
1055  *
1056  * If we have nothing to send, set *<b>destroy_queue_out</b> to NULL and
1057  * return NULL.
1058  */
1059 
1060 circuit_t *
1062  destroy_cell_queue_t **destroy_queue_out)
1063 {
1064  circuit_t *circ = NULL;
1065 
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);
1071 
1072  *destroy_queue_out = NULL;
1073 
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. */
1078 
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;
1082 
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);
1093  }
1094 
1095  return circ;
1096 }
1097 
1098 /**
1099  * Notify the circuitmux that cells have been sent on a circuit; this
1100  * is called from channel.c.
1101  */
1102 
1103 void
1104 circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
1105  unsigned int n_cells)
1106 {
1107  chanid_circid_muxinfo_t *hashent = NULL;
1108  int becomes_inactive = 0;
1109 
1110  tor_assert(cmux);
1111  tor_assert(circ);
1112 
1113  if (n_cells == 0) return;
1114 
1115  /*
1116  * To handle this, we have to:
1117  *
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
1123  */
1124 
1125  /* Find the hash entry */
1126  hashent = circuitmux_find_map_entry(cmux, circ);
1127  /* Assert that we found one */
1128  tor_assert(hashent);
1129 
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;
1137 
1138  /*
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.
1141  */
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);
1146  }
1147 
1148  /*
1149  * Now make the circuit inactive if needed; this will call the policy's
1150  * notify_circ_inactive() if present.
1151  */
1152  if (becomes_inactive) {
1153  --(cmux->n_active_circuits);
1155  }
1156 }
1157 
1158 /**
1159  * Notify the circuitmux that a destroy was sent, so we can update
1160  * the counter.
1161  */
1162 
1163 void
1165 {
1166  tor_assert(cmux);
1167 
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));
1176 }
1177 
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)
1184 {
1185  destroy_cell_queue_append(&cmux->destroy_cell_queue, circ_id, reason);
1186 
1187  /* Destroy entering the queue, update counters */
1188  ++(cmux->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));
1196 
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.
1202  */
1203  log_debug(LD_GENERAL, "Primed a buffer.");
1205  }
1206 }
1207 
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)
1212 {
1213  int64_t n_destroy_cells = cmux->destroy_ctr;
1214  int64_t destroy_queue_size = cmux->destroy_cell_queue.n;
1215 
1216  int64_t manual_total = 0;
1217  int64_t manual_total_in_map = 0;
1218  destroy_cell_t *cell;
1219 
1220  TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
1221  circid_t id;
1222  ++manual_total;
1223 
1224  id = cell->circid;
1225  if (circuit_id_in_use_on_channel(id, (channel_t*)chan))
1226  ++manual_total_in_map;
1227  }
1228 
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));
1239  }
1240 
1241  return n_destroy_cells;
1242 }
1243 
1244 /**
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.
1249  *
1250  * If the cmuxes have different cmux policies or the policy does not
1251  * support the cmp_cmux method, return 0.
1252  */
1253 
1254 MOCK_IMPL(int,
1255 circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2))
1256 {
1257  const circuitmux_policy_t *policy;
1258 
1259  tor_assert(cmux_1);
1260  tor_assert(cmux_2);
1261 
1262  if (cmux_1 == cmux_2) {
1263  /* Equivalent because they're the same cmux */
1264  return 0;
1265  }
1266 
1267  if (cmux_1->policy && cmux_2->policy) {
1268  if (cmux_1->policy == cmux_2->policy) {
1269  policy = cmux_1->policy;
1270 
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 {
1276  /*
1277  * Equivalent because the policy doesn't know how to compare between
1278  * muxes.
1279  */
1280  return 0;
1281  }
1282  } else {
1283  /* Equivalent because they have different policies */
1284  return 0;
1285  }
1286  } else {
1287  /* Equivalent because one or both are missing a policy */
1288  return 0;
1289  }
1290 }
static void set_uint64(void *cp, uint64_t v)
Definition: bytes.h:96
static void set_uint32(void *cp, uint32_t v)
Definition: bytes.h:87
int channel_has_queued_writes(channel_t *chan)
Definition: channel.c:2871
channel_t * channel_find_by_global_id(uint64_t global_identifier)
Definition: channel.c:650
Header file for channel.c.
#define OR_CIRCUIT_MAGIC
Definition: circuit_st.h:33
circuit_t * circuit_get_by_circid_channel_even_if_marked(circid_t circ_id, channel_t *chan)
Definition: circuitlist.c:1538
int circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan)
Definition: circuitlist.c:1552
void channel_mark_circid_usable(channel_t *chan, circid_t id)
Definition: circuitlist.c:397
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:165
Header file for circuitlist.c.
cell_direction_t circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:549
void circuitmux_clear_policy(circuitmux_t *cmux)
Definition: circuitmux.c:402
static unsigned int chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
Definition: circuitmux.c:170
void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, channel_t *chan)
Definition: circuitmux.c:324
void circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
Definition: circuitmux.c:1164
unsigned int circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:666
void circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
Definition: circuitmux.c:214
void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ, unsigned int n_cells)
Definition: circuitmux.c:1104
static void circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:941
void circuitmux_set_policy(circuitmux_t *cmux, const circuitmux_policy_t *pol)
Definition: circuitmux.c:428
int circuitmux_compare_muxes(circuitmux_t *cmux_1, circuitmux_t *cmux_2)
Definition: circuitmux.c:1255
static void circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:965
unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux)
Definition: circuitmux.c:702
void circuitmux_attach_circuit(circuitmux_t *cmux, circuit_t *circ, cell_direction_t direction)
Definition: circuitmux.c:731
unsigned int circuitmux_num_circuits(circuitmux_t *cmux)
Definition: circuitmux.c:714
void circuitmux_detach_circuit(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:852
static chanid_circid_muxinfo_t * circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:572
static int64_t global_destroy_ctr
Definition: circuitmux.c:148
circuitmux_t * circuitmux_alloc(void)
Definition: circuitmux.c:194
int circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:642
void circuitmux_free_(circuitmux_t *cmux)
Definition: circuitmux.c:338
void circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:988
int circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
Definition: circuitmux.c:627
static int chanid_circid_entries_eq(chanid_circid_muxinfo_t *a, chanid_circid_muxinfo_t *b)
Definition: circuitmux.c:159
circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux, destroy_cell_queue_t **destroy_queue_out)
Definition: circuitmux.c:1061
void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ, unsigned int n_cells)
Definition: circuitmux.c:999
unsigned int circuitmux_num_cells(circuitmux_t *cmux)
Definition: circuitmux.c:690
const circuitmux_policy_t * circuitmux_get_policy(circuitmux_t *cmux)
Definition: circuitmux.c:415
Header file for circuitmux.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
HT_PROTOTYPE(hs_circuitmap_ht, circuit_t, hs_circuitmap_node, hs_circuit_hash_token, hs_circuits_have_same_token)
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CIRC
Definition: log.h:82
void tor_free_(void *mem)
Definition: malloc.c:227
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
Definition: malloc.c:146
#define tor_free(p)
Definition: malloc.h:56
Master header file for Tor-specific functionality.
uint32_t circid_t
Definition: or.h:488
cell_direction_t
Definition: or.h:366
@ CELL_DIRECTION_OUT
Definition: or.h:368
@ CELL_DIRECTION_IN
Definition: or.h:367
int channel_flush_from_first_active_circuit(channel_t *chan, int max)
Definition: relay.c:2986
void destroy_cell_queue_init(destroy_cell_queue_t *queue)
Definition: relay.c:2688
void destroy_cell_queue_clear(destroy_cell_queue_t *queue)
Definition: relay.c:2696
void destroy_cell_queue_append(destroy_cell_queue_t *queue, circid_t circid, uint8_t reason)
Definition: relay.c:2722
Header file for relay.c.
void smartlist_add(smartlist_t *sl, void *element)
uint64_t global_identifier
Definition: channel.h:197
cell_queue_t n_chan_cells
Definition: circuit_st.h:82
uint32_t magic
Definition: circuit_st.h:63
channel_t * n_chan
Definition: circuit_st.h:70
circid_t n_circ_id
Definition: circuit_st.h:79
channel_t * p_chan
Definition: or_circuit_st.h:37
circid_t p_circ_id
Definition: or_circuit_st.h:33
cell_queue_t p_chan_cells
Definition: or_circuit_st.h:35
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
#define tor_assert(expr)
Definition: util_bug.h:102