circuitmux.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  1. /* * Copyright (c) 2012-2017, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file circuitmux.c
  5. * \brief Circuit mux/cell selection abstraction
  6. *
  7. * A circuitmux is responsible for <b>MU</b>ltiple<b>X</b>ing all of the
  8. * circuits that are writing on a single channel. It keeps track of which of
  9. * these circuits has something to write (aka, "active" circuits), and which
  10. * one should write next. A circuitmux corresponds 1:1 with a channel.
  11. *
  12. * There can be different implementations of the circuitmux's rules (which
  13. * decide which circuit is next to write).
  14. *
  15. * A circuitmux exposes three distinct
  16. * interfaces to other components:
  17. *
  18. * To channels, which each have a circuitmux_t, the supported operations
  19. * (invoked from relay.c) are:
  20. *
  21. * circuitmux_get_first_active_circuit():
  22. *
  23. * Pick one of the circuitmux's active circuits to send cells from.
  24. *
  25. * circuitmux_notify_xmit_cells():
  26. *
  27. * Notify the circuitmux that cells have been sent on a circuit.
  28. *
  29. * To circuits, the exposed operations are:
  30. *
  31. * circuitmux_attach_circuit():
  32. *
  33. * Attach a circuit to the circuitmux; this will allocate any policy-
  34. * specific data wanted for this circuit and add it to the active
  35. * circuits list if it has queued cells.
  36. *
  37. * circuitmux_detach_circuit():
  38. *
  39. * Detach a circuit from the circuitmux, freeing associated structures.
  40. *
  41. * circuitmux_clear_num_cells():
  42. *
  43. * Clear the circuitmux's cell counter for this circuit.
  44. *
  45. * circuitmux_set_num_cells():
  46. *
  47. * Set the circuitmux's cell counter for this circuit. One of
  48. * circuitmuc_clear_num_cells() or circuitmux_set_num_cells() MUST be
  49. * called when the number of cells queued on a circuit changes.
  50. *
  51. * See circuitmux.h for the circuitmux_policy_t data structure, which contains
  52. * a table of function pointers implementing a circuit selection policy, and
  53. * circuitmux_ewma.c for an example of a circuitmux policy. Circuitmux
  54. * policies can be manipulated with:
  55. *
  56. * circuitmux_get_policy():
  57. *
  58. * Return the current policy for a circuitmux_t, if any.
  59. *
  60. * circuitmux_clear_policy():
  61. *
  62. * Remove a policy installed on a circuitmux_t, freeing all associated
  63. * data. The circuitmux will revert to the built-in round-robin behavior.
  64. *
  65. * circuitmux_set_policy():
  66. *
  67. * Install a policy on a circuitmux_t; the appropriate callbacks will be
  68. * made to attach all existing circuits to the new policy.
  69. **/
  70. #include "or.h"
  71. #include "channel.h"
  72. #include "circuitlist.h"
  73. #include "circuitmux.h"
  74. #include "relay.h"
  75. #include "or_circuit_st.h"
  76. /*
  77. * Private typedefs for circuitmux.c
  78. */
  79. /*
  80. * Map of muxinfos for circuitmux_t to use; struct is defined below (name
  81. * of struct must match HT_HEAD line).
  82. */
  83. typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t;
  84. /*
  85. * Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
  86. * break the hash table code).
  87. */
  88. typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
  89. /*
  90. * Anything the mux wants to store per-circuit in the map; right now just
  91. * a count of queued cells.
  92. */
  93. typedef struct circuit_muxinfo_s circuit_muxinfo_t;
  94. /*
  95. * Structures for circuitmux.c
  96. */
  97. struct circuitmux_s {
  98. /* Keep count of attached, active circuits */
  99. unsigned int n_circuits, n_active_circuits;
  100. /* Total number of queued cells on all circuits */
  101. unsigned int n_cells;
  102. /*
  103. * Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
  104. */
  105. chanid_circid_muxinfo_map_t *chanid_circid_map;
  106. /** List of queued destroy cells */
  107. destroy_cell_queue_t destroy_cell_queue;
  108. /** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
  109. * returned the destroy queue. Used to force alternation between
  110. * destroy/non-destroy cells.
  111. *
  112. * XXXX There is no reason to think that alternating is a particularly good
  113. * approach -- it's just designed to prevent destroys from starving other
  114. * cells completely.
  115. */
  116. unsigned int last_cell_was_destroy : 1;
  117. /** Destroy counter: increment this when a destroy gets queued, decrement
  118. * when we unqueue it, so we can test to make sure they don't starve.
  119. */
  120. int64_t destroy_ctr;
  121. /*
  122. * Circuitmux policy; if this is non-NULL, it can override the built-
  123. * in round-robin active circuits behavior. This is how EWMA works in
  124. * the new circuitmux_t world.
  125. */
  126. const circuitmux_policy_t *policy;
  127. /* Policy-specific data */
  128. circuitmux_policy_data_t *policy_data;
  129. };
  130. /*
  131. * This struct holds whatever we want to store per attached circuit on a
  132. * circuitmux_t; right now, just the count of queued cells and the direction.
  133. */
  134. struct circuit_muxinfo_s {
  135. /* Count of cells on this circuit at last update */
  136. unsigned int cell_count;
  137. /* Direction of flow */
  138. cell_direction_t direction;
  139. /* Policy-specific data */
  140. circuitmux_policy_circ_data_t *policy_data;
  141. /* Mark bit for consistency checker */
  142. unsigned int mark:1;
  143. };
  144. /*
  145. * A map from channel ID and circuit ID to a circuit_muxinfo_t for that
  146. * circuit.
  147. */
  148. struct chanid_circid_muxinfo_t {
  149. HT_ENTRY(chanid_circid_muxinfo_t) node;
  150. uint64_t chan_id;
  151. circid_t circ_id;
  152. circuit_muxinfo_t muxinfo;
  153. };
  154. /*
  155. * Static function declarations
  156. */
  157. static inline int
  158. chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
  159. chanid_circid_muxinfo_t *b);
  160. static inline unsigned int
  161. chanid_circid_entry_hash(chanid_circid_muxinfo_t *a);
  162. static chanid_circid_muxinfo_t *
  163. circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ);
  164. static void
  165. circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ);
  166. static void
  167. circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ);
  168. /* Static global variables */
  169. /** Count the destroy balance to debug destroy queue logic */
  170. static int64_t global_destroy_ctr = 0;
  171. /* Function definitions */
  172. /**
  173. * Helper for chanid_circid_cell_count_map_t hash table: compare the channel
  174. * ID and circuit ID for a and b, and return less than, equal to, or greater
  175. * than zero appropriately.
  176. */
  177. static inline int
  178. chanid_circid_entries_eq(chanid_circid_muxinfo_t *a,
  179. chanid_circid_muxinfo_t *b)
  180. {
  181. return a->chan_id == b->chan_id && a->circ_id == b->circ_id;
  182. }
  183. /**
  184. * Helper: return a hash based on circuit ID and channel ID in a.
  185. */
  186. static inline unsigned int
  187. chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
  188. {
  189. return (((unsigned int)(a->circ_id) << 8) ^
  190. ((unsigned int)((a->chan_id >> 32) & 0xffffffff)) ^
  191. ((unsigned int)(a->chan_id & 0xffffffff)));
  192. }
  193. /* Declare the struct chanid_circid_muxinfo_map type */
  194. HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t);
  195. /* Emit a bunch of hash table stuff */
  196. HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
  197. chanid_circid_entry_hash, chanid_circid_entries_eq)
  198. HT_GENERATE2(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
  199. chanid_circid_entry_hash, chanid_circid_entries_eq, 0.6,
  200. tor_reallocarray_, tor_free_)
  201. /*
  202. * Circuitmux alloc/free functions
  203. */
  204. /**
  205. * Allocate a new circuitmux_t
  206. */
  207. circuitmux_t *
  208. circuitmux_alloc(void)
  209. {
  210. circuitmux_t *rv = NULL;
  211. rv = tor_malloc_zero(sizeof(*rv));
  212. rv->chanid_circid_map = tor_malloc_zero(sizeof(*( rv->chanid_circid_map)));
  213. HT_INIT(chanid_circid_muxinfo_map, rv->chanid_circid_map);
  214. destroy_cell_queue_init(&rv->destroy_cell_queue);
  215. return rv;
  216. }
  217. /**
  218. * Detach all circuits from a circuitmux (use before circuitmux_free())
  219. *
  220. * If <b>detached_out</b> is non-NULL, add every detached circuit_t to
  221. * detached_out.
  222. */
  223. void
  224. circuitmux_detach_all_circuits(circuitmux_t *cmux, smartlist_t *detached_out)
  225. {
  226. chanid_circid_muxinfo_t **i = NULL, *to_remove;
  227. channel_t *chan = NULL;
  228. circuit_t *circ = NULL;
  229. tor_assert(cmux);
  230. i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
  231. while (i) {
  232. to_remove = *i;
  233. if (! to_remove) {
  234. log_warn(LD_BUG, "Somehow, an HT iterator gave us a NULL pointer.");
  235. break;
  236. } else {
  237. /* Find a channel and circuit */
  238. chan = channel_find_by_global_id(to_remove->chan_id);
  239. if (chan) {
  240. circ =
  241. circuit_get_by_circid_channel_even_if_marked(to_remove->circ_id,
  242. chan);
  243. if (circ) {
  244. /* Clear the circuit's mux for this direction */
  245. if (to_remove->muxinfo.direction == CELL_DIRECTION_OUT) {
  246. /*
  247. * Update active_circuits et al.; this does policy notifies, so
  248. * comes before freeing policy data
  249. */
  250. if (to_remove->muxinfo.cell_count > 0) {
  251. circuitmux_make_circuit_inactive(cmux, circ);
  252. }
  253. /* Clear n_mux */
  254. circ->n_mux = NULL;
  255. if (detached_out)
  256. smartlist_add(detached_out, circ);
  257. } else if (circ->magic == OR_CIRCUIT_MAGIC) {
  258. /*
  259. * Update active_circuits et al.; this does policy notifies, so
  260. * comes before freeing policy data
  261. */
  262. if (to_remove->muxinfo.cell_count > 0) {
  263. circuitmux_make_circuit_inactive(cmux, circ);
  264. }
  265. /*
  266. * It has a sensible p_chan and direction == CELL_DIRECTION_IN,
  267. * so clear p_mux.
  268. */
  269. TO_OR_CIRCUIT(circ)->p_mux = NULL;
  270. if (detached_out)
  271. smartlist_add(detached_out, circ);
  272. } else {
  273. /* Complain and move on */
  274. log_warn(LD_CIRC,
  275. "Circuit %u/channel " U64_FORMAT " had direction == "
  276. "CELL_DIRECTION_IN, but isn't an or_circuit_t",
  277. (unsigned)to_remove->circ_id,
  278. U64_PRINTF_ARG(to_remove->chan_id));
  279. }
  280. /* Free policy-specific data if we have it */
  281. if (to_remove->muxinfo.policy_data) {
  282. /*
  283. * If we have policy data, assert that we have the means to
  284. * free it
  285. */
  286. tor_assert(cmux->policy);
  287. tor_assert(cmux->policy->free_circ_data);
  288. /* Call free_circ_data() */
  289. cmux->policy->free_circ_data(cmux,
  290. cmux->policy_data,
  291. circ,
  292. to_remove->muxinfo.policy_data);
  293. to_remove->muxinfo.policy_data = NULL;
  294. }
  295. } else {
  296. /* Complain and move on */
  297. log_warn(LD_CIRC,
  298. "Couldn't find circuit %u (for channel " U64_FORMAT ")",
  299. (unsigned)to_remove->circ_id,
  300. U64_PRINTF_ARG(to_remove->chan_id));
  301. }
  302. } else {
  303. /* Complain and move on */
  304. log_warn(LD_CIRC,
  305. "Couldn't find channel " U64_FORMAT " (for circuit id %u)",
  306. U64_PRINTF_ARG(to_remove->chan_id),
  307. (unsigned)to_remove->circ_id);
  308. }
  309. /* Assert that we don't have un-freed policy data for this circuit */
  310. tor_assert(to_remove->muxinfo.policy_data == NULL);
  311. }
  312. i = HT_NEXT_RMV(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
  313. /* Free it */
  314. tor_free(to_remove);
  315. }
  316. cmux->n_circuits = 0;
  317. cmux->n_active_circuits = 0;
  318. cmux->n_cells = 0;
  319. }
  320. /** Reclaim all circuit IDs currently marked as unusable on <b>chan</b> because
  321. * of pending destroy cells in <b>cmux</b>.
  322. *
  323. * This function must be called AFTER circuits are unlinked from the (channel,
  324. * circuid-id) map with circuit_unlink_all_from_channel(), but before calling
  325. * circuitmux_free().
  326. */
  327. void
  328. circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux, channel_t *chan)
  329. {
  330. destroy_cell_t *cell;
  331. TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
  332. channel_mark_circid_usable(chan, cell->circid);
  333. }
  334. }
  335. /**
  336. * Free a circuitmux_t; the circuits must be detached first with
  337. * circuitmux_detach_all_circuits().
  338. */
  339. void
  340. circuitmux_free_(circuitmux_t *cmux)
  341. {
  342. if (!cmux) return;
  343. tor_assert(cmux->n_circuits == 0);
  344. tor_assert(cmux->n_active_circuits == 0);
  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. if (cmux->chanid_circid_map) {
  359. HT_CLEAR(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
  360. tor_free(cmux->chanid_circid_map);
  361. }
  362. /*
  363. * We're throwing away some destroys; log the counter and
  364. * adjust the global counter by the queue size.
  365. */
  366. if (cmux->destroy_cell_queue.n > 0) {
  367. cmux->destroy_ctr -= cmux->destroy_cell_queue.n;
  368. global_destroy_ctr -= cmux->destroy_cell_queue.n;
  369. log_debug(LD_CIRC,
  370. "Freeing cmux at %p with %u queued destroys; the last cmux "
  371. "destroy balance was "I64_FORMAT", global is "I64_FORMAT,
  372. cmux, cmux->destroy_cell_queue.n,
  373. I64_PRINTF_ARG(cmux->destroy_ctr),
  374. I64_PRINTF_ARG(global_destroy_ctr));
  375. } else {
  376. log_debug(LD_CIRC,
  377. "Freeing cmux at %p with no queued destroys, the cmux destroy "
  378. "balance was "I64_FORMAT", global is "I64_FORMAT,
  379. cmux,
  380. I64_PRINTF_ARG(cmux->destroy_ctr),
  381. I64_PRINTF_ARG(global_destroy_ctr));
  382. }
  383. destroy_cell_queue_clear(&cmux->destroy_cell_queue);
  384. tor_free(cmux);
  385. }
  386. /*
  387. * Circuitmux policy control functions
  388. */
  389. /**
  390. * Remove any policy installed on cmux; all policy data will be freed and
  391. * cmux behavior will revert to the built-in round-robin active_circuits
  392. * mechanism.
  393. */
  394. void
  395. circuitmux_clear_policy(circuitmux_t *cmux)
  396. {
  397. tor_assert(cmux);
  398. /* Internally, this is just setting policy to NULL */
  399. circuitmux_set_policy(cmux, NULL);
  400. }
  401. /**
  402. * Return the policy currently installed on a circuitmux_t
  403. */
  404. MOCK_IMPL(const circuitmux_policy_t *,
  405. circuitmux_get_policy, (circuitmux_t *cmux))
  406. {
  407. tor_assert(cmux);
  408. return cmux->policy;
  409. }
  410. /**
  411. * Set policy; allocate for new policy, detach all circuits from old policy
  412. * if any, attach them to new policy, and free old policy data.
  413. */
  414. void
  415. circuitmux_set_policy(circuitmux_t *cmux,
  416. const circuitmux_policy_t *pol)
  417. {
  418. const circuitmux_policy_t *old_pol = NULL, *new_pol = NULL;
  419. circuitmux_policy_data_t *old_pol_data = NULL, *new_pol_data = NULL;
  420. chanid_circid_muxinfo_t **i = NULL;
  421. channel_t *chan = NULL;
  422. uint64_t last_chan_id_searched = 0;
  423. circuit_t *circ = NULL;
  424. tor_assert(cmux);
  425. /* Set up variables */
  426. old_pol = cmux->policy;
  427. old_pol_data = cmux->policy_data;
  428. new_pol = pol;
  429. /* Check if this is the trivial case */
  430. if (old_pol == new_pol) return;
  431. /* Allocate data for new policy, if any */
  432. if (new_pol && new_pol->alloc_cmux_data) {
  433. /*
  434. * If alloc_cmux_data is not null, then we expect to get some policy
  435. * data. Assert that we also have free_cmux_data so we can free it
  436. * when the time comes, and allocate it.
  437. */
  438. tor_assert(new_pol->free_cmux_data);
  439. new_pol_data = new_pol->alloc_cmux_data(cmux);
  440. tor_assert(new_pol_data);
  441. }
  442. /* Install new policy and new policy data on cmux */
  443. cmux->policy = new_pol;
  444. cmux->policy_data = new_pol_data;
  445. /* Iterate over all circuits, attaching/detaching each one */
  446. i = HT_START(chanid_circid_muxinfo_map, cmux->chanid_circid_map);
  447. while (i) {
  448. /* Assert that this entry isn't NULL */
  449. tor_assert(*i);
  450. /*
  451. * Get the channel; since normal case is all circuits on the mux share a
  452. * channel, we cache last_chan_id_searched
  453. */
  454. if (!chan || last_chan_id_searched != (*i)->chan_id) {
  455. chan = channel_find_by_global_id((*i)->chan_id);
  456. last_chan_id_searched = (*i)->chan_id;
  457. }
  458. tor_assert(chan);
  459. /* Get the circuit */
  460. circ = circuit_get_by_circid_channel_even_if_marked((*i)->circ_id, chan);
  461. tor_assert(circ);
  462. /* Need to tell old policy it becomes inactive (i.e., it is active) ? */
  463. if (old_pol && old_pol->notify_circ_inactive &&
  464. (*i)->muxinfo.cell_count > 0) {
  465. old_pol->notify_circ_inactive(cmux, old_pol_data, circ,
  466. (*i)->muxinfo.policy_data);
  467. }
  468. /* Need to free old policy data? */
  469. if ((*i)->muxinfo.policy_data) {
  470. /* Assert that we have the means to free it if we have policy data */
  471. tor_assert(old_pol);
  472. tor_assert(old_pol->free_circ_data);
  473. /* Free it */
  474. old_pol->free_circ_data(cmux, old_pol_data, circ,
  475. (*i)->muxinfo.policy_data);
  476. (*i)->muxinfo.policy_data = NULL;
  477. }
  478. /* Need to allocate new policy data? */
  479. if (new_pol && new_pol->alloc_circ_data) {
  480. /*
  481. * If alloc_circ_data is not null, we expect to get some per-circuit
  482. * policy data. Assert that we also have free_circ_data so we can
  483. * free it when the time comes, and allocate it.
  484. */
  485. tor_assert(new_pol->free_circ_data);
  486. (*i)->muxinfo.policy_data =
  487. new_pol->alloc_circ_data(cmux, new_pol_data, circ,
  488. (*i)->muxinfo.direction,
  489. (*i)->muxinfo.cell_count);
  490. }
  491. /* Need to make active on new policy? */
  492. if (new_pol && new_pol->notify_circ_active &&
  493. (*i)->muxinfo.cell_count > 0) {
  494. new_pol->notify_circ_active(cmux, new_pol_data, circ,
  495. (*i)->muxinfo.policy_data);
  496. }
  497. /* Advance to next circuit map entry */
  498. i = HT_NEXT(chanid_circid_muxinfo_map, cmux->chanid_circid_map, i);
  499. }
  500. /* Free data for old policy, if any */
  501. if (old_pol_data) {
  502. /*
  503. * If we had old policy data, we should have an old policy and a free
  504. * function for it.
  505. */
  506. tor_assert(old_pol);
  507. tor_assert(old_pol->free_cmux_data);
  508. old_pol->free_cmux_data(cmux, old_pol_data);
  509. old_pol_data = NULL;
  510. }
  511. }
  512. /*
  513. * Circuitmux/circuit attachment status inquiry functions
  514. */
  515. /**
  516. * Query the direction of an attached circuit
  517. */
  518. cell_direction_t
  519. circuitmux_attached_circuit_direction(circuitmux_t *cmux, circuit_t *circ)
  520. {
  521. chanid_circid_muxinfo_t *hashent = NULL;
  522. /* Try to find a map entry */
  523. hashent = circuitmux_find_map_entry(cmux, circ);
  524. /*
  525. * This function should only be called on attached circuits; assert that
  526. * we had a map entry.
  527. */
  528. tor_assert(hashent);
  529. /* Return the direction from the map entry */
  530. return hashent->muxinfo.direction;
  531. }
  532. /**
  533. * Find an entry in the cmux's map for this circuit or return NULL if there
  534. * is none.
  535. */
  536. static chanid_circid_muxinfo_t *
  537. circuitmux_find_map_entry(circuitmux_t *cmux, circuit_t *circ)
  538. {
  539. chanid_circid_muxinfo_t search, *hashent = NULL;
  540. /* Sanity-check parameters */
  541. tor_assert(cmux);
  542. tor_assert(cmux->chanid_circid_map);
  543. tor_assert(circ);
  544. /* Check if we have n_chan */
  545. if (circ->n_chan) {
  546. /* Okay, let's see if it's attached for n_chan/n_circ_id */
  547. search.chan_id = circ->n_chan->global_identifier;
  548. search.circ_id = circ->n_circ_id;
  549. /* Query */
  550. hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
  551. &search);
  552. }
  553. /* Found something? */
  554. if (hashent) {
  555. /*
  556. * Assert that the direction makes sense for a hashent we found by
  557. * n_chan/n_circ_id before we return it.
  558. */
  559. tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_OUT);
  560. } else {
  561. /* Not there, have we got a p_chan/p_circ_id to try? */
  562. if (circ->magic == OR_CIRCUIT_MAGIC) {
  563. search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
  564. /* Check for p_chan */
  565. if (TO_OR_CIRCUIT(circ)->p_chan) {
  566. search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier;
  567. /* Okay, search for that */
  568. hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
  569. &search);
  570. /* Find anything? */
  571. if (hashent) {
  572. /* Assert that the direction makes sense before we return it */
  573. tor_assert(hashent->muxinfo.direction == CELL_DIRECTION_IN);
  574. }
  575. }
  576. }
  577. }
  578. /* Okay, hashent is it if it was there */
  579. return hashent;
  580. }
  581. /**
  582. * Query whether a circuit is attached to a circuitmux
  583. */
  584. int
  585. circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ)
  586. {
  587. chanid_circid_muxinfo_t *hashent = NULL;
  588. /* Look if it's in the circuit map */
  589. hashent = circuitmux_find_map_entry(cmux, circ);
  590. return (hashent != NULL);
  591. }
  592. /**
  593. * Query whether a circuit is active on a circuitmux
  594. */
  595. int
  596. circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ)
  597. {
  598. chanid_circid_muxinfo_t *hashent = NULL;
  599. int is_active = 0;
  600. tor_assert(cmux);
  601. tor_assert(circ);
  602. /* Look if it's in the circuit map */
  603. hashent = circuitmux_find_map_entry(cmux, circ);
  604. if (hashent) {
  605. /* Check the number of cells on this circuit */
  606. is_active = (hashent->muxinfo.cell_count > 0);
  607. }
  608. /* else not attached, so not active */
  609. return is_active;
  610. }
  611. /**
  612. * Query number of available cells for a circuit on a circuitmux
  613. */
  614. unsigned int
  615. circuitmux_num_cells_for_circuit(circuitmux_t *cmux, circuit_t *circ)
  616. {
  617. chanid_circid_muxinfo_t *hashent = NULL;
  618. unsigned int n_cells = 0;
  619. tor_assert(cmux);
  620. tor_assert(circ);
  621. /* Look if it's in the circuit map */
  622. hashent = circuitmux_find_map_entry(cmux, circ);
  623. if (hashent) {
  624. /* Just get the cell count for this circuit */
  625. n_cells = hashent->muxinfo.cell_count;
  626. }
  627. /* else not attached, so 0 cells */
  628. return n_cells;
  629. }
  630. /**
  631. * Query total number of available cells on a circuitmux
  632. */
  633. MOCK_IMPL(unsigned int,
  634. circuitmux_num_cells, (circuitmux_t *cmux))
  635. {
  636. tor_assert(cmux);
  637. return cmux->n_cells + cmux->destroy_cell_queue.n;
  638. }
  639. /**
  640. * Query total number of circuits active on a circuitmux
  641. */
  642. unsigned int
  643. circuitmux_num_active_circuits(circuitmux_t *cmux)
  644. {
  645. tor_assert(cmux);
  646. return cmux->n_active_circuits;
  647. }
  648. /**
  649. * Query total number of circuits attached to a circuitmux
  650. */
  651. unsigned int
  652. circuitmux_num_circuits(circuitmux_t *cmux)
  653. {
  654. tor_assert(cmux);
  655. return cmux->n_circuits;
  656. }
  657. /*
  658. * Functions for circuit code to call to update circuit status
  659. */
  660. /**
  661. * Attach a circuit to a circuitmux, for the specified direction.
  662. */
  663. MOCK_IMPL(void,
  664. circuitmux_attach_circuit,(circuitmux_t *cmux, circuit_t *circ,
  665. cell_direction_t direction))
  666. {
  667. channel_t *chan = NULL;
  668. uint64_t channel_id;
  669. circid_t circ_id;
  670. chanid_circid_muxinfo_t search, *hashent = NULL;
  671. unsigned int cell_count;
  672. tor_assert(cmux);
  673. tor_assert(circ);
  674. tor_assert(direction == CELL_DIRECTION_IN ||
  675. direction == CELL_DIRECTION_OUT);
  676. /*
  677. * Figure out which channel we're using, and get the circuit's current
  678. * cell count and circuit ID; assert that the circuit is not already
  679. * attached to another mux.
  680. */
  681. if (direction == CELL_DIRECTION_OUT) {
  682. /* It's n_chan */
  683. chan = circ->n_chan;
  684. cell_count = circ->n_chan_cells.n;
  685. circ_id = circ->n_circ_id;
  686. } else {
  687. /* We want p_chan */
  688. chan = TO_OR_CIRCUIT(circ)->p_chan;
  689. cell_count = TO_OR_CIRCUIT(circ)->p_chan_cells.n;
  690. circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
  691. }
  692. /* Assert that we did get a channel */
  693. tor_assert(chan);
  694. /* Assert that the circuit ID is sensible */
  695. tor_assert(circ_id != 0);
  696. /* Get the channel ID */
  697. channel_id = chan->global_identifier;
  698. /* See if we already have this one */
  699. search.chan_id = channel_id;
  700. search.circ_id = circ_id;
  701. hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
  702. &search);
  703. if (hashent) {
  704. /*
  705. * This circuit was already attached to this cmux; make sure the
  706. * directions match and update the cell count and active circuit count.
  707. */
  708. log_info(LD_CIRC,
  709. "Circuit %u on channel " U64_FORMAT " was already attached to "
  710. "cmux %p (trying to attach to %p)",
  711. (unsigned)circ_id, U64_PRINTF_ARG(channel_id),
  712. ((direction == CELL_DIRECTION_OUT) ?
  713. circ->n_mux : TO_OR_CIRCUIT(circ)->p_mux),
  714. cmux);
  715. /*
  716. * The mux pointer on this circuit and the direction in result should
  717. * match; otherwise assert.
  718. */
  719. if (direction == CELL_DIRECTION_OUT) tor_assert(circ->n_mux == cmux);
  720. else tor_assert(TO_OR_CIRCUIT(circ)->p_mux == cmux);
  721. tor_assert(hashent->muxinfo.direction == direction);
  722. /*
  723. * Looks okay; just update the cell count and active circuits if we must
  724. */
  725. if (hashent->muxinfo.cell_count > 0 && cell_count == 0) {
  726. --(cmux->n_active_circuits);
  727. circuitmux_make_circuit_inactive(cmux, circ);
  728. } else if (hashent->muxinfo.cell_count == 0 && cell_count > 0) {
  729. ++(cmux->n_active_circuits);
  730. circuitmux_make_circuit_active(cmux, circ);
  731. }
  732. cmux->n_cells -= hashent->muxinfo.cell_count;
  733. cmux->n_cells += cell_count;
  734. hashent->muxinfo.cell_count = cell_count;
  735. } else {
  736. /*
  737. * New circuit; add an entry and update the circuit/active circuit
  738. * counts.
  739. */
  740. log_debug(LD_CIRC,
  741. "Attaching circuit %u on channel " U64_FORMAT " to cmux %p",
  742. (unsigned)circ_id, U64_PRINTF_ARG(channel_id), cmux);
  743. /*
  744. * Assert that the circuit doesn't already have a mux for this
  745. * direction.
  746. */
  747. if (direction == CELL_DIRECTION_OUT) tor_assert(circ->n_mux == NULL);
  748. else tor_assert(TO_OR_CIRCUIT(circ)->p_mux == NULL);
  749. /* Insert it in the map */
  750. hashent = tor_malloc_zero(sizeof(*hashent));
  751. hashent->chan_id = channel_id;
  752. hashent->circ_id = circ_id;
  753. hashent->muxinfo.cell_count = cell_count;
  754. hashent->muxinfo.direction = direction;
  755. /* Allocate policy specific circuit data if we need it */
  756. if (cmux->policy->alloc_circ_data) {
  757. /* Assert that we have the means to free policy-specific data */
  758. tor_assert(cmux->policy->free_circ_data);
  759. /* Allocate it */
  760. hashent->muxinfo.policy_data =
  761. cmux->policy->alloc_circ_data(cmux,
  762. cmux->policy_data,
  763. circ,
  764. direction,
  765. cell_count);
  766. /* If we wanted policy data, it's an error not to get any */
  767. tor_assert(hashent->muxinfo.policy_data);
  768. }
  769. HT_INSERT(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
  770. hashent);
  771. /* Set the circuit's mux for this direction */
  772. if (direction == CELL_DIRECTION_OUT) circ->n_mux = cmux;
  773. else TO_OR_CIRCUIT(circ)->p_mux = cmux;
  774. /* Update counters */
  775. ++(cmux->n_circuits);
  776. if (cell_count > 0) {
  777. ++(cmux->n_active_circuits);
  778. circuitmux_make_circuit_active(cmux, circ);
  779. }
  780. cmux->n_cells += cell_count;
  781. }
  782. }
  783. /**
  784. * Detach a circuit from a circuitmux and update all counters as needed;
  785. * no-op if not attached.
  786. */
  787. MOCK_IMPL(void,
  788. circuitmux_detach_circuit,(circuitmux_t *cmux, circuit_t *circ))
  789. {
  790. chanid_circid_muxinfo_t search, *hashent = NULL;
  791. /*
  792. * Use this to keep track of whether we found it for n_chan or
  793. * p_chan for consistency checking.
  794. *
  795. * The 0 initializer is not a valid cell_direction_t value.
  796. * We assert that it has been replaced with a valid value before it is used.
  797. */
  798. cell_direction_t last_searched_direction = 0;
  799. tor_assert(cmux);
  800. tor_assert(cmux->chanid_circid_map);
  801. tor_assert(circ);
  802. /* See if we have it for n_chan/n_circ_id */
  803. if (circ->n_chan) {
  804. search.chan_id = circ->n_chan->global_identifier;
  805. search.circ_id = circ->n_circ_id;
  806. hashent = HT_FIND(chanid_circid_muxinfo_map, cmux->chanid_circid_map,
  807. &search);
  808. last_searched_direction = CELL_DIRECTION_OUT;
  809. }
  810. /* Got one? If not, see if it's an or_circuit_t and try p_chan/p_circ_id */
  811. if (!hashent) {
  812. if (circ->magic == OR_CIRCUIT_MAGIC) {
  813. search.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
  814. if (TO_OR_CIRCUIT(circ)->p_chan) {
  815. search.chan_id = TO_OR_CIRCUIT(circ)->p_chan->global_identifier;
  816. hashent = HT_FIND(chanid_circid_muxinfo_map,
  817. cmux->chanid_circid_map,
  818. &search);
  819. last_searched_direction = CELL_DIRECTION_IN;
  820. }
  821. }
  822. }
  823. tor_assert(last_searched_direction == CELL_DIRECTION_OUT
  824. || last_searched_direction == CELL_DIRECTION_IN);
  825. /*
  826. * If hashent isn't NULL, we have a circuit to detach; don't remove it from
  827. * the map until later of circuitmux_make_circuit_inactive() breaks.
  828. */
  829. if (hashent) {
  830. /* Update counters */
  831. --(cmux->n_circuits);
  832. if (hashent->muxinfo.cell_count > 0) {
  833. --(cmux->n_active_circuits);
  834. /* This does policy notifies, so comes before freeing policy data */
  835. circuitmux_make_circuit_inactive(cmux, circ);
  836. }
  837. cmux->n_cells -= hashent->muxinfo.cell_count;
  838. /* Free policy-specific data if we have it */
  839. if (hashent->muxinfo.policy_data) {
  840. /* If we have policy data, assert that we have the means to free it */
  841. tor_assert(cmux->policy);
  842. tor_assert(cmux->policy->free_circ_data);
  843. /* Call free_circ_data() */
  844. cmux->policy->free_circ_data(cmux,
  845. cmux->policy_data,
  846. circ,
  847. hashent->muxinfo.policy_data);
  848. hashent->muxinfo.policy_data = NULL;
  849. }
  850. /* Consistency check: the direction must match the direction searched */
  851. tor_assert(last_searched_direction == hashent->muxinfo.direction);
  852. /* Clear the circuit's mux for this direction */
  853. if (last_searched_direction == CELL_DIRECTION_OUT) circ->n_mux = NULL;
  854. else TO_OR_CIRCUIT(circ)->p_mux = NULL;
  855. /* Now remove it from the map */
  856. HT_REMOVE(chanid_circid_muxinfo_map, cmux->chanid_circid_map, hashent);
  857. /* Free the hash entry */
  858. tor_free(hashent);
  859. }
  860. }
  861. /**
  862. * Make a circuit active; update active list and policy-specific info, but
  863. * we don't mess with the counters or hash table here.
  864. */
  865. static void
  866. circuitmux_make_circuit_active(circuitmux_t *cmux, circuit_t *circ)
  867. {
  868. tor_assert(cmux);
  869. tor_assert(cmux->policy);
  870. tor_assert(circ);
  871. /* Policy-specific notification */
  872. if (cmux->policy->notify_circ_active) {
  873. /* Okay, we need to check the circuit for policy data now */
  874. chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
  875. /* We should have found something */
  876. tor_assert(hashent);
  877. /* Notify */
  878. cmux->policy->notify_circ_active(cmux, cmux->policy_data,
  879. circ, hashent->muxinfo.policy_data);
  880. }
  881. }
  882. /**
  883. * Make a circuit inactive; update active list and policy-specific info, but
  884. * we don't mess with the counters or hash table here.
  885. */
  886. static void
  887. circuitmux_make_circuit_inactive(circuitmux_t *cmux, circuit_t *circ)
  888. {
  889. tor_assert(cmux);
  890. tor_assert(cmux->policy);
  891. tor_assert(circ);
  892. /* Policy-specific notification */
  893. if (cmux->policy->notify_circ_inactive) {
  894. /* Okay, we need to check the circuit for policy data now */
  895. chanid_circid_muxinfo_t *hashent = circuitmux_find_map_entry(cmux, circ);
  896. /* We should have found something */
  897. tor_assert(hashent);
  898. /* Notify */
  899. cmux->policy->notify_circ_inactive(cmux, cmux->policy_data,
  900. circ, hashent->muxinfo.policy_data);
  901. }
  902. }
  903. /**
  904. * Clear the cell counter for a circuit on a circuitmux
  905. */
  906. void
  907. circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ)
  908. {
  909. /* This is the same as setting the cell count to zero */
  910. circuitmux_set_num_cells(cmux, circ, 0);
  911. }
  912. /**
  913. * Set the cell counter for a circuit on a circuitmux
  914. */
  915. void
  916. circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
  917. unsigned int n_cells)
  918. {
  919. chanid_circid_muxinfo_t *hashent = NULL;
  920. tor_assert(cmux);
  921. tor_assert(circ);
  922. /* Search for this circuit's entry */
  923. hashent = circuitmux_find_map_entry(cmux, circ);
  924. /* Assert that we found one */
  925. tor_assert(hashent);
  926. /* Update cmux cell counter */
  927. cmux->n_cells -= hashent->muxinfo.cell_count;
  928. cmux->n_cells += n_cells;
  929. /* Do we need to notify a cmux policy? */
  930. if (cmux->policy->notify_set_n_cells) {
  931. /* Call notify_set_n_cells */
  932. cmux->policy->notify_set_n_cells(cmux,
  933. cmux->policy_data,
  934. circ,
  935. hashent->muxinfo.policy_data,
  936. n_cells);
  937. }
  938. /*
  939. * Update cmux active circuit counter: is the old cell count > 0 and the
  940. * new cell count == 0 ?
  941. */
  942. if (hashent->muxinfo.cell_count > 0 && n_cells == 0) {
  943. --(cmux->n_active_circuits);
  944. hashent->muxinfo.cell_count = n_cells;
  945. circuitmux_make_circuit_inactive(cmux, circ);
  946. /* Is the old cell count == 0 and the new cell count > 0 ? */
  947. } else if (hashent->muxinfo.cell_count == 0 && n_cells > 0) {
  948. ++(cmux->n_active_circuits);
  949. hashent->muxinfo.cell_count = n_cells;
  950. circuitmux_make_circuit_active(cmux, circ);
  951. } else {
  952. hashent->muxinfo.cell_count = n_cells;
  953. }
  954. }
  955. /*
  956. * Functions for channel code to call to get a circuit to transmit from or
  957. * notify that cells have been transmitted.
  958. */
  959. /**
  960. * Pick a circuit to send from, using the active circuits list or a
  961. * circuitmux policy if one is available. This is called from channel.c.
  962. *
  963. * If we would rather send a destroy cell, return NULL and set
  964. * *<b>destroy_queue_out</b> to the destroy queue.
  965. *
  966. * If we have nothing to send, set *<b>destroy_queue_out</b> to NULL and
  967. * return NULL.
  968. */
  969. circuit_t *
  970. circuitmux_get_first_active_circuit(circuitmux_t *cmux,
  971. destroy_cell_queue_t **destroy_queue_out)
  972. {
  973. circuit_t *circ = NULL;
  974. tor_assert(cmux);
  975. tor_assert(cmux->policy);
  976. /* This callback is mandatory. */
  977. tor_assert(cmux->policy->pick_active_circuit);
  978. tor_assert(destroy_queue_out);
  979. *destroy_queue_out = NULL;
  980. if (cmux->destroy_cell_queue.n &&
  981. (!cmux->last_cell_was_destroy || cmux->n_active_circuits == 0)) {
  982. /* We have destroy cells to send, and either we just sent a relay cell,
  983. * or we have no relay cells to send. */
  984. /* XXXX We should let the cmux policy have some say in this eventually. */
  985. /* XXXX Alternating is not a terribly brilliant approach here. */
  986. *destroy_queue_out = &cmux->destroy_cell_queue;
  987. cmux->last_cell_was_destroy = 1;
  988. } else if (cmux->n_active_circuits > 0) {
  989. /* We also must have a cell available for this to be the case */
  990. tor_assert(cmux->n_cells > 0);
  991. /* Do we have a policy-provided circuit selector? */
  992. circ = cmux->policy->pick_active_circuit(cmux, cmux->policy_data);
  993. cmux->last_cell_was_destroy = 0;
  994. } else {
  995. tor_assert(cmux->n_cells == 0);
  996. tor_assert(cmux->destroy_cell_queue.n == 0);
  997. }
  998. return circ;
  999. }
  1000. /**
  1001. * Notify the circuitmux that cells have been sent on a circuit; this
  1002. * is called from channel.c.
  1003. */
  1004. void
  1005. circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
  1006. unsigned int n_cells)
  1007. {
  1008. chanid_circid_muxinfo_t *hashent = NULL;
  1009. int becomes_inactive = 0;
  1010. tor_assert(cmux);
  1011. tor_assert(circ);
  1012. if (n_cells == 0) return;
  1013. /*
  1014. * To handle this, we have to:
  1015. *
  1016. * 1.) Adjust the circuit's cell counter in the cmux hash table
  1017. * 2.) Move the circuit to the tail of the active_circuits linked list
  1018. * for this cmux, or make the circuit inactive if the cell count
  1019. * went to zero.
  1020. * 3.) Call cmux->policy->notify_xmit_cells(), if any
  1021. */
  1022. /* Find the hash entry */
  1023. hashent = circuitmux_find_map_entry(cmux, circ);
  1024. /* Assert that we found one */
  1025. tor_assert(hashent);
  1026. /* Adjust the cell counter and assert that we had that many cells to send */
  1027. tor_assert(n_cells <= hashent->muxinfo.cell_count);
  1028. hashent->muxinfo.cell_count -= n_cells;
  1029. /* Do we need to make the circuit inactive? */
  1030. if (hashent->muxinfo.cell_count == 0) becomes_inactive = 1;
  1031. /* Adjust the mux cell counter */
  1032. cmux->n_cells -= n_cells;
  1033. /*
  1034. * We call notify_xmit_cells() before making the circuit inactive if needed,
  1035. * so the policy can always count on this coming in on an active circuit.
  1036. */
  1037. if (cmux->policy->notify_xmit_cells) {
  1038. cmux->policy->notify_xmit_cells(cmux, cmux->policy_data, circ,
  1039. hashent->muxinfo.policy_data,
  1040. n_cells);
  1041. }
  1042. /*
  1043. * Now make the circuit inactive if needed; this will call the policy's
  1044. * notify_circ_inactive() if present.
  1045. */
  1046. if (becomes_inactive) {
  1047. --(cmux->n_active_circuits);
  1048. circuitmux_make_circuit_inactive(cmux, circ);
  1049. }
  1050. }
  1051. /**
  1052. * Notify the circuitmux that a destroy was sent, so we can update
  1053. * the counter.
  1054. */
  1055. void
  1056. circuitmux_notify_xmit_destroy(circuitmux_t *cmux)
  1057. {
  1058. tor_assert(cmux);
  1059. --(cmux->destroy_ctr);
  1060. --(global_destroy_ctr);
  1061. log_debug(LD_CIRC,
  1062. "Cmux at %p sent a destroy, cmux counter is now "I64_FORMAT", "
  1063. "global counter is now "I64_FORMAT,
  1064. cmux,
  1065. I64_PRINTF_ARG(cmux->destroy_ctr),
  1066. I64_PRINTF_ARG(global_destroy_ctr));
  1067. }
  1068. /*DOCDOC */
  1069. void
  1070. circuitmux_append_destroy_cell(channel_t *chan,
  1071. circuitmux_t *cmux,
  1072. circid_t circ_id,
  1073. uint8_t reason)
  1074. {
  1075. destroy_cell_queue_append(&cmux->destroy_cell_queue, circ_id, reason);
  1076. /* Destroy entering the queue, update counters */
  1077. ++(cmux->destroy_ctr);
  1078. ++global_destroy_ctr;
  1079. log_debug(LD_CIRC,
  1080. "Cmux at %p queued a destroy for circ %u, cmux counter is now "
  1081. I64_FORMAT", global counter is now "I64_FORMAT,
  1082. cmux, circ_id,
  1083. I64_PRINTF_ARG(cmux->destroy_ctr),
  1084. I64_PRINTF_ARG(global_destroy_ctr));
  1085. /* XXXX Duplicate code from append_cell_to_circuit_queue */
  1086. if (!channel_has_queued_writes(chan)) {
  1087. /* There is no data at all waiting to be sent on the outbuf. Add a
  1088. * cell, so that we can notice when it gets flushed, flushed_some can
  1089. * get called, and we can start putting more data onto the buffer then.
  1090. */
  1091. log_debug(LD_GENERAL, "Primed a buffer.");
  1092. channel_flush_from_first_active_circuit(chan, 1);
  1093. }
  1094. }
  1095. /*DOCDOC; for debugging 12184. This runs slowly. */
  1096. int64_t
  1097. circuitmux_count_queued_destroy_cells(const channel_t *chan,
  1098. const circuitmux_t *cmux)
  1099. {
  1100. int64_t n_destroy_cells = cmux->destroy_ctr;
  1101. int64_t destroy_queue_size = cmux->destroy_cell_queue.n;
  1102. int64_t manual_total = 0;
  1103. int64_t manual_total_in_map = 0;
  1104. destroy_cell_t *cell;
  1105. TOR_SIMPLEQ_FOREACH(cell, &cmux->destroy_cell_queue.head, next) {
  1106. circid_t id;
  1107. ++manual_total;
  1108. id = cell->circid;
  1109. if (circuit_id_in_use_on_channel(id, (channel_t*)chan))
  1110. ++manual_total_in_map;
  1111. }
  1112. if (n_destroy_cells != destroy_queue_size ||
  1113. n_destroy_cells != manual_total ||
  1114. n_destroy_cells != manual_total_in_map) {
  1115. log_warn(LD_BUG, " Discrepancy in counts for queued destroy cells on "
  1116. "circuitmux. n="I64_FORMAT". queue_size="I64_FORMAT". "
  1117. "manual_total="I64_FORMAT". manual_total_in_map="I64_FORMAT".",
  1118. I64_PRINTF_ARG(n_destroy_cells),
  1119. I64_PRINTF_ARG(destroy_queue_size),
  1120. I64_PRINTF_ARG(manual_total),
  1121. I64_PRINTF_ARG(manual_total_in_map));
  1122. }
  1123. return n_destroy_cells;
  1124. }
  1125. /**
  1126. * Compare cmuxes to see which is more preferred; return < 0 if
  1127. * cmux_1 has higher priority (i.e., cmux_1 < cmux_2 in the scheduler's
  1128. * sort order), > 0 if cmux_2 has higher priority, or 0 if they are
  1129. * equally preferred.
  1130. *
  1131. * If the cmuxes have different cmux policies or the policy does not
  1132. * support the cmp_cmux method, return 0.
  1133. */
  1134. MOCK_IMPL(int,
  1135. circuitmux_compare_muxes, (circuitmux_t *cmux_1, circuitmux_t *cmux_2))
  1136. {
  1137. const circuitmux_policy_t *policy;
  1138. tor_assert(cmux_1);
  1139. tor_assert(cmux_2);
  1140. if (cmux_1 == cmux_2) {
  1141. /* Equivalent because they're the same cmux */
  1142. return 0;
  1143. }
  1144. if (cmux_1->policy && cmux_2->policy) {
  1145. if (cmux_1->policy == cmux_2->policy) {
  1146. policy = cmux_1->policy;
  1147. if (policy->cmp_cmux) {
  1148. /* Okay, we can compare! */
  1149. return policy->cmp_cmux(cmux_1, cmux_1->policy_data,
  1150. cmux_2, cmux_2->policy_data);
  1151. } else {
  1152. /*
  1153. * Equivalent because the policy doesn't know how to compare between
  1154. * muxes.
  1155. */
  1156. return 0;
  1157. }
  1158. } else {
  1159. /* Equivalent because they have different policies */
  1160. return 0;
  1161. }
  1162. } else {
  1163. /* Equivalent because one or both are missing a policy */
  1164. return 0;
  1165. }
  1166. }