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