tor  0.4.2.0-alpha-dev
circuitmux_ewma.c
Go to the documentation of this file.
1 /* * Copyright (c) 2012-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
31 #define CIRCUITMUX_EWMA_PRIVATE
32 
33 #include "orconfig.h"
34 
35 #include <math.h>
36 
37 #include "core/or/or.h"
38 #include "core/or/circuitmux.h"
43 
44 /*** EWMA parameter #defines ***/
45 
47 #define EWMA_TICK_LEN 10
48 
51 #define EWMA_DEFAULT_HALFLIFE 0.0
52 
53 /*** Some useful constant #defines ***/
54 
57 #define EPSILON 0.00001
58 
59 #define LOG_ONEHALF -0.69314718055994529
60 
61 /*** EWMA structures ***/
62 
63 typedef struct cell_ewma_s cell_ewma_t;
66 
74 struct cell_ewma_s {
80  unsigned int last_adjusted_tick;
82  double cell_count;
85  unsigned int is_for_p_chan : 1;
89 };
90 
93 
101 
108 };
109 
112 
119 
127 };
128 
129 #define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
130 #define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
131 
132 /*** Downcasts for the above types ***/
133 
134 static ewma_policy_data_t *
136 
139 
145 static inline ewma_policy_data_t *
147 {
148  if (!pol) return NULL;
149  else {
150  tor_assert(pol->magic == EWMA_POL_DATA_MAGIC);
151  return DOWNCAST(ewma_policy_data_t, pol);
152  }
153 }
154 
160 static inline ewma_policy_circ_data_t *
162 {
163  if (!pol) return NULL;
164  else {
165  tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC);
166  return DOWNCAST(ewma_policy_circ_data_t, pol);
167  }
168 }
169 
170 /*** Static declarations for circuitmux_ewma.c ***/
171 
172 static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
173 static int compare_cell_ewma_counts(const void *p1, const void *p2);
175 static inline double get_scale_factor(unsigned from_tick, unsigned to_tick);
177 static void remove_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
178 static void scale_single_cell_ewma(cell_ewma_t *ewma, unsigned cur_tick);
180  unsigned cur_tick);
181 
182 /*** Circuitmux policy methods ***/
183 
185 static void ewma_free_cmux_data(circuitmux_t *cmux,
186  circuitmux_policy_data_t *pol_data);
189  circuit_t *circ, cell_direction_t direction,
190  unsigned int cell_count);
191 static void
193  circuitmux_policy_data_t *pol_data,
194  circuit_t *circ,
195  circuitmux_policy_circ_data_t *pol_circ_data);
196 static void
198  circuitmux_policy_data_t *pol_data,
199  circuit_t *circ,
200  circuitmux_policy_circ_data_t *pol_circ_data);
201 static void
203  circuitmux_policy_data_t *pol_data,
204  circuit_t *circ,
205  circuitmux_policy_circ_data_t *pol_circ_data);
206 static void
208  circuitmux_policy_data_t *pol_data,
209  circuit_t *circ,
210  circuitmux_policy_circ_data_t *pol_circ_data,
211  unsigned int n_cells);
212 static circuit_t *
214  circuitmux_policy_data_t *pol_data);
215 static int
217  circuitmux_t *cmux_2, circuitmux_policy_data_t *pol_data_2);
218 
219 /*** EWMA global variables ***/
220 
225 static double ewma_scale_factor = 0.1;
226 
227 /*** EWMA circuitmux_policy_t method table ***/
228 
229 circuitmux_policy_t ewma_policy = {
230  /*.alloc_cmux_data =*/ ewma_alloc_cmux_data,
231  /*.free_cmux_data =*/ ewma_free_cmux_data,
232  /*.alloc_circ_data =*/ ewma_alloc_circ_data,
233  /*.free_circ_data =*/ ewma_free_circ_data,
234  /*.notify_circ_active =*/ ewma_notify_circ_active,
235  /*.notify_circ_inactive =*/ ewma_notify_circ_inactive,
236  /*.notify_set_n_cells =*/ NULL, /* EWMA doesn't need this */
237  /*.notify_xmit_cells =*/ ewma_notify_xmit_cells,
238  /*.pick_active_circuit =*/ ewma_pick_active_circuit,
239  /*.cmp_cmux =*/ ewma_cmp_cmux
240 };
241 
243 static int ewma_ticks_initialized = 0;
245 static monotime_coarse_t start_of_current_tick;
247 static unsigned current_tick_num;
248 
249 /*** EWMA method implementations using the below EWMA helper functions ***/
250 
252 static inline unsigned int
254 {
255  monotime_coarse_t now;
256  monotime_coarse_get(&now);
258  &now);
259  return current_tick_num + msec_diff / (1000*EWMA_TICK_LEN);
260 }
261 
269 {
270  ewma_policy_data_t *pol = NULL;
271 
272  tor_assert(cmux);
273 
274  pol = tor_malloc_zero(sizeof(*pol));
275  pol->base_.magic = EWMA_POL_DATA_MAGIC;
276  pol->active_circuit_pqueue = smartlist_new();
278 
279  return TO_CMUX_POL_DATA(pol);
280 }
281 
286 static void
288  circuitmux_policy_data_t *pol_data)
289 {
290  ewma_policy_data_t *pol = NULL;
291 
292  tor_assert(cmux);
293  if (!pol_data) return;
294 
295  pol = TO_EWMA_POL_DATA(pol_data);
296 
297  smartlist_free(pol->active_circuit_pqueue);
298  tor_free(pol);
299 }
300 
309  circuitmux_policy_data_t *pol_data,
310  circuit_t *circ,
311  cell_direction_t direction,
312  unsigned int cell_count)
313 {
314  ewma_policy_circ_data_t *cdata = NULL;
315 
316  tor_assert(cmux);
317  tor_assert(pol_data);
318  tor_assert(circ);
319  tor_assert(direction == CELL_DIRECTION_OUT ||
320  direction == CELL_DIRECTION_IN);
321  /* Shut the compiler up without triggering -Wtautological-compare */
322  (void)cell_count;
323 
324  cdata = tor_malloc_zero(sizeof(*cdata));
325  cdata->base_.magic = EWMA_POL_CIRC_DATA_MAGIC;
326  cdata->circ = circ;
327 
328  /*
329  * Initialize the cell_ewma_t structure (formerly in
330  * init_circuit_base())
331  */
333  cdata->cell_ewma.cell_count = 0.0;
334  cdata->cell_ewma.heap_index = -1;
335  if (direction == CELL_DIRECTION_IN) {
336  cdata->cell_ewma.is_for_p_chan = 1;
337  } else {
338  cdata->cell_ewma.is_for_p_chan = 0;
339  }
340 
341  return TO_CMUX_POL_CIRC_DATA(cdata);
342 }
343 
348 static void
350  circuitmux_policy_data_t *pol_data,
351  circuit_t *circ,
352  circuitmux_policy_circ_data_t *pol_circ_data)
353 
354 {
355  ewma_policy_circ_data_t *cdata = NULL;
356 
357  tor_assert(cmux);
358  tor_assert(circ);
359  tor_assert(pol_data);
360 
361  if (!pol_circ_data) return;
362 
363  cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data);
364 
365  tor_free(cdata);
366 }
367 
373 static void
375  circuitmux_policy_data_t *pol_data,
376  circuit_t *circ,
377  circuitmux_policy_circ_data_t *pol_circ_data)
378 {
379  ewma_policy_data_t *pol = NULL;
380  ewma_policy_circ_data_t *cdata = NULL;
381 
382  tor_assert(cmux);
383  tor_assert(pol_data);
384  tor_assert(circ);
385  tor_assert(pol_circ_data);
386 
387  pol = TO_EWMA_POL_DATA(pol_data);
388  cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data);
389 
390  add_cell_ewma(pol, &(cdata->cell_ewma));
391 }
392 
398 static void
400  circuitmux_policy_data_t *pol_data,
401  circuit_t *circ,
402  circuitmux_policy_circ_data_t *pol_circ_data)
403 {
404  ewma_policy_data_t *pol = NULL;
405  ewma_policy_circ_data_t *cdata = NULL;
406 
407  tor_assert(cmux);
408  tor_assert(pol_data);
409  tor_assert(circ);
410  tor_assert(pol_circ_data);
411 
412  pol = TO_EWMA_POL_DATA(pol_data);
413  cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data);
414 
415  remove_cell_ewma(pol, &(cdata->cell_ewma));
416 }
417 
424 static void
426  circuitmux_policy_data_t *pol_data,
427  circuit_t *circ,
428  circuitmux_policy_circ_data_t *pol_circ_data,
429  unsigned int n_cells)
430 {
431  ewma_policy_data_t *pol = NULL;
432  ewma_policy_circ_data_t *cdata = NULL;
433  unsigned int tick;
434  double fractional_tick, ewma_increment;
435  cell_ewma_t *cell_ewma, *tmp;
436 
437  tor_assert(cmux);
438  tor_assert(pol_data);
439  tor_assert(circ);
440  tor_assert(pol_circ_data);
441  tor_assert(n_cells > 0);
442 
443  pol = TO_EWMA_POL_DATA(pol_data);
444  cdata = TO_EWMA_POL_CIRC_DATA(pol_circ_data);
445 
446  /* Rescale the EWMAs if needed */
447  tick = cell_ewma_get_current_tick_and_fraction(&fractional_tick);
448 
449  if (tick != pol->active_circuit_pqueue_last_recalibrated) {
450  scale_active_circuits(pol, tick);
451  }
452 
453  /* How much do we adjust the cell count in cell_ewma by? */
454  ewma_increment =
455  ((double)(n_cells)) * pow(ewma_scale_factor, -fractional_tick);
456 
457  /* Do the adjustment */
458  cell_ewma = &(cdata->cell_ewma);
459  cell_ewma->cell_count += ewma_increment;
460 
461  /*
462  * Since we just sent on this circuit, it should be at the head of
463  * the queue. Pop the head, assert that it matches, then re-add.
464  */
465  tmp = pop_first_cell_ewma(pol);
466  tor_assert(tmp == cell_ewma);
467  add_cell_ewma(pol, cell_ewma);
468 }
469 
476 static circuit_t *
478  circuitmux_policy_data_t *pol_data)
479 {
480  ewma_policy_data_t *pol = NULL;
481  circuit_t *circ = NULL;
482  cell_ewma_t *cell_ewma = NULL;
483 
484  tor_assert(cmux);
485  tor_assert(pol_data);
486 
487  pol = TO_EWMA_POL_DATA(pol_data);
488 
489  if (smartlist_len(pol->active_circuit_pqueue) > 0) {
490  /* Get the head of the queue */
491  cell_ewma = smartlist_get(pol->active_circuit_pqueue, 0);
492  circ = cell_ewma_to_circuit(cell_ewma);
493  }
494 
495  return circ;
496 }
497 
503 static int
505  circuitmux_t *cmux_2, circuitmux_policy_data_t *pol_data_2)
506 {
507  ewma_policy_data_t *p1 = NULL, *p2 = NULL;
508  cell_ewma_t *ce1 = NULL, *ce2 = NULL;
509 
510  tor_assert(cmux_1);
511  tor_assert(pol_data_1);
512  tor_assert(cmux_2);
513  tor_assert(pol_data_2);
514 
515  p1 = TO_EWMA_POL_DATA(pol_data_1);
516  p2 = TO_EWMA_POL_DATA(pol_data_2);
517 
518  if (p1 != p2) {
519  /* Get the head cell_ewma_t from each queue */
520  if (smartlist_len(p1->active_circuit_pqueue) > 0) {
521  ce1 = smartlist_get(p1->active_circuit_pqueue, 0);
522  }
523 
524  if (smartlist_len(p2->active_circuit_pqueue) > 0) {
525  ce2 = smartlist_get(p2->active_circuit_pqueue, 0);
526  }
527 
528  /* Got both of them? */
529  if (ce1 != NULL && ce2 != NULL) {
530  /* Pick whichever one has the better best circuit */
531  return compare_cell_ewma_counts(ce1, ce2);
532  } else {
533  if (ce1 != NULL ) {
534  /* We only have a circuit on cmux_1, so prefer it */
535  return -1;
536  } else if (ce2 != NULL) {
537  /* We only have a circuit on cmux_2, so prefer it */
538  return 1;
539  } else {
540  /* No circuits at all; no preference */
541  return 0;
542  }
543  }
544  } else {
545  /* We got identical params */
546  return 0;
547  }
548 }
549 
551 static int
552 compare_cell_ewma_counts(const void *p1, const void *p2)
553 {
554  const cell_ewma_t *e1 = p1, *e2 = p2;
555 
556  if (e1->cell_count < e2->cell_count)
557  return -1;
558  else if (e1->cell_count > e2->cell_count)
559  return 1;
560  else
561  return 0;
562 }
563 
565 static circuit_t *
567 {
568  ewma_policy_circ_data_t *cdata = NULL;
569 
570  tor_assert(ewma);
571  cdata = SUBTYPE_P(ewma, ewma_policy_circ_data_t, cell_ewma);
572  tor_assert(cdata);
573 
574  return cdata->circ;
575 }
576 
577 /* ==== Functions for scaling cell_ewma_t ====
578 
579  When choosing which cells to relay first, we favor circuits that have been
580  quiet recently. This gives better latency on connections that aren't
581  pushing lots of data, and makes the network feel more interactive.
582 
583  Conceptually, we take an exponentially weighted mean average of the number
584  of cells a circuit has sent, and allow active circuits (those with cells to
585  relay) to send cells in reverse order of their exponentially-weighted mean
586  average (EWMA) cell count. [That is, a cell sent N seconds ago 'counts'
587  F^N times as much as a cell sent now, for 0<F<1.0, and we favor the
588  circuit that has sent the fewest cells]
589 
590  If 'double' had infinite precision, we could do this simply by counting a
591  cell sent at startup as having weight 1.0, and a cell sent N seconds later
592  as having weight F^-N. This way, we would never need to re-scale
593  any already-sent cells.
594 
595  To prevent double from overflowing, we could count a cell sent now as
596  having weight 1.0 and a cell sent N seconds ago as having weight F^N.
597  This, however, would mean we'd need to re-scale *ALL* old circuits every
598  time we wanted to send a cell.
599 
600  So as a compromise, we divide time into 'ticks' (currently, 10-second
601  increments) and say that a cell sent at the start of a current tick is
602  worth 1.0, a cell sent N seconds before the start of the current tick is
603  worth F^N, and a cell sent N seconds after the start of the current tick is
604  worth F^-N. This way we don't overflow, and we don't need to constantly
605  rescale.
606  */
607 
611 STATIC void
613 {
615  return;
616  monotime_coarse_get(&start_of_current_tick);
617  crypto_rand((char*)&current_tick_num, sizeof(current_tick_num));
619 }
620 
627 STATIC unsigned
629 {
630  if (BUG(!ewma_ticks_initialized)) {
631  cell_ewma_initialize_ticks(); // LCOV_EXCL_LINE
632  }
633  monotime_coarse_t now;
634  monotime_coarse_get(&now);
636  &now);
637  if (msec_diff > (1000*EWMA_TICK_LEN)) {
638  unsigned ticks_difference = msec_diff / (1000*EWMA_TICK_LEN);
639  monotime_coarse_add_msec(&start_of_current_tick,
641  ticks_difference * 1000 * EWMA_TICK_LEN);
642  current_tick_num += ticks_difference;
643  msec_diff %= 1000*EWMA_TICK_LEN;
644  }
645  *remainder_out = ((double)msec_diff) / (1.0e3 * EWMA_TICK_LEN);
646  return current_tick_num;
647 }
648 
649 /* Default value for the CircuitPriorityHalflifeMsec consensus parameter in
650  * msec. */
651 #define CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT 30000
652 /* Minimum and maximum value for the CircuitPriorityHalflifeMsec consensus
653  * parameter. */
654 #define CMUX_PRIORITY_HALFLIFE_MSEC_MIN 1
655 #define CMUX_PRIORITY_HALFLIFE_MSEC_MAX INT32_MAX
656 
657 /* Return the value of the circuit priority halflife from the options if
658  * available or else from the consensus (in that order). If none can be found,
659  * a default value is returned.
660  *
661  * The source_msg points to a string describing from where the value was
662  * picked so it can be used for logging. */
663 static double
664 get_circuit_priority_halflife(const or_options_t *options,
665  const networkstatus_t *consensus,
666  const char **source_msg)
667 {
668  int32_t halflife_ms;
669  double halflife;
670  /* Compute the default value now. We might need it. */
671  double halflife_default =
672  ((double) CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT) / 1000.0;
673 
674  /* Try to get it from configuration file first. */
675  if (options && options->CircuitPriorityHalflife >= -EPSILON) {
676  halflife = options->CircuitPriorityHalflife;
677  *source_msg = "CircuitPriorityHalflife in configuration";
678  goto end;
679  }
680 
681  /* Try to get the msec value from the consensus. */
682  halflife_ms = networkstatus_get_param(consensus,
683  "CircuitPriorityHalflifeMsec",
684  CMUX_PRIORITY_HALFLIFE_MSEC_DEFAULT,
685  CMUX_PRIORITY_HALFLIFE_MSEC_MIN,
686  CMUX_PRIORITY_HALFLIFE_MSEC_MAX);
687  halflife = ((double) halflife_ms) / 1000.0;
688  *source_msg = "CircuitPriorityHalflifeMsec in consensus";
689 
690  end:
691  /* We should never go below the EPSILON else we would consider it disabled
692  * and we can't have that. */
693  if (halflife < EPSILON) {
694  log_warn(LD_CONFIG, "CircuitPriorityHalflife is too small (%f). "
695  "Adjusting to the smallest value allowed: %f.",
696  halflife, halflife_default);
697  halflife = halflife_default;
698  }
699  return halflife;
700 }
701 
703 void
705  const networkstatus_t *consensus)
706 {
707  double halflife;
708  const char *source;
709 
711 
712  /* Both options and consensus can be NULL. This assures us to either get a
713  * valid configured value or the default one. */
714  halflife = get_circuit_priority_halflife(options, consensus, &source);
715 
716  /* convert halflife into halflife-per-tick. */
717  halflife /= EWMA_TICK_LEN;
718  /* compute per-tick scale factor. */
719  ewma_scale_factor = exp( LOG_ONEHALF / halflife );
720  log_info(LD_OR,
721  "Enabled cell_ewma algorithm because of value in %s; "
722  "scale factor is %f per %d seconds",
724 }
725 
728 static inline double
729 get_scale_factor(unsigned from_tick, unsigned to_tick)
730 {
731  /* This math can wrap around, but that's okay: unsigned overflow is
732  well-defined */
733  int diff = (int)(to_tick - from_tick);
734  return pow(ewma_scale_factor, diff);
735 }
736 
739 static void
740 scale_single_cell_ewma(cell_ewma_t *ewma, unsigned cur_tick)
741 {
742  double factor = get_scale_factor(ewma->last_adjusted_tick, cur_tick);
743  ewma->cell_count *= factor;
744  ewma->last_adjusted_tick = cur_tick;
745 }
746 
749 static void
751 {
752  double factor;
753 
754  tor_assert(pol);
756 
757  factor =
760  cur_tick);
765  cell_ewma_t *, e) {
766  tor_assert(e->last_adjusted_tick ==
768  e->cell_count *= factor;
769  e->last_adjusted_tick = cur_tick;
770  } SMARTLIST_FOREACH_END(e);
772 }
773 
776 static void
778 {
779  tor_assert(pol);
781  tor_assert(ewma);
782  tor_assert(ewma->heap_index == -1);
783 
785  ewma,
787 
790  offsetof(cell_ewma_t, heap_index),
791  ewma);
792 }
793 
795 static void
797 {
798  tor_assert(pol);
800  tor_assert(ewma);
801  tor_assert(ewma->heap_index != -1);
802 
805  offsetof(cell_ewma_t, heap_index),
806  ewma);
807 }
808 
811 static cell_ewma_t *
813 {
814  tor_assert(pol);
816 
819  offsetof(cell_ewma_t, heap_index));
820 }
821 
825 void
827 {
829 }
static void ewma_free_cmux_data(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data)
static int32_t monotime_coarse_diff_msec32(const monotime_coarse_t *start, const monotime_coarse_t *end)
Definition: compat_time.h:338
Common functions for using (pseudo-)random number generators.
static circuit_t * cell_ewma_to_circuit(cell_ewma_t *ewma)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
void smartlist_pqueue_add(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset, void *item)
Definition: smartlist.c:726
static void scale_active_circuits(ewma_policy_data_t *pol, unsigned cur_tick)
static void ewma_notify_xmit_cells(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, circuit_t *circ, circuitmux_policy_circ_data_t *pol_circ_data, unsigned int n_cells)
void * smartlist_pqueue_pop(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset)
Definition: smartlist.c:755
void circuitmux_ewma_free_all(void)
#define DOWNCAST(to, ptr)
Definition: or.h:110
static circuitmux_policy_data_t * ewma_alloc_cmux_data(circuitmux_t *cmux)
unsigned int last_adjusted_tick
void cmux_ewma_set_options(const or_options_t *options, const networkstatus_t *consensus)
#define SUBTYPE_P(p, subtype, basemember)
STATIC void cell_ewma_initialize_ticks(void)
static unsigned int cell_ewma_get_tick(void)
The or_options_t structure, which represents Tor's configuration.
#define tor_free(p)
Definition: malloc.h:52
static monotime_coarse_t start_of_current_tick
static void scale_single_cell_ewma(cell_ewma_t *ewma, unsigned cur_tick)
cell_direction_t
Definition: or.h:482
static int ewma_ticks_initialized
void smartlist_pqueue_remove(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset, void *item)
Definition: smartlist.c:779
static void ewma_notify_circ_active(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, circuit_t *circ, circuitmux_policy_circ_data_t *pol_circ_data)
static ewma_policy_data_t * TO_EWMA_POL_DATA(circuitmux_policy_data_t *)
tor_assert(buffer)
double cell_count
static void remove_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma)
smartlist_t * active_circuit_pqueue
Master header file for Tor-specific functionality.
unsigned int active_circuit_pqueue_last_recalibrated
unsigned int is_for_p_chan
Header file for circuitmux_ewma.c.
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma)
static int ewma_cmp_cmux(circuitmux_t *cmux_1, circuitmux_policy_data_t *pol_data_1, circuitmux_t *cmux_2, circuitmux_policy_data_t *pol_data_2)
#define LD_OR
Definition: log.h:90
static void ewma_notify_circ_inactive(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, circuit_t *circ, circuitmux_policy_circ_data_t *pol_circ_data)
static circuitmux_policy_circ_data_t * ewma_alloc_circ_data(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, circuit_t *circ, cell_direction_t direction, unsigned int cell_count)
static double get_scale_factor(unsigned from_tick, unsigned to_tick)
#define LOG_ONEHALF
static circuit_t * ewma_pick_active_circuit(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data)
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out)
#define TO_CMUX_POL_CIRC_DATA(x)
Definition: circuitmux.h:98
static unsigned current_tick_num
Header file for circuitmux.c.
static ewma_policy_circ_data_t * TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *)
static cell_ewma_t * pop_first_cell_ewma(ewma_policy_data_t *pol)
static void ewma_free_circ_data(circuitmux_t *cmux, circuitmux_policy_data_t *pol_data, circuit_t *circ, circuitmux_policy_circ_data_t *pol_circ_data)
static double ewma_scale_factor
#define TO_CMUX_POL_DATA(x)
Definition: circuitmux.h:91
Header file for networkstatus.c.
#define LD_CONFIG
Definition: log.h:66
static int compare_cell_ewma_counts(const void *p1, const void *p2)
#define EPSILON
#define EWMA_TICK_LEN