40#include "core/or/or_circuit_st.h"
50worker_state_new(
void *arg)
59#define worker_state_free(ws) \
60 FREE_AND_NULL(worker_state_t, worker_state_free_, (ws))
67 server_onion_keys_free(ws->onion_keys);
72worker_state_free_void(
void *arg)
74 worker_state_free_(arg);
79static uint32_t total_pending_tasks = 0;
80static uint32_t max_pending_tasks = 128;
88#define MAX_PENDING_TASKS_PER_CPU_DEFAULT 64
89#define MAX_PENDING_TASKS_PER_CPU_MIN 1
90#define MAX_PENDING_TASKS_PER_CPU_MAX INT32_MAX
93 MAX_PENDING_TASKS_PER_CPU_DEFAULT,
94 MAX_PENDING_TASKS_PER_CPU_MIN,
95 MAX_PENDING_TASKS_PER_CPU_MAX);
132 worker_state_free_void,
146 threadpool_free(threadpool);
161#define CPUWORKER_REQUEST_MAGIC 0xda4afeed
162#define CPUWORKER_REPLY_MAGIC 0x5eedf00d
211 uint8_t
keys[CPATH_KEY_MATERIAL_LEN];
218typedef struct cpuworker_job_u_t {
227update_state_threadfn(
void *state_,
void *work_)
231 server_onion_keys_free(state->onion_keys);
232 state->onion_keys = update->onion_keys;
233 update->onion_keys = NULL;
234 worker_state_free(update);
253 update_state_threadfn,
254 worker_state_free_void,
256 log_warn(
LD_OR,
"Failed to queue key update for worker threads.");
275#define MAX_BELIEVABLE_ONIONSKIN_DELAY (2*1000*1000)
283 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
301 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
302 return 1000 * (uint64_t)n_requests;
305 return 1000 * (uint64_t)n_requests;
321 uint16_t onionskin_type)
328 if (onionskin_type > MAX_ONION_HANDSHAKE_TYPE)
348 const char *onionskin_type_name)
351 double relative_overhead;
356 if (!overhead || r<0)
360 "%s onionskins have averaged %u usec overhead (%.2f%%) in "
362 onionskin_type_name, (
unsigned)overhead, relative_overhead*100);
374 --total_pending_tasks;
377 memcpy(&rpl, &job->u.reply,
sizeof(rpl));
385 struct timeval tv_end, tv_diff;
386 int64_t usec_roundtrip;
389 usec_roundtrip = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
390 if (usec_roundtrip >= 0 &&
408 "Unpacking cpuworker reply %p, circ=%p, success=%d",
415 log_debug(
LD_OR,
"Circuit died while reply was pending. Freeing memory.");
416 circ->base_.
magic = 0;
418 goto done_processing;
425 log_debug(
LD_OR,
"circuit is already marked.");
426 goto done_processing;
431 "decoding onionskin failed. "
432 "(Old key or bad software.) Closing.");
433 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
434 goto done_processing;
451 (
const char*)rpl.
keys,
sizeof(rpl.
keys),
453 log_warn(
LD_OR,
"onionskin_answer failed. Closing.");
454 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
455 goto done_processing;
458 log_debug(
LD_OR,
"onionskin_answer succeeded. Yay.");
479 memcpy(&req, &job->u.request,
sizeof(req));
482 memset(&rpl, 0,
sizeof(rpl));
486 struct timeval tv_start = {0,0}, tv_end;
498 sizeof(cell_out->
reply),
499 rpl.
keys, CPATH_KEY_MATERIAL_LEN,
504 log_debug(
LD_OR,
"onion_skin_server_handshake failed.");
505 memset(&rpl, 0,
sizeof(rpl));
509 log_debug(
LD_OR,
"onion_skin_server_handshake succeeded.");
513 cell_out->
cell_type = CELL_CREATED;
break;
515 cell_out->
cell_type = CELL_CREATED2;
break;
516 case CELL_CREATE_FAST:
517 cell_out->
cell_type = CELL_CREATED_FAST;
break;
525 rpl.
magic = CPUWORKER_REPLY_MAGIC;
530 timersub(&tv_end, &tv_start, &tv_diff);
531 usec = ((int64_t)tv_diff.tv_sec)*1000000 + tv_diff.tv_usec;
535 rpl.
n_usec = (uint32_t) usec;
538 memcpy(&job->u.reply, &rpl,
sizeof(rpl));
552 while (total_pending_tasks < max_pending_tasks) {
559 log_info(
LD_OR,
"assign_to_cpuworker failed. Ignoring.");
567 void (*reply_fn)(
void *),
596 log_info(
LD_OR,
"circ->p_chan gone. Failing circ.");
601 if (total_pending_tasks >= max_pending_tasks) {
602 log_debug(
LD_OR,
"No idle cpuworkers. Queuing.");
614 memset(&req, 0,
sizeof(req));
616 req.
timed = should_time;
632 memcpy(&job->u.request, &req,
sizeof(req));
635 ++total_pending_tasks;
642 log_warn(
LD_BUG,
"Couldn't queue work on threadpool");
647 log_debug(
LD_OR,
"Queued task %p (qe=%p, circ=%p)",
648 job, queue_entry, job->circ);
667 memwipe(job, 0xe0,
sizeof(*job));
670 --total_pending_tasks;
int channel_is_client(const channel_t *chan)
Header file for channel.c.
#define DEAD_CIRCUIT_MAGIC
int onionskin_answer(struct or_circuit_t *circ, const created_cell_t *created_cell, const char *keys, size_t keys_len, const uint8_t *rend_circ_nonce)
Header for feature/relay/circuitbuild_relay.c.
Header file for circuitlist.c.
int get_num_cpus(const or_options_t *options)
const or_options_t * get_options(void)
Header file for config.c.
congestion_control_t * congestion_control_new(const circuit_params_t *params, cc_path_t path)
bool congestion_control_enabled(void)
Public APIs for congestion control.
static uint8_t congestion_control_sendme_inc(void)
APIs for stream flow control on congestion controlled circuits.
Header file for connection_or.c.
#define CPUWORKER_REQUEST_MAGIC
static void queue_pending_tasks(void)
void cpuworker_cancel_circ_handshake(or_circuit_t *circ)
#define MAX_BELIEVABLE_ONIONSKIN_DELAY
static uint64_t onionskins_usec_roundtrip[MAX_ONION_HANDSHAKE_TYPE+1]
static uint32_t get_max_pending_tasks_per_cpu(const networkstatus_t *ns)
int assign_onionskin_to_cpuworker(or_circuit_t *circ, create_cell_t *onionskin)
static void set_max_pending_tasks(const networkstatus_t *ns)
static uint64_t onionskins_n_processed[MAX_ONION_HANDSHAKE_TYPE+1]
workqueue_entry_t * cpuworker_queue_work(workqueue_priority_t priority, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
void cpuworker_free_all(void)
static int get_overhead_for_onionskins(uint32_t *usec_out, double *frac_out, uint16_t onionskin_type)
void cpuworker_init(void)
unsigned int cpuworker_get_n_threads(void)
void cpuworker_consensus_has_changed(const networkstatus_t *ns)
void cpuworker_log_onionskin_overhead(int severity, int onionskin_type, const char *onionskin_type_name)
static workqueue_reply_t cpuworker_onion_handshake_threadfn(void *state_, void *work_)
void cpuworkers_rotate_keyinfo(void)
static uint64_t onionskins_usec_internal[MAX_ONION_HANDSHAKE_TYPE+1]
static void cpuworker_onion_handshake_replyfn(void *work_)
uint64_t estimated_usec_for_onionskins(uint32_t n_requests, uint16_t onionskin_type)
static int should_time_request(uint16_t onionskin_type)
Header file for cpuworker.c.
Common functions for using (pseudo-)random number generators.
#define crypto_fast_rng_one_in_n(rng, n)
crypto_fast_rng_t * get_thread_fast_rng(void)
void memwipe(void *mem, uint8_t byte, size_t sz)
Common functions for cryptographic routines.
#define log_fn(severity, domain, args,...)
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
int onion_skin_server_handshake(int type, const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, const circuit_params_t *our_ns_params, uint8_t *reply_out, size_t reply_out_maxlen, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_nonce_out, circuit_params_t *params_out)
server_onion_keys_t * server_onion_keys_new(void)
Header file for onion_crypto.c.
int onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
or_circuit_t * onion_next_task(create_cell_t **onionskin_out)
Header file for onion_queue.c.
Master header file for Tor-specific functionality.
void rep_hist_note_circuit_handshake_assigned(uint16_t type)
Header file for rephist.c.
Header file for router.c.
struct timeval started_at
created_cell_t created_cell
uint8_t keys[CPATH_KEY_MATERIAL_LEN]
uint8_t rend_auth_material[DIGEST_LEN]
circuit_params_t circ_params
struct timeval started_at
create_cell_t create_cell
circuit_params_t circ_ns_params
uint8_t onionskin[CELL_PAYLOAD_SIZE - 4]
uint8_t reply[CELL_PAYLOAD_SIZE - 2]
struct workqueue_entry_t * workqueue_entry
#define MOCK_IMPL(rv, funcname, arglist)
#define timersub(tv1, tv2, tvout)
void tor_gettimeofday(struct timeval *timeval)
void * workqueue_entry_cancel(workqueue_entry_t *ent)
workqueue_entry_t * threadpool_queue_work_priority(threadpool_t *pool, workqueue_priority_t prio, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
replyqueue_t * replyqueue_new(uint32_t alertsocks_flags)
int threadpool_register_reply_event(threadpool_t *tp, void(*cb)(threadpool_t *tp))
int threadpool_queue_update(threadpool_t *pool, void *(*dup_fn)(void *), workqueue_reply_t(*fn)(void *, void *), void(*free_fn)(void *), void *arg)
threadpool_t * threadpool_new(int n_threads, replyqueue_t *replyqueue, void *(*new_thread_state_fn)(void *), void(*free_thread_state_fn)(void *), void *arg)
unsigned int threadpool_get_n_threads(threadpool_t *tp)