mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Merge remote-tracking branch 'tor-github/pr/1480'
This commit is contained in:
commit
096cbfb8b0
2
changes/ticket32196
Normal file
2
changes/ticket32196
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
o Testing (circuit, EWMA):
|
||||||
|
- Add unit tests for circuitmux and EWMA subsystems. Closes ticket 32196.
|
@ -69,26 +69,20 @@
|
|||||||
* made to attach all existing circuits to the new policy.
|
* made to attach all existing circuits to the new policy.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
#define CIRCUITMUX_PRIVATE
|
||||||
|
|
||||||
#include "core/or/or.h"
|
#include "core/or/or.h"
|
||||||
#include "core/or/channel.h"
|
#include "core/or/channel.h"
|
||||||
#include "core/or/circuitlist.h"
|
#include "core/or/circuitlist.h"
|
||||||
#include "core/or/circuitmux.h"
|
#include "core/or/circuitmux.h"
|
||||||
#include "core/or/relay.h"
|
#include "core/or/relay.h"
|
||||||
|
|
||||||
#include "core/or/cell_queue_st.h"
|
|
||||||
#include "core/or/destroy_cell_queue_st.h"
|
|
||||||
#include "core/or/or_circuit_st.h"
|
#include "core/or/or_circuit_st.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private typedefs for circuitmux.c
|
* Private typedefs for circuitmux.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Map of muxinfos for circuitmux_t to use; struct is defined below (name
|
|
||||||
* of struct must match HT_HEAD line).
|
|
||||||
*/
|
|
||||||
typedef struct chanid_circid_muxinfo_map chanid_circid_muxinfo_map_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
|
* Hash table entry (yeah, calling it chanid_circid_muxinfo_s seems to
|
||||||
* break the hash table code).
|
* break the hash table code).
|
||||||
@ -102,49 +96,6 @@ typedef struct chanid_circid_muxinfo_t chanid_circid_muxinfo_t;
|
|||||||
|
|
||||||
typedef struct circuit_muxinfo_s circuit_muxinfo_t;
|
typedef struct circuit_muxinfo_s circuit_muxinfo_t;
|
||||||
|
|
||||||
/*
|
|
||||||
* Structures for circuitmux.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct circuitmux_s {
|
|
||||||
/* Keep count of attached, active circuits */
|
|
||||||
unsigned int n_circuits, n_active_circuits;
|
|
||||||
|
|
||||||
/* Total number of queued cells on all circuits */
|
|
||||||
unsigned int n_cells;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
|
|
||||||
*/
|
|
||||||
chanid_circid_muxinfo_map_t *chanid_circid_map;
|
|
||||||
|
|
||||||
/** List of queued destroy cells */
|
|
||||||
destroy_cell_queue_t destroy_cell_queue;
|
|
||||||
/** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
|
|
||||||
* returned the destroy queue. Used to force alternation between
|
|
||||||
* destroy/non-destroy cells.
|
|
||||||
*
|
|
||||||
* XXXX There is no reason to think that alternating is a particularly good
|
|
||||||
* approach -- it's just designed to prevent destroys from starving other
|
|
||||||
* cells completely.
|
|
||||||
*/
|
|
||||||
unsigned int last_cell_was_destroy : 1;
|
|
||||||
/** Destroy counter: increment this when a destroy gets queued, decrement
|
|
||||||
* when we unqueue it, so we can test to make sure they don't starve.
|
|
||||||
*/
|
|
||||||
int64_t destroy_ctr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Circuitmux policy; if this is non-NULL, it can override the built-
|
|
||||||
* in round-robin active circuits behavior. This is how EWMA works in
|
|
||||||
* the new circuitmux_t world.
|
|
||||||
*/
|
|
||||||
const circuitmux_policy_t *policy;
|
|
||||||
|
|
||||||
/* Policy-specific data */
|
|
||||||
circuitmux_policy_data_t *policy_data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This struct holds whatever we want to store per attached circuit on a
|
* This struct holds whatever we want to store per attached circuit on a
|
||||||
* circuitmux_t; right now, just the count of queued cells and the direction.
|
* circuitmux_t; right now, just the count of queued cells and the direction.
|
||||||
@ -221,9 +172,6 @@ chanid_circid_entry_hash(chanid_circid_muxinfo_t *a)
|
|||||||
((unsigned int)(a->chan_id & 0xffffffff)));
|
((unsigned int)(a->chan_id & 0xffffffff)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Declare the struct chanid_circid_muxinfo_map type */
|
|
||||||
HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t);
|
|
||||||
|
|
||||||
/* Emit a bunch of hash table stuff */
|
/* Emit a bunch of hash table stuff */
|
||||||
HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
|
HT_PROTOTYPE(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t, node,
|
||||||
chanid_circid_entry_hash, chanid_circid_entries_eq)
|
chanid_circid_entry_hash, chanid_circid_entries_eq)
|
||||||
|
@ -158,5 +158,61 @@ void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux,
|
|||||||
MOCK_DECL(int, circuitmux_compare_muxes,
|
MOCK_DECL(int, circuitmux_compare_muxes,
|
||||||
(circuitmux_t *cmux_1, circuitmux_t *cmux_2));
|
(circuitmux_t *cmux_1, circuitmux_t *cmux_2));
|
||||||
|
|
||||||
|
#ifdef CIRCUITMUX_PRIVATE
|
||||||
|
|
||||||
|
#include "core/or/destroy_cell_queue_st.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map of muxinfos for circuitmux_t to use; struct is defined below (name
|
||||||
|
* of struct must match HT_HEAD line).
|
||||||
|
*/
|
||||||
|
typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t)
|
||||||
|
chanid_circid_muxinfo_map_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Structures for circuitmux.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct circuitmux_s {
|
||||||
|
/* Keep count of attached, active circuits */
|
||||||
|
unsigned int n_circuits, n_active_circuits;
|
||||||
|
|
||||||
|
/* Total number of queued cells on all circuits */
|
||||||
|
unsigned int n_cells;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
|
||||||
|
*/
|
||||||
|
chanid_circid_muxinfo_map_t *chanid_circid_map;
|
||||||
|
|
||||||
|
/** List of queued destroy cells */
|
||||||
|
destroy_cell_queue_t destroy_cell_queue;
|
||||||
|
/** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
|
||||||
|
* returned the destroy queue. Used to force alternation between
|
||||||
|
* destroy/non-destroy cells.
|
||||||
|
*
|
||||||
|
* XXXX There is no reason to think that alternating is a particularly good
|
||||||
|
* approach -- it's just designed to prevent destroys from starving other
|
||||||
|
* cells completely.
|
||||||
|
*/
|
||||||
|
unsigned int last_cell_was_destroy : 1;
|
||||||
|
/** Destroy counter: increment this when a destroy gets queued, decrement
|
||||||
|
* when we unqueue it, so we can test to make sure they don't starve.
|
||||||
|
*/
|
||||||
|
int64_t destroy_ctr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Circuitmux policy; if this is non-NULL, it can override the built-
|
||||||
|
* in round-robin active circuits behavior. This is how EWMA works in
|
||||||
|
* the new circuitmux_t world.
|
||||||
|
*/
|
||||||
|
const circuitmux_policy_t *policy;
|
||||||
|
|
||||||
|
/* Policy-specific data */
|
||||||
|
circuitmux_policy_data_t *policy_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CIRCUITMUX_PRIVATE */
|
||||||
|
|
||||||
#endif /* !defined(TOR_CIRCUITMUX_H) */
|
#endif /* !defined(TOR_CIRCUITMUX_H) */
|
||||||
|
|
||||||
|
@ -58,115 +58,6 @@
|
|||||||
/** The natural logarithm of 0.5. */
|
/** The natural logarithm of 0.5. */
|
||||||
#define LOG_ONEHALF -0.69314718055994529
|
#define LOG_ONEHALF -0.69314718055994529
|
||||||
|
|
||||||
/*** EWMA structures ***/
|
|
||||||
|
|
||||||
typedef struct cell_ewma_s cell_ewma_t;
|
|
||||||
typedef struct ewma_policy_data_s ewma_policy_data_t;
|
|
||||||
typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The cell_ewma_t structure keeps track of how many cells a circuit has
|
|
||||||
* transferred recently. It keeps an EWMA (exponentially weighted moving
|
|
||||||
* average) of the number of cells flushed from the circuit queue onto a
|
|
||||||
* connection in channel_flush_from_first_active_circuit().
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct cell_ewma_s {
|
|
||||||
/** The last 'tick' at which we recalibrated cell_count.
|
|
||||||
*
|
|
||||||
* A cell sent at exactly the start of this tick has weight 1.0. Cells sent
|
|
||||||
* since the start of this tick have weight greater than 1.0; ones sent
|
|
||||||
* earlier have less weight. */
|
|
||||||
unsigned int last_adjusted_tick;
|
|
||||||
/** The EWMA of the cell count. */
|
|
||||||
double cell_count;
|
|
||||||
/** True iff this is the cell count for a circuit's previous
|
|
||||||
* channel. */
|
|
||||||
unsigned int is_for_p_chan : 1;
|
|
||||||
/** The position of the circuit within the OR connection's priority
|
|
||||||
* queue. */
|
|
||||||
int heap_index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ewma_policy_data_s {
|
|
||||||
circuitmux_policy_data_t base_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Priority queue of cell_ewma_t for circuits with queued cells waiting
|
|
||||||
* for room to free up on the channel that owns this circuitmux. Kept
|
|
||||||
* in heap order according to EWMA. This was formerly in channel_t, and
|
|
||||||
* in or_connection_t before that.
|
|
||||||
*/
|
|
||||||
smartlist_t *active_circuit_pqueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The tick on which the cell_ewma_ts in active_circuit_pqueue last had
|
|
||||||
* their ewma values rescaled. This was formerly in channel_t, and in
|
|
||||||
* or_connection_t before that.
|
|
||||||
*/
|
|
||||||
unsigned int active_circuit_pqueue_last_recalibrated;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ewma_policy_circ_data_s {
|
|
||||||
circuitmux_policy_circ_data_t base_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The EWMA count for the number of cells flushed from this circuit
|
|
||||||
* onto this circuitmux. Used to determine which circuit to flush
|
|
||||||
* from next. This was formerly in circuit_t and or_circuit_t.
|
|
||||||
*/
|
|
||||||
cell_ewma_t cell_ewma;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pointer back to the circuit_t this is for; since we're separating
|
|
||||||
* out circuit selection policy like this, we can't attach cell_ewma_t
|
|
||||||
* to the circuit_t any more, so we can't use SUBTYPE_P directly to a
|
|
||||||
* circuit_t like before; instead get it here.
|
|
||||||
*/
|
|
||||||
circuit_t *circ;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
|
|
||||||
#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
|
|
||||||
|
|
||||||
/*** Downcasts for the above types ***/
|
|
||||||
|
|
||||||
static ewma_policy_data_t *
|
|
||||||
TO_EWMA_POL_DATA(circuitmux_policy_data_t *);
|
|
||||||
|
|
||||||
static ewma_policy_circ_data_t *
|
|
||||||
TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
|
|
||||||
* if the cast is impossible.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline ewma_policy_data_t *
|
|
||||||
TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
|
|
||||||
{
|
|
||||||
if (!pol) return NULL;
|
|
||||||
else {
|
|
||||||
tor_assert(pol->magic == EWMA_POL_DATA_MAGIC);
|
|
||||||
return DOWNCAST(ewma_policy_data_t, pol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
|
|
||||||
* and assert if the cast is impossible.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static inline ewma_policy_circ_data_t *
|
|
||||||
TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
|
|
||||||
{
|
|
||||||
if (!pol) return NULL;
|
|
||||||
else {
|
|
||||||
tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC);
|
|
||||||
return DOWNCAST(ewma_policy_circ_data_t, pol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*** Static declarations for circuitmux_ewma.c ***/
|
/*** Static declarations for circuitmux_ewma.c ***/
|
||||||
|
|
||||||
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
|
static void add_cell_ewma(ewma_policy_data_t *pol, cell_ewma_t *ewma);
|
||||||
|
@ -22,9 +22,114 @@ void cmux_ewma_set_options(const or_options_t *options,
|
|||||||
void circuitmux_ewma_free_all(void);
|
void circuitmux_ewma_free_all(void);
|
||||||
|
|
||||||
#ifdef CIRCUITMUX_EWMA_PRIVATE
|
#ifdef CIRCUITMUX_EWMA_PRIVATE
|
||||||
|
|
||||||
|
/*** EWMA structures ***/
|
||||||
|
|
||||||
|
typedef struct cell_ewma_s cell_ewma_t;
|
||||||
|
typedef struct ewma_policy_data_s ewma_policy_data_t;
|
||||||
|
typedef struct ewma_policy_circ_data_s ewma_policy_circ_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cell_ewma_t structure keeps track of how many cells a circuit has
|
||||||
|
* transferred recently. It keeps an EWMA (exponentially weighted moving
|
||||||
|
* average) of the number of cells flushed from the circuit queue onto a
|
||||||
|
* connection in channel_flush_from_first_active_circuit().
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct cell_ewma_s {
|
||||||
|
/** The last 'tick' at which we recalibrated cell_count.
|
||||||
|
*
|
||||||
|
* A cell sent at exactly the start of this tick has weight 1.0. Cells sent
|
||||||
|
* since the start of this tick have weight greater than 1.0; ones sent
|
||||||
|
* earlier have less weight. */
|
||||||
|
unsigned int last_adjusted_tick;
|
||||||
|
/** The EWMA of the cell count. */
|
||||||
|
double cell_count;
|
||||||
|
/** True iff this is the cell count for a circuit's previous
|
||||||
|
* channel. */
|
||||||
|
unsigned int is_for_p_chan : 1;
|
||||||
|
/** The position of the circuit within the OR connection's priority
|
||||||
|
* queue. */
|
||||||
|
int heap_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ewma_policy_data_s {
|
||||||
|
circuitmux_policy_data_t base_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Priority queue of cell_ewma_t for circuits with queued cells waiting
|
||||||
|
* for room to free up on the channel that owns this circuitmux. Kept
|
||||||
|
* in heap order according to EWMA. This was formerly in channel_t, and
|
||||||
|
* in or_connection_t before that.
|
||||||
|
*/
|
||||||
|
smartlist_t *active_circuit_pqueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tick on which the cell_ewma_ts in active_circuit_pqueue last had
|
||||||
|
* their ewma values rescaled. This was formerly in channel_t, and in
|
||||||
|
* or_connection_t before that.
|
||||||
|
*/
|
||||||
|
unsigned int active_circuit_pqueue_last_recalibrated;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ewma_policy_circ_data_s {
|
||||||
|
circuitmux_policy_circ_data_t base_;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The EWMA count for the number of cells flushed from this circuit
|
||||||
|
* onto this circuitmux. Used to determine which circuit to flush
|
||||||
|
* from next. This was formerly in circuit_t and or_circuit_t.
|
||||||
|
*/
|
||||||
|
cell_ewma_t cell_ewma;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pointer back to the circuit_t this is for; since we're separating
|
||||||
|
* out circuit selection policy like this, we can't attach cell_ewma_t
|
||||||
|
* to the circuit_t any more, so we can't use SUBTYPE_P directly to a
|
||||||
|
* circuit_t like before; instead get it here.
|
||||||
|
*/
|
||||||
|
circuit_t *circ;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
|
||||||
|
#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
|
||||||
|
|
||||||
|
/*** Downcasts for the above types ***/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
|
||||||
|
* if the cast is impossible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline ewma_policy_data_t *
|
||||||
|
TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
|
||||||
|
{
|
||||||
|
if (!pol) return NULL;
|
||||||
|
else {
|
||||||
|
tor_assert(pol->magic == EWMA_POL_DATA_MAGIC);
|
||||||
|
return DOWNCAST(ewma_policy_data_t, pol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
|
||||||
|
* and assert if the cast is impossible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static inline ewma_policy_circ_data_t *
|
||||||
|
TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
|
||||||
|
{
|
||||||
|
if (!pol) return NULL;
|
||||||
|
else {
|
||||||
|
tor_assert(pol->magic == EWMA_POL_CIRC_DATA_MAGIC);
|
||||||
|
return DOWNCAST(ewma_policy_circ_data_t, pol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
|
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
|
||||||
STATIC void cell_ewma_initialize_ticks(void);
|
STATIC void cell_ewma_initialize_ticks(void);
|
||||||
#endif
|
|
||||||
|
#endif /* CIRCUITMUX_EWMA_PRIVATE */
|
||||||
|
|
||||||
#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
|
#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#ifndef DESTROY_CELL_QUEUE_ST_H
|
#ifndef DESTROY_CELL_QUEUE_ST_H
|
||||||
#define DESTROY_CELL_QUEUE_ST_H
|
#define DESTROY_CELL_QUEUE_ST_H
|
||||||
|
|
||||||
|
#include "core/or/cell_queue_st.h"
|
||||||
|
|
||||||
/** A single queued destroy cell. */
|
/** A single queued destroy cell. */
|
||||||
struct destroy_cell_t {
|
struct destroy_cell_t {
|
||||||
TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
|
TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
|
||||||
|
88
src/test/fakecircs.c
Normal file
88
src/test/fakecircs.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright (c) 2019, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file fakecircs.c
|
||||||
|
* \brief Fake circuits API for unit test.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define CHANNEL_PRIVATE
|
||||||
|
#define CIRCUITBUILD_PRIVATE
|
||||||
|
#define CIRCUITLIST_PRIVATE
|
||||||
|
#define CRYPT_PATH_PRIVATE
|
||||||
|
|
||||||
|
#include "core/or/or.h"
|
||||||
|
|
||||||
|
#include "core/crypto/relay_crypto.h"
|
||||||
|
#include "core/or/channel.h"
|
||||||
|
#include "core/or/circuitbuild.h"
|
||||||
|
#include "core/or/circuitlist.h"
|
||||||
|
#include "core/or/circuitpadding.h"
|
||||||
|
#include "core/or/crypt_path.h"
|
||||||
|
#include "core/or/relay.h"
|
||||||
|
#include "core/or/relay_crypto_st.h"
|
||||||
|
|
||||||
|
#include "fakecircs.h"
|
||||||
|
|
||||||
|
/** Return newly allocated OR circuit using the given nchan and pchan. It must
|
||||||
|
* be freed with the free_fake_orcirc(). */
|
||||||
|
or_circuit_t *
|
||||||
|
new_fake_orcirc(channel_t *nchan, channel_t *pchan)
|
||||||
|
{
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
crypt_path_t tmp_cpath;
|
||||||
|
char whatevs_key[CPATH_KEY_MATERIAL_LEN];
|
||||||
|
|
||||||
|
orcirc = tor_malloc_zero(sizeof(*orcirc));
|
||||||
|
circ = &(orcirc->base_);
|
||||||
|
circ->magic = OR_CIRCUIT_MAGIC;
|
||||||
|
|
||||||
|
circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
|
||||||
|
cell_queue_init(&(circ->n_chan_cells));
|
||||||
|
|
||||||
|
circ->n_hop = NULL;
|
||||||
|
circ->streams_blocked_on_n_chan = 0;
|
||||||
|
circ->streams_blocked_on_p_chan = 0;
|
||||||
|
circ->n_delete_pending = 0;
|
||||||
|
circ->p_delete_pending = 0;
|
||||||
|
circ->received_destroy = 0;
|
||||||
|
circ->state = CIRCUIT_STATE_OPEN;
|
||||||
|
circ->purpose = CIRCUIT_PURPOSE_OR;
|
||||||
|
circ->package_window = CIRCWINDOW_START_MAX;
|
||||||
|
circ->deliver_window = CIRCWINDOW_START_MAX;
|
||||||
|
circ->n_chan_create_cell = NULL;
|
||||||
|
|
||||||
|
circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
|
||||||
|
cell_queue_init(&(orcirc->p_chan_cells));
|
||||||
|
|
||||||
|
memset(&tmp_cpath, 0, sizeof(tmp_cpath));
|
||||||
|
if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
|
||||||
|
sizeof(whatevs_key), 0, 0)<0) {
|
||||||
|
log_warn(LD_BUG,"Circuit initialization failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
orcirc->crypto = tmp_cpath.pvt_crypto;
|
||||||
|
|
||||||
|
return orcirc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Free fake OR circuit which MUST be created by new_fake_orcirc(). */
|
||||||
|
void
|
||||||
|
free_fake_orcirc(or_circuit_t *orcirc)
|
||||||
|
{
|
||||||
|
circuit_t *circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
relay_crypto_clear(&orcirc->crypto);
|
||||||
|
|
||||||
|
circpad_circuit_free_all_machineinfos(circ);
|
||||||
|
|
||||||
|
if (orcirc->p_chan && orcirc->p_chan->cmux) {
|
||||||
|
circuitmux_detach_circuit(orcirc->p_chan->cmux, circ);
|
||||||
|
}
|
||||||
|
if (circ->n_chan && circ->n_chan->cmux) {
|
||||||
|
circuitmux_detach_circuit(circ->n_chan->cmux, circ);
|
||||||
|
}
|
||||||
|
|
||||||
|
tor_free_(circ);
|
||||||
|
}
|
17
src/test/fakecircs.h
Normal file
17
src/test/fakecircs.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* Copyright (c) 2019, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file fakecircs.h
|
||||||
|
* \brief Declarations for fake circuits for test suite use.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef TOR_FAKECIRCS_H
|
||||||
|
#define TOR_FAKECIRCS_H
|
||||||
|
|
||||||
|
#include "core/or/or_circuit_st.h"
|
||||||
|
|
||||||
|
or_circuit_t *new_fake_orcirc(channel_t *nchan, channel_t *pchan);
|
||||||
|
void free_fake_orcirc(or_circuit_t *orcirc);
|
||||||
|
|
||||||
|
#endif /* TOR_FAKECIRCS_H */
|
@ -99,6 +99,7 @@ if UNITTESTS_ENABLED
|
|||||||
|
|
||||||
# ADD_C_FILE: INSERT SOURCES HERE.
|
# ADD_C_FILE: INSERT SOURCES HERE.
|
||||||
src_test_test_SOURCES += \
|
src_test_test_SOURCES += \
|
||||||
|
src/test/fakecircs.c \
|
||||||
src/test/log_test_helpers.c \
|
src/test/log_test_helpers.c \
|
||||||
src/test/hs_test_helpers.c \
|
src/test/hs_test_helpers.c \
|
||||||
src/test/rend_test_helpers.c \
|
src/test/rend_test_helpers.c \
|
||||||
@ -122,6 +123,7 @@ src_test_test_SOURCES += \
|
|||||||
src/test/test_checkdir.c \
|
src/test/test_checkdir.c \
|
||||||
src/test/test_circuitlist.c \
|
src/test/test_circuitlist.c \
|
||||||
src/test/test_circuitmux.c \
|
src/test/test_circuitmux.c \
|
||||||
|
src/test/test_circuitmux_ewma.c \
|
||||||
src/test/test_circuitbuild.c \
|
src/test/test_circuitbuild.c \
|
||||||
src/test/test_circuituse.c \
|
src/test/test_circuituse.c \
|
||||||
src/test/test_circuitstats.c \
|
src/test/test_circuitstats.c \
|
||||||
@ -339,6 +341,7 @@ src_test_test_timers_LDFLAGS = $(src_test_test_LDFLAGS)
|
|||||||
# ADD_C_FILE: INSERT HEADERS HERE.
|
# ADD_C_FILE: INSERT HEADERS HERE.
|
||||||
noinst_HEADERS+= \
|
noinst_HEADERS+= \
|
||||||
src/test/fakechans.h \
|
src/test/fakechans.h \
|
||||||
|
src/test/fakecircs.h \
|
||||||
src/test/hs_test_helpers.h \
|
src/test/hs_test_helpers.h \
|
||||||
src/test/log_test_helpers.h \
|
src/test/log_test_helpers.h \
|
||||||
src/test/rend_test_helpers.h \
|
src/test/rend_test_helpers.h \
|
||||||
|
@ -836,6 +836,7 @@ struct testgroup_t testgroups[] = {
|
|||||||
{ "circuitpadding/", circuitpadding_tests },
|
{ "circuitpadding/", circuitpadding_tests },
|
||||||
{ "circuitlist/", circuitlist_tests },
|
{ "circuitlist/", circuitlist_tests },
|
||||||
{ "circuitmux/", circuitmux_tests },
|
{ "circuitmux/", circuitmux_tests },
|
||||||
|
{ "circuitmux_ewma/", circuitmux_ewma_tests },
|
||||||
{ "circuitstats/", circuitstats_tests },
|
{ "circuitstats/", circuitstats_tests },
|
||||||
{ "circuituse/", circuituse_tests },
|
{ "circuituse/", circuituse_tests },
|
||||||
{ "compat/libevent/", compat_libevent_tests },
|
{ "compat/libevent/", compat_libevent_tests },
|
||||||
|
@ -199,6 +199,7 @@ extern struct testcase_t checkdir_tests[];
|
|||||||
extern struct testcase_t circuitbuild_tests[];
|
extern struct testcase_t circuitbuild_tests[];
|
||||||
extern struct testcase_t circuitlist_tests[];
|
extern struct testcase_t circuitlist_tests[];
|
||||||
extern struct testcase_t circuitmux_tests[];
|
extern struct testcase_t circuitmux_tests[];
|
||||||
|
extern struct testcase_t circuitmux_ewma_tests[];
|
||||||
extern struct testcase_t circuitstats_tests[];
|
extern struct testcase_t circuitstats_tests[];
|
||||||
extern struct testcase_t circuituse_tests[];
|
extern struct testcase_t circuituse_tests[];
|
||||||
extern struct testcase_t compat_libevent_tests[];
|
extern struct testcase_t compat_libevent_tests[];
|
||||||
|
@ -5,29 +5,23 @@
|
|||||||
#define CIRCUITMUX_PRIVATE
|
#define CIRCUITMUX_PRIVATE
|
||||||
#define CIRCUITMUX_EWMA_PRIVATE
|
#define CIRCUITMUX_EWMA_PRIVATE
|
||||||
#define RELAY_PRIVATE
|
#define RELAY_PRIVATE
|
||||||
|
|
||||||
#include "core/or/or.h"
|
#include "core/or/or.h"
|
||||||
#include "core/or/channel.h"
|
#include "core/or/channel.h"
|
||||||
#include "core/or/circuitmux.h"
|
#include "core/or/circuitmux.h"
|
||||||
#include "core/or/circuitmux_ewma.h"
|
#include "core/or/circuitmux_ewma.h"
|
||||||
|
#include "core/or/destroy_cell_queue_st.h"
|
||||||
#include "core/or/relay.h"
|
#include "core/or/relay.h"
|
||||||
#include "core/or/scheduler.h"
|
#include "core/or/scheduler.h"
|
||||||
#include "test/test.h"
|
|
||||||
|
|
||||||
#include "core/or/destroy_cell_queue_st.h"
|
#include "test/fakechans.h"
|
||||||
|
#include "test/fakecircs.h"
|
||||||
|
#include "test/test.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
/* XXXX duplicated function from test_circuitlist.c */
|
|
||||||
static channel_t *
|
|
||||||
new_fake_channel(void)
|
|
||||||
{
|
|
||||||
channel_t *chan = tor_malloc_zero(sizeof(channel_t));
|
|
||||||
channel_init(chan);
|
|
||||||
return chan;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
has_queued_writes(channel_t *c)
|
mock_has_queued_writes_true(channel_t *c)
|
||||||
{
|
{
|
||||||
(void) c;
|
(void) c;
|
||||||
return 1;
|
return 1;
|
||||||
@ -44,16 +38,14 @@ test_cmux_destroy_cell_queue(void *arg)
|
|||||||
packed_cell_t *pc = NULL;
|
packed_cell_t *pc = NULL;
|
||||||
destroy_cell_t *dc = NULL;
|
destroy_cell_t *dc = NULL;
|
||||||
|
|
||||||
scheduler_init();
|
MOCK(scheduler_release_channel, scheduler_release_channel_mock);
|
||||||
|
|
||||||
(void) arg;
|
(void) arg;
|
||||||
|
|
||||||
cmux = circuitmux_alloc();
|
|
||||||
tt_assert(cmux);
|
|
||||||
ch = new_fake_channel();
|
ch = new_fake_channel();
|
||||||
circuitmux_set_policy(cmux, &ewma_policy);
|
ch->has_queued_writes = mock_has_queued_writes_true;
|
||||||
ch->has_queued_writes = has_queued_writes;
|
|
||||||
ch->wide_circ_ids = 1;
|
ch->wide_circ_ids = 1;
|
||||||
|
cmux = ch->cmux;
|
||||||
|
|
||||||
circ = circuitmux_get_first_active_circuit(cmux, &cq);
|
circ = circuitmux_get_first_active_circuit(cmux, &cq);
|
||||||
tt_ptr_op(circ, OP_EQ, NULL);
|
tt_ptr_op(circ, OP_EQ, NULL);
|
||||||
@ -78,10 +70,11 @@ test_cmux_destroy_cell_queue(void *arg)
|
|||||||
tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2);
|
tt_int_op(circuitmux_num_cells(cmux), OP_EQ, 2);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
circuitmux_free(cmux);
|
free_fake_channel(ch);
|
||||||
channel_free(ch);
|
|
||||||
packed_cell_free(pc);
|
packed_cell_free(pc);
|
||||||
tor_free(dc);
|
tor_free(dc);
|
||||||
|
|
||||||
|
UNMOCK(scheduler_release_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -125,9 +118,364 @@ test_cmux_compute_ticks(void *arg)
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_allocate(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t *cmux = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
cmux = circuitmux_alloc();
|
||||||
|
tt_assert(cmux);
|
||||||
|
tt_assert(cmux->chanid_circid_map);
|
||||||
|
tt_int_op(HT_SIZE(cmux->chanid_circid_map), OP_EQ, 0);
|
||||||
|
tt_uint_op(cmux->n_circuits, OP_EQ, 0);
|
||||||
|
tt_uint_op(cmux->n_active_circuits, OP_EQ, 0);
|
||||||
|
tt_uint_op(cmux->n_cells, OP_EQ, 0);
|
||||||
|
tt_uint_op(cmux->last_cell_was_destroy, OP_EQ, 0);
|
||||||
|
tt_int_op(cmux->destroy_ctr, OP_EQ, 0);
|
||||||
|
tt_ptr_op(cmux->policy, OP_EQ, NULL);
|
||||||
|
tt_ptr_op(cmux->policy_data, OP_EQ, NULL);
|
||||||
|
|
||||||
|
tt_assert(TOR_SIMPLEQ_EMPTY(&cmux->destroy_cell_queue.head));
|
||||||
|
|
||||||
|
done:
|
||||||
|
circuitmux_free(cmux);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_attach_circuit(void *arg)
|
||||||
|
{
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
channel_t *pchan = NULL, *nchan = NULL;
|
||||||
|
cell_direction_t cdir;
|
||||||
|
unsigned int n_cells;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pchan = new_fake_channel();
|
||||||
|
tt_assert(pchan);
|
||||||
|
nchan = new_fake_channel();
|
||||||
|
tt_assert(nchan);
|
||||||
|
|
||||||
|
orcirc = new_fake_orcirc(nchan, pchan);
|
||||||
|
tt_assert(orcirc);
|
||||||
|
circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
/* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
|
||||||
|
* called for a new channel on the circuit. This means, we should now have
|
||||||
|
* the created circuit attached on both the pchan and nchan cmux. */
|
||||||
|
tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* There should be _no_ active circuit due to no queued cells. */
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(nchan->cmux), OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Circuit should not be active on the cmux. */
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Not active so no cells. */
|
||||||
|
n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
|
||||||
|
tt_uint_op(n_cells, OP_EQ, 0);
|
||||||
|
n_cells = circuitmux_num_cells(pchan->cmux);
|
||||||
|
tt_uint_op(n_cells, OP_EQ, 0);
|
||||||
|
n_cells = circuitmux_num_cells_for_circuit(nchan->cmux, circ);
|
||||||
|
tt_uint_op(n_cells, OP_EQ, 0);
|
||||||
|
n_cells = circuitmux_num_cells(nchan->cmux);
|
||||||
|
tt_uint_op(n_cells, OP_EQ, 0);
|
||||||
|
|
||||||
|
/* So it should be attached :) */
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Query the chanid<->circid map in the cmux subsytem with what we just
|
||||||
|
* created and validate the cell direction. */
|
||||||
|
cdir = circuitmux_attached_circuit_direction(pchan->cmux, circ);
|
||||||
|
tt_int_op(cdir, OP_EQ, CELL_DIRECTION_IN);
|
||||||
|
cdir = circuitmux_attached_circuit_direction(nchan->cmux, circ);
|
||||||
|
tt_int_op(cdir, OP_EQ, CELL_DIRECTION_OUT);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We'll activate->deactivate->activate to test all code paths of
|
||||||
|
* circuitmux_set_num_cells().
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Activate circuit. */
|
||||||
|
circuitmux_set_num_cells(pchan->cmux, circ, 4);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Deactivate. */
|
||||||
|
circuitmux_clear_num_cells(pchan->cmux, circ);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Re-activate. */
|
||||||
|
circuitmux_set_num_cells(pchan->cmux, circ, 4);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Once re-attached, it should become inactive because the circuit has no
|
||||||
|
* cells while the chanid<->circid object has some. The attach code will
|
||||||
|
* reset the count on the cmux for that circuit:
|
||||||
|
*
|
||||||
|
* if (chanid_circid_muxinfo_t->muxinfo.cell_count > 0 && cell_count == 0) {
|
||||||
|
*/
|
||||||
|
circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
|
||||||
|
n_cells = circuitmux_num_cells_for_circuit(pchan->cmux, circ);
|
||||||
|
tt_uint_op(n_cells, OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Lets queue a cell on the circuit now so it becomes active when
|
||||||
|
* re-attaching:
|
||||||
|
*
|
||||||
|
* else if (chanid_circid_muxinfo_t->muxinfo.cell_count == 0 &&
|
||||||
|
* cell_count > 0) {
|
||||||
|
*/
|
||||||
|
orcirc->p_chan_cells.n = 1;
|
||||||
|
circuitmux_attach_circuit(pchan->cmux, circ, CELL_DIRECTION_IN);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
done:
|
||||||
|
free_fake_orcirc(orcirc);
|
||||||
|
free_fake_channel(pchan);
|
||||||
|
free_fake_channel(nchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_detach_circuit(void *arg)
|
||||||
|
{
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
channel_t *pchan = NULL, *nchan = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pchan = new_fake_channel();
|
||||||
|
tt_assert(pchan);
|
||||||
|
nchan = new_fake_channel();
|
||||||
|
tt_assert(nchan);
|
||||||
|
|
||||||
|
orcirc = new_fake_orcirc(nchan, pchan);
|
||||||
|
tt_assert(orcirc);
|
||||||
|
circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
/* While assigning a new circuit IDs, the circuitmux_attach_circuit() is
|
||||||
|
* called for a new channel on the circuit. This means, we should now have
|
||||||
|
* the created circuit attached on both the pchan and nchan cmux. */
|
||||||
|
tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Now, detach the circuit from pchan and then nchan. */
|
||||||
|
circuitmux_detach_circuit(pchan->cmux, circ);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
circuitmux_detach_circuit(nchan->cmux, circ);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
free_fake_orcirc(orcirc);
|
||||||
|
free_fake_channel(pchan);
|
||||||
|
free_fake_channel(nchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_detach_all_circuits(void *arg)
|
||||||
|
{
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
channel_t *pchan = NULL, *nchan = NULL;
|
||||||
|
smartlist_t *detached_out = smartlist_new();
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Channels need to be registered in order for the detach all circuit
|
||||||
|
* function to find them. */
|
||||||
|
pchan = new_fake_channel();
|
||||||
|
tt_assert(pchan);
|
||||||
|
channel_register(pchan);
|
||||||
|
nchan = new_fake_channel();
|
||||||
|
tt_assert(nchan);
|
||||||
|
channel_register(nchan);
|
||||||
|
|
||||||
|
orcirc = new_fake_orcirc(nchan, pchan);
|
||||||
|
tt_assert(orcirc);
|
||||||
|
circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
/* Just make sure it is attached. */
|
||||||
|
tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Queue some cells so we can test if the circuit becomes inactive on the
|
||||||
|
* cmux after the mass detach. */
|
||||||
|
circuitmux_set_num_cells(pchan->cmux, circ, 4);
|
||||||
|
circuitmux_set_num_cells(nchan->cmux, circ, 4);
|
||||||
|
|
||||||
|
/* Detach all on pchan and then nchan. */
|
||||||
|
circuitmux_detach_all_circuits(pchan->cmux, detached_out);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(pchan->cmux), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_int_op(smartlist_len(detached_out), OP_EQ, 1);
|
||||||
|
circuitmux_detach_all_circuits(nchan->cmux, NULL);
|
||||||
|
tt_uint_op(circuitmux_num_circuits(nchan->cmux), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_attached(nchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(nchan->cmux, circ), OP_EQ, 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
smartlist_free(detached_out);
|
||||||
|
free_fake_orcirc(orcirc);
|
||||||
|
free_fake_channel(pchan);
|
||||||
|
free_fake_channel(nchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_policy(void *arg)
|
||||||
|
{
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
channel_t *pchan = NULL, *nchan = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pchan = new_fake_channel();
|
||||||
|
tt_assert(pchan);
|
||||||
|
channel_register(pchan);
|
||||||
|
nchan = new_fake_channel();
|
||||||
|
tt_assert(nchan);
|
||||||
|
channel_register(nchan);
|
||||||
|
|
||||||
|
orcirc = new_fake_orcirc(nchan, pchan);
|
||||||
|
tt_assert(orcirc);
|
||||||
|
circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
/* Confirm we have the EWMA policy by default for new channels. */
|
||||||
|
tt_ptr_op(circuitmux_get_policy(pchan->cmux), OP_EQ, &ewma_policy);
|
||||||
|
tt_ptr_op(circuitmux_get_policy(nchan->cmux), OP_EQ, &ewma_policy);
|
||||||
|
|
||||||
|
/* Putting cell on the cmux means will make the notify policy code path to
|
||||||
|
* trigger. */
|
||||||
|
circuitmux_set_num_cells(pchan->cmux, circ, 4);
|
||||||
|
|
||||||
|
/* Clear it out. */
|
||||||
|
circuitmux_clear_policy(pchan->cmux);
|
||||||
|
|
||||||
|
/* Set back the EWMA policy. */
|
||||||
|
circuitmux_set_policy(pchan->cmux, &ewma_policy);
|
||||||
|
|
||||||
|
done:
|
||||||
|
free_fake_orcirc(orcirc);
|
||||||
|
free_fake_channel(pchan);
|
||||||
|
free_fake_channel(nchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_xmit_cell(void *arg)
|
||||||
|
{
|
||||||
|
circuit_t *circ = NULL;
|
||||||
|
or_circuit_t *orcirc = NULL;
|
||||||
|
channel_t *pchan = NULL, *nchan = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pchan = new_fake_channel();
|
||||||
|
tt_assert(pchan);
|
||||||
|
nchan = new_fake_channel();
|
||||||
|
tt_assert(nchan);
|
||||||
|
|
||||||
|
orcirc = new_fake_orcirc(nchan, pchan);
|
||||||
|
tt_assert(orcirc);
|
||||||
|
circ = TO_CIRCUIT(orcirc);
|
||||||
|
|
||||||
|
/* Queue 4 cells on the circuit. */
|
||||||
|
circuitmux_set_num_cells(pchan->cmux, circ, 4);
|
||||||
|
tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 4);
|
||||||
|
tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 4);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Emit the first cell. Circuit should still be active. */
|
||||||
|
circuitmux_notify_xmit_cells(pchan->cmux, circ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 3);
|
||||||
|
tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 3);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 1);
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Emit the last 3 cells. Circuit should become inactive. */
|
||||||
|
circuitmux_notify_xmit_cells(pchan->cmux, circ, 3);
|
||||||
|
tt_uint_op(circuitmux_num_cells(pchan->cmux), OP_EQ, 0);
|
||||||
|
tt_uint_op(circuitmux_num_cells_for_circuit(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_int_op(circuitmux_is_circuit_active(pchan->cmux, circ), OP_EQ, 0);
|
||||||
|
tt_uint_op(circuitmux_num_active_circuits(pchan->cmux), OP_EQ, 0);
|
||||||
|
|
||||||
|
/* Queue a DESTROY cell. */
|
||||||
|
pchan->has_queued_writes = mock_has_queued_writes_true;
|
||||||
|
circuitmux_append_destroy_cell(pchan, pchan->cmux, orcirc->p_circ_id, 0);
|
||||||
|
tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 1);
|
||||||
|
tt_int_op(pchan->cmux->destroy_cell_queue.n, OP_EQ, 1);
|
||||||
|
tt_int_op(circuitmux_count_queued_destroy_cells(pchan, pchan->cmux),
|
||||||
|
OP_EQ, 1);
|
||||||
|
|
||||||
|
/* Emit the DESTROY cell. */
|
||||||
|
circuitmux_notify_xmit_destroy(pchan->cmux);
|
||||||
|
tt_int_op(pchan->cmux->destroy_ctr, OP_EQ, 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
free_fake_orcirc(orcirc);
|
||||||
|
free_fake_channel(pchan);
|
||||||
|
free_fake_channel(nchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
cmux_setup_test(const struct testcase_t *tc)
|
||||||
|
{
|
||||||
|
static int whatever;
|
||||||
|
|
||||||
|
(void) tc;
|
||||||
|
|
||||||
|
cell_ewma_initialize_ticks();
|
||||||
|
return &whatever;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmux_cleanup_test(const struct testcase_t *tc, void *ptr)
|
||||||
|
{
|
||||||
|
(void) tc;
|
||||||
|
(void) ptr;
|
||||||
|
|
||||||
|
circuitmux_ewma_free_all();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct testcase_setup_t cmux_test_setup = {
|
||||||
|
.setup_fn = cmux_setup_test,
|
||||||
|
.cleanup_fn = cmux_cleanup_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_CMUX(name) \
|
||||||
|
{ #name, test_cmux_##name, TT_FORK, &cmux_test_setup, NULL }
|
||||||
|
|
||||||
struct testcase_t circuitmux_tests[] = {
|
struct testcase_t circuitmux_tests[] = {
|
||||||
{ "destroy_cell_queue", test_cmux_destroy_cell_queue, TT_FORK, NULL, NULL },
|
/* Test circuitmux_t object */
|
||||||
{ "compute_ticks", test_cmux_compute_ticks, TT_FORK, NULL, NULL },
|
TEST_CMUX(allocate),
|
||||||
|
TEST_CMUX(attach_circuit),
|
||||||
|
TEST_CMUX(detach_circuit),
|
||||||
|
TEST_CMUX(detach_all_circuits),
|
||||||
|
TEST_CMUX(policy),
|
||||||
|
TEST_CMUX(xmit_cell),
|
||||||
|
|
||||||
|
/* Misc. */
|
||||||
|
TEST_CMUX(compute_ticks),
|
||||||
|
TEST_CMUX(destroy_cell_queue),
|
||||||
|
|
||||||
END_OF_TESTCASES
|
END_OF_TESTCASES
|
||||||
};
|
};
|
||||||
|
|
||||||
|
228
src/test/test_circuitmux_ewma.c
Normal file
228
src/test/test_circuitmux_ewma.c
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/* Copyright (c) 2013-2019, The Tor Project, Inc. */
|
||||||
|
/* See LICENSE for licensing information */
|
||||||
|
|
||||||
|
#define CIRCUITMUX_PRIVATE
|
||||||
|
#define CIRCUITMUX_EWMA_PRIVATE
|
||||||
|
|
||||||
|
#include "core/or/or.h"
|
||||||
|
#include "core/or/circuitmux.h"
|
||||||
|
#include "core/or/circuitmux_ewma.h"
|
||||||
|
|
||||||
|
#include "test/fakechans.h"
|
||||||
|
#include "test/fakecircs.h"
|
||||||
|
#include "test/test.h"
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_ewma_active_circuit(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t cmux; /* garbage */
|
||||||
|
circuitmux_policy_data_t *pol_data = NULL;
|
||||||
|
circuit_t circ; /* garbage */
|
||||||
|
circuitmux_policy_circ_data_t *circ_data = NULL;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pol_data = ewma_policy.alloc_cmux_data(&cmux);
|
||||||
|
tt_assert(pol_data);
|
||||||
|
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
|
||||||
|
CELL_DIRECTION_OUT, 42);
|
||||||
|
tt_assert(circ_data);
|
||||||
|
|
||||||
|
/* Get EWMA specific objects. */
|
||||||
|
|
||||||
|
/* Make circuit active. */
|
||||||
|
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
|
||||||
|
|
||||||
|
circuit_t *entry = ewma_policy.pick_active_circuit(&cmux, pol_data);
|
||||||
|
tt_mem_op(entry, OP_EQ, &circ, sizeof(circ));
|
||||||
|
|
||||||
|
done:
|
||||||
|
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
|
||||||
|
ewma_policy.free_cmux_data(&cmux, pol_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_ewma_xmit_cell(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t cmux; /* garbage */
|
||||||
|
circuitmux_policy_data_t *pol_data = NULL;
|
||||||
|
circuit_t circ; /* garbage */
|
||||||
|
circuitmux_policy_circ_data_t *circ_data = NULL;
|
||||||
|
ewma_policy_data_t *ewma_pol_data;
|
||||||
|
ewma_policy_circ_data_t *ewma_data;
|
||||||
|
double old_cell_count;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pol_data = ewma_policy.alloc_cmux_data(&cmux);
|
||||||
|
tt_assert(pol_data);
|
||||||
|
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
|
||||||
|
CELL_DIRECTION_OUT, 42);
|
||||||
|
tt_assert(circ_data);
|
||||||
|
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
|
||||||
|
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
|
||||||
|
|
||||||
|
/* Make circuit active. */
|
||||||
|
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
|
||||||
|
|
||||||
|
/* Move back in time the last time we calibrated so we scale the active
|
||||||
|
* circuit when emitting a cell. */
|
||||||
|
ewma_pol_data->active_circuit_pqueue_last_recalibrated -= 100;
|
||||||
|
ewma_data->cell_ewma.last_adjusted_tick =
|
||||||
|
ewma_pol_data->active_circuit_pqueue_last_recalibrated;
|
||||||
|
|
||||||
|
/* Grab old cell count. */
|
||||||
|
old_cell_count = ewma_data->cell_ewma.cell_count;
|
||||||
|
|
||||||
|
ewma_policy.notify_xmit_cells(&cmux, pol_data, &circ, circ_data, 1);
|
||||||
|
|
||||||
|
/* Our old cell count should be lower to what we have since we just emitted
|
||||||
|
* a cell and thus we scale. */
|
||||||
|
tt_double_op(old_cell_count, OP_LT, ewma_data->cell_ewma.cell_count);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
|
||||||
|
ewma_policy.free_cmux_data(&cmux, pol_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_ewma_notify_circ(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t cmux; /* garbage */
|
||||||
|
circuitmux_policy_data_t *pol_data = NULL;
|
||||||
|
circuit_t circ; /* garbage */
|
||||||
|
circuitmux_policy_circ_data_t *circ_data = NULL;
|
||||||
|
const ewma_policy_data_t *ewma_pol_data;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pol_data = ewma_policy.alloc_cmux_data(&cmux);
|
||||||
|
tt_assert(pol_data);
|
||||||
|
circ_data = ewma_policy.alloc_circ_data(&cmux, pol_data, &circ,
|
||||||
|
CELL_DIRECTION_OUT, 42);
|
||||||
|
tt_assert(circ_data);
|
||||||
|
|
||||||
|
/* Currently, notify_circ_active() ignores cmux and circ. They can not be
|
||||||
|
* NULL so it is fine to pass garbage. */
|
||||||
|
ewma_policy.notify_circ_active(&cmux, pol_data, &circ, circ_data);
|
||||||
|
|
||||||
|
/* We should have an active circuit in the queue so its EWMA value can be
|
||||||
|
* tracked. */
|
||||||
|
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
|
||||||
|
tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 1);
|
||||||
|
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
|
||||||
|
|
||||||
|
ewma_policy.notify_circ_inactive(&cmux, pol_data, &circ, circ_data);
|
||||||
|
/* Should be removed from the active queue. */
|
||||||
|
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
|
||||||
|
tt_int_op(smartlist_len(ewma_pol_data->active_circuit_pqueue), OP_EQ, 0);
|
||||||
|
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ewma_policy.free_circ_data(&cmux, pol_data, &circ, circ_data);
|
||||||
|
ewma_policy.free_cmux_data(&cmux, pol_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_ewma_policy_circ_data(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t cmux; /* garbage */
|
||||||
|
circuitmux_policy_data_t pol_data; /* garbage */
|
||||||
|
circuit_t circ; /* garbage */
|
||||||
|
circuitmux_policy_circ_data_t *circ_data = NULL;
|
||||||
|
const ewma_policy_circ_data_t *ewma_data;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
/* Currently, alloc_circ_data() ignores every parameter _except_ the cell
|
||||||
|
* direction so it is OK to pass garbage. They can not be NULL. */
|
||||||
|
circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
|
||||||
|
CELL_DIRECTION_OUT, 42);
|
||||||
|
tt_assert(circ_data);
|
||||||
|
tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
|
||||||
|
|
||||||
|
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
|
||||||
|
tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
|
||||||
|
tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
|
||||||
|
tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
|
||||||
|
tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 0);
|
||||||
|
ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
|
||||||
|
|
||||||
|
circ_data = ewma_policy.alloc_circ_data(&cmux, &pol_data, &circ,
|
||||||
|
CELL_DIRECTION_IN, 42);
|
||||||
|
tt_assert(circ_data);
|
||||||
|
tt_uint_op(circ_data->magic, OP_EQ, EWMA_POL_CIRC_DATA_MAGIC);
|
||||||
|
|
||||||
|
ewma_data = TO_EWMA_POL_CIRC_DATA(circ_data);
|
||||||
|
tt_mem_op(ewma_data->circ, OP_EQ, &circ, sizeof(circuit_t));
|
||||||
|
tt_double_op(ewma_data->cell_ewma.cell_count, OP_LE, 0.0);
|
||||||
|
tt_int_op(ewma_data->cell_ewma.heap_index, OP_EQ, -1);
|
||||||
|
tt_uint_op(ewma_data->cell_ewma.is_for_p_chan, OP_EQ, 1);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ewma_policy.free_circ_data(&cmux, &pol_data, &circ, circ_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_cmux_ewma_policy_data(void *arg)
|
||||||
|
{
|
||||||
|
circuitmux_t cmux; /* garbage. */
|
||||||
|
circuitmux_policy_data_t *pol_data = NULL;
|
||||||
|
const ewma_policy_data_t *ewma_pol_data;
|
||||||
|
|
||||||
|
(void) arg;
|
||||||
|
|
||||||
|
pol_data = ewma_policy.alloc_cmux_data(&cmux);
|
||||||
|
tt_assert(pol_data);
|
||||||
|
tt_uint_op(pol_data->magic, OP_EQ, EWMA_POL_DATA_MAGIC);
|
||||||
|
|
||||||
|
/* Test EWMA object. */
|
||||||
|
ewma_pol_data = TO_EWMA_POL_DATA(pol_data);
|
||||||
|
tt_assert(ewma_pol_data->active_circuit_pqueue);
|
||||||
|
tt_uint_op(ewma_pol_data->active_circuit_pqueue_last_recalibrated, OP_NE, 0);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ewma_policy.free_cmux_data(&cmux, pol_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
cmux_ewma_setup_test(const struct testcase_t *tc)
|
||||||
|
{
|
||||||
|
static int whatever;
|
||||||
|
|
||||||
|
(void) tc;
|
||||||
|
|
||||||
|
cell_ewma_initialize_ticks();
|
||||||
|
cmux_ewma_set_options(NULL, NULL);
|
||||||
|
|
||||||
|
return &whatever;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmux_ewma_cleanup_test(const struct testcase_t *tc, void *ptr)
|
||||||
|
{
|
||||||
|
(void) tc;
|
||||||
|
(void) ptr;
|
||||||
|
|
||||||
|
circuitmux_ewma_free_all();
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct testcase_setup_t cmux_ewma_test_setup = {
|
||||||
|
.setup_fn = cmux_ewma_setup_test,
|
||||||
|
.cleanup_fn = cmux_ewma_cleanup_test,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TEST_CMUX_EWMA(name) \
|
||||||
|
{ #name, test_cmux_ewma_##name, TT_FORK, &cmux_ewma_test_setup, NULL }
|
||||||
|
|
||||||
|
struct testcase_t circuitmux_ewma_tests[] = {
|
||||||
|
TEST_CMUX_EWMA(active_circuit),
|
||||||
|
TEST_CMUX_EWMA(policy_data),
|
||||||
|
TEST_CMUX_EWMA(policy_circ_data),
|
||||||
|
TEST_CMUX_EWMA(notify_circ),
|
||||||
|
TEST_CMUX_EWMA(xmit_cell),
|
||||||
|
|
||||||
|
END_OF_TESTCASES
|
||||||
|
};
|
@ -38,6 +38,7 @@
|
|||||||
#include "core/or/or_circuit_st.h"
|
#include "core/or/or_circuit_st.h"
|
||||||
#include "core/or/origin_circuit_st.h"
|
#include "core/or/origin_circuit_st.h"
|
||||||
|
|
||||||
|
#include "test/fakecircs.h"
|
||||||
#include "test/rng_test_helpers.h"
|
#include "test/rng_test_helpers.h"
|
||||||
|
|
||||||
/* Start our monotime mocking at 1 second past whatever monotime_init()
|
/* Start our monotime mocking at 1 second past whatever monotime_init()
|
||||||
@ -53,7 +54,6 @@ circid_t get_unique_circ_id_by_chan(channel_t *chan);
|
|||||||
void helper_create_basic_machine(void);
|
void helper_create_basic_machine(void);
|
||||||
static void helper_create_conditional_machines(void);
|
static void helper_create_conditional_machines(void);
|
||||||
|
|
||||||
static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
|
|
||||||
channel_t *new_fake_channel(void);
|
channel_t *new_fake_channel(void);
|
||||||
void test_circuitpadding_negotiation(void *arg);
|
void test_circuitpadding_negotiation(void *arg);
|
||||||
void test_circuitpadding_wronghop(void *arg);
|
void test_circuitpadding_wronghop(void *arg);
|
||||||
@ -67,7 +67,6 @@ void test_circuitpadding_state_length(void *arg);
|
|||||||
static void
|
static void
|
||||||
simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
|
simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
|
||||||
int padding);
|
int padding);
|
||||||
void free_fake_orcirc(circuit_t *circ);
|
|
||||||
void free_fake_origin_circuit(origin_circuit_t *circ);
|
void free_fake_origin_circuit(origin_circuit_t *circ);
|
||||||
|
|
||||||
static int deliver_negotiated = 1;
|
static int deliver_negotiated = 1;
|
||||||
@ -127,62 +126,6 @@ circuit_get_nth_node_mock(origin_circuit_t *circ, int hop)
|
|||||||
return &padding_node;
|
return &padding_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static or_circuit_t *
|
|
||||||
new_fake_orcirc(channel_t *nchan, channel_t *pchan)
|
|
||||||
{
|
|
||||||
or_circuit_t *orcirc = NULL;
|
|
||||||
circuit_t *circ = NULL;
|
|
||||||
crypt_path_t tmp_cpath;
|
|
||||||
char whatevs_key[CPATH_KEY_MATERIAL_LEN];
|
|
||||||
|
|
||||||
orcirc = tor_malloc_zero(sizeof(*orcirc));
|
|
||||||
circ = &(orcirc->base_);
|
|
||||||
circ->magic = OR_CIRCUIT_MAGIC;
|
|
||||||
|
|
||||||
//circ->n_chan = nchan;
|
|
||||||
circ->n_circ_id = get_unique_circ_id_by_chan(nchan);
|
|
||||||
cell_queue_init(&(circ->n_chan_cells));
|
|
||||||
circ->n_hop = NULL;
|
|
||||||
circ->streams_blocked_on_n_chan = 0;
|
|
||||||
circ->streams_blocked_on_p_chan = 0;
|
|
||||||
circ->n_delete_pending = 0;
|
|
||||||
circ->p_delete_pending = 0;
|
|
||||||
circ->received_destroy = 0;
|
|
||||||
circ->state = CIRCUIT_STATE_OPEN;
|
|
||||||
circ->purpose = CIRCUIT_PURPOSE_OR;
|
|
||||||
circ->package_window = CIRCWINDOW_START_MAX;
|
|
||||||
circ->deliver_window = CIRCWINDOW_START_MAX;
|
|
||||||
circ->n_chan_create_cell = NULL;
|
|
||||||
|
|
||||||
//orcirc->p_chan = pchan;
|
|
||||||
orcirc->p_circ_id = get_unique_circ_id_by_chan(pchan);
|
|
||||||
cell_queue_init(&(orcirc->p_chan_cells));
|
|
||||||
|
|
||||||
circuit_set_p_circid_chan(orcirc, orcirc->p_circ_id, pchan);
|
|
||||||
circuit_set_n_circid_chan(circ, circ->n_circ_id, nchan);
|
|
||||||
|
|
||||||
memset(&tmp_cpath, 0, sizeof(tmp_cpath));
|
|
||||||
if (cpath_init_circuit_crypto(&tmp_cpath, whatevs_key,
|
|
||||||
sizeof(whatevs_key), 0, 0)<0) {
|
|
||||||
log_warn(LD_BUG,"Circuit initialization failed");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
orcirc->crypto = tmp_cpath.pvt_crypto;
|
|
||||||
|
|
||||||
return orcirc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
free_fake_orcirc(circuit_t *circ)
|
|
||||||
{
|
|
||||||
or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
|
|
||||||
|
|
||||||
relay_crypto_clear(&orcirc->crypto);
|
|
||||||
|
|
||||||
circpad_circuit_free_all_machineinfos(circ);
|
|
||||||
tor_free(circ);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
free_fake_origin_circuit(origin_circuit_t *circ)
|
free_fake_origin_circuit(origin_circuit_t *circ)
|
||||||
{
|
{
|
||||||
@ -413,7 +356,7 @@ test_circuitpadding_rtt(void *arg)
|
|||||||
circpad_machine_current_state(
|
circpad_machine_current_state(
|
||||||
client_side->padding_info[0])->histogram_edges[0]);
|
client_side->padding_info[0])->histogram_edges[0]);
|
||||||
done:
|
done:
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
timers_shutdown();
|
timers_shutdown();
|
||||||
@ -1439,7 +1382,7 @@ test_circuitpadding_wronghop(void *arg)
|
|||||||
|
|
||||||
/* Test 2: Test no padding */
|
/* Test 2: Test no padding */
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
|
|
||||||
client_side = TO_CIRCUIT(origin_circuit_new());
|
client_side = TO_CIRCUIT(origin_circuit_new());
|
||||||
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
|
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
|
||||||
@ -1484,7 +1427,7 @@ test_circuitpadding_wronghop(void *arg)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
monotime_disable_test_mocking();
|
monotime_disable_test_mocking();
|
||||||
@ -1553,7 +1496,7 @@ test_circuitpadding_negotiation(void *arg)
|
|||||||
|
|
||||||
/* Test 2: Test no padding */
|
/* Test 2: Test no padding */
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
|
|
||||||
client_side = TO_CIRCUIT(origin_circuit_new());
|
client_side = TO_CIRCUIT(origin_circuit_new());
|
||||||
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
|
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
|
||||||
@ -1591,7 +1534,7 @@ test_circuitpadding_negotiation(void *arg)
|
|||||||
|
|
||||||
/* 3. Test failure to negotiate a machine due to desync */
|
/* 3. Test failure to negotiate a machine due to desync */
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
|
|
||||||
client_side = TO_CIRCUIT(origin_circuit_new());
|
client_side = TO_CIRCUIT(origin_circuit_new());
|
||||||
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
|
relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
|
||||||
@ -1619,7 +1562,7 @@ test_circuitpadding_negotiation(void *arg)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
monotime_disable_test_mocking();
|
monotime_disable_test_mocking();
|
||||||
@ -1939,7 +1882,7 @@ test_circuitpadding_state_length(void *arg)
|
|||||||
tor_free(client_machine);
|
tor_free(client_machine);
|
||||||
|
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
|
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
@ -2312,7 +2255,7 @@ test_circuitpadding_circuitsetup_machine(void *arg)
|
|||||||
tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
|
tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
|
||||||
OP_NE, 0);
|
OP_NE, 0);
|
||||||
circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE);
|
circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE);
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
timers_advance_and_run(5000);
|
timers_advance_and_run(5000);
|
||||||
|
|
||||||
/* No cells sent */
|
/* No cells sent */
|
||||||
@ -2616,7 +2559,7 @@ test_circuitpadding_global_rate_limiting(void *arg)
|
|||||||
tt_int_op(retval, OP_EQ, 0);
|
tt_int_op(retval, OP_EQ, 0);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
|
SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
|
||||||
@ -2769,7 +2712,7 @@ test_circuitpadding_reduce_disable(void *arg)
|
|||||||
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
|
tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
testing_disable_reproducible_rng();
|
testing_disable_reproducible_rng();
|
||||||
@ -3075,7 +3018,7 @@ helper_test_hs_machines(bool test_intro_circs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
free_fake_orcirc(relay_side);
|
free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
|
||||||
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
|
||||||
circuitmux_free(dummy_channel.cmux);
|
circuitmux_free(dummy_channel.cmux);
|
||||||
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
|
||||||
|
@ -21,42 +21,10 @@
|
|||||||
/* Test suite stuff */
|
/* Test suite stuff */
|
||||||
#include "test/test.h"
|
#include "test/test.h"
|
||||||
#include "test/fakechans.h"
|
#include "test/fakechans.h"
|
||||||
|
#include "test/fakecircs.h"
|
||||||
static or_circuit_t * new_fake_orcirc(channel_t *nchan, channel_t *pchan);
|
|
||||||
|
|
||||||
static void test_relay_append_cell_to_circuit_queue(void *arg);
|
static void test_relay_append_cell_to_circuit_queue(void *arg);
|
||||||
|
|
||||||
static or_circuit_t *
|
|
||||||
new_fake_orcirc(channel_t *nchan, channel_t *pchan)
|
|
||||||
{
|
|
||||||
or_circuit_t *orcirc = NULL;
|
|
||||||
circuit_t *circ = NULL;
|
|
||||||
|
|
||||||
orcirc = tor_malloc_zero(sizeof(*orcirc));
|
|
||||||
circ = &(orcirc->base_);
|
|
||||||
circ->magic = OR_CIRCUIT_MAGIC;
|
|
||||||
|
|
||||||
circuit_set_n_circid_chan(circ, get_unique_circ_id_by_chan(nchan), nchan);
|
|
||||||
cell_queue_init(&(circ->n_chan_cells));
|
|
||||||
|
|
||||||
circ->n_hop = NULL;
|
|
||||||
circ->streams_blocked_on_n_chan = 0;
|
|
||||||
circ->streams_blocked_on_p_chan = 0;
|
|
||||||
circ->n_delete_pending = 0;
|
|
||||||
circ->p_delete_pending = 0;
|
|
||||||
circ->received_destroy = 0;
|
|
||||||
circ->state = CIRCUIT_STATE_OPEN;
|
|
||||||
circ->purpose = CIRCUIT_PURPOSE_OR;
|
|
||||||
circ->package_window = CIRCWINDOW_START_MAX;
|
|
||||||
circ->deliver_window = CIRCWINDOW_START_MAX;
|
|
||||||
circ->n_chan_create_cell = NULL;
|
|
||||||
|
|
||||||
circuit_set_p_circid_chan(orcirc, get_unique_circ_id_by_chan(pchan), pchan);
|
|
||||||
cell_queue_init(&(orcirc->p_chan_cells));
|
|
||||||
|
|
||||||
return orcirc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
assert_circuit_ok_mock(const circuit_t *c)
|
assert_circuit_ok_mock(const circuit_t *c)
|
||||||
{
|
{
|
||||||
@ -145,7 +113,7 @@ test_relay_close_circuit(void *arg)
|
|||||||
cell_queue_clear(&orcirc->base_.n_chan_cells);
|
cell_queue_clear(&orcirc->base_.n_chan_cells);
|
||||||
cell_queue_clear(&orcirc->p_chan_cells);
|
cell_queue_clear(&orcirc->p_chan_cells);
|
||||||
}
|
}
|
||||||
tor_free(orcirc);
|
free_fake_orcirc(orcirc);
|
||||||
free_fake_channel(nchan);
|
free_fake_channel(nchan);
|
||||||
free_fake_channel(pchan);
|
free_fake_channel(pchan);
|
||||||
UNMOCK(assert_circuit_ok);
|
UNMOCK(assert_circuit_ok);
|
||||||
@ -218,7 +186,7 @@ test_relay_append_cell_to_circuit_queue(void *arg)
|
|||||||
cell_queue_clear(&orcirc->base_.n_chan_cells);
|
cell_queue_clear(&orcirc->base_.n_chan_cells);
|
||||||
cell_queue_clear(&orcirc->p_chan_cells);
|
cell_queue_clear(&orcirc->p_chan_cells);
|
||||||
}
|
}
|
||||||
tor_free(orcirc);
|
free_fake_orcirc(orcirc);
|
||||||
free_fake_channel(nchan);
|
free_fake_channel(nchan);
|
||||||
free_fake_channel(pchan);
|
free_fake_channel(pchan);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user