1 #define CHANNEL_OBJECT_PRIVATE
2 #define TOR_TIMERS_PRIVATE
3 #define CIRCUITPADDING_PRIVATE
4 #define CIRCUITPADDING_MACHINES_PRIVATE
5 #define NETWORKSTATUS_PRIVATE
6 #define CRYPT_PATH_PRIVATE
9 #include "core/or/or.h"
10 #include "test/test.h"
11 #include "test/log_test_helpers.h"
12 #include "lib/testsupport/testsupport.h"
13 #include "core/or/connection_or.h"
14 #include "core/or/channel.h"
15 #include "core/or/channeltls.h"
16 #include "core/or/crypt_path.h"
18 #include "lib/evloop/compat_libevent.h"
19 #include "lib/time/compat_time.h"
20 #include "lib/defs/time.h"
21 #include "core/or/relay.h"
22 #include "core/or/circuitlist.h"
23 #include "core/or/circuitbuild.h"
24 #include "core/or/circuitpadding.h"
25 #include "core/or/circuitpadding_machines.h"
26 #include "core/or/extendinfo.h"
27 #include "core/mainloop/netstatus.h"
28 #include "core/crypto/relay_crypto.h"
29 #include "core/or/protover.h"
30 #include "feature/nodelist/nodelist.h"
31 #include "app/config/config.h"
33 #include "feature/nodelist/routerstatus_st.h"
34 #include "feature/nodelist/networkstatus_st.h"
35 #include "feature/nodelist/node_st.h"
36 #include "core/or/cell_st.h"
37 #include "core/or/crypt_path_st.h"
38 #include "core/or/or_circuit_st.h"
39 #include "core/or/origin_circuit_st.h"
41 #include "test/fakecircs.h"
42 #include "test/rng_test_helpers.h"
44 /* Start our monotime mocking at 1 second past whatever monotime_init()
45 * thought the actual wall clock time was, for platforms with bad resolution
46 * and weird timevalues during monotime_init() before mocking. */
47 #define MONOTIME_MOCK_START (monotime_absolute_nsec()+\
48 TOR_NSEC_PER_USEC*TOR_USEC_PER_SEC)
50 extern smartlist_t
*connection_array
;
51 void circuit_expire_old_circuits_clientside(void);
53 circid_t
get_unique_circ_id_by_chan(channel_t
*chan
);
54 void helper_create_basic_machine(void);
55 static void helper_create_conditional_machines(void);
57 channel_t
*new_fake_channel(void);
58 void test_circuitpadding_negotiation(void *arg
);
59 void test_circuitpadding_wronghop(void *arg
);
60 void test_circuitpadding_conditions(void *arg
);
62 void test_circuitpadding_serialize(void *arg
);
63 void test_circuitpadding_rtt(void *arg
);
64 void test_circuitpadding_tokens(void *arg
);
65 void test_circuitpadding_state_length(void *arg
);
68 simulate_single_hop_extend(circuit_t
*client
, circuit_t
*mid_relay
,
70 void free_fake_origin_circuit(origin_circuit_t
*circ
);
72 static int deliver_negotiated
= 1;
73 static int64_t curr_mocked_time
;
75 static node_t padding_node
;
76 static node_t non_padding_node
;
78 static channel_t dummy_channel
;
79 static circpad_machine_spec_t circ_client_machine
;
82 timers_advance_and_run(int64_t msec_update
)
84 curr_mocked_time
+= msec_update
*TOR_NSEC_PER_MSEC
;
85 monotime_coarse_set_mock_time_nsec(curr_mocked_time
);
86 monotime_set_mock_time_nsec(curr_mocked_time
);
93 padding_node
.rs
= tor_malloc_zero(sizeof(routerstatus_t
));
94 padding_node
.rs
->pv
.supports_hs_setup_padding
= 1;
96 non_padding_node
.rs
= tor_malloc_zero(sizeof(routerstatus_t
));
97 non_padding_node
.rs
->pv
.supports_hs_setup_padding
= 0;
103 tor_free(padding_node
.rs
);
105 tor_free(non_padding_node
.rs
);
108 static const node_t
*
109 node_get_by_id_mock(const char *identity_digest
)
111 if (identity_digest
[0] == 1) {
112 return &padding_node
;
113 } else if (identity_digest
[0] == 0) {
114 return &non_padding_node
;
120 static const node_t
*
121 circuit_get_nth_node_mock(origin_circuit_t
*circ
, int hop
)
126 return &padding_node
;
130 free_fake_origin_circuit(origin_circuit_t
*circ
)
132 circpad_circuit_free_all_machineinfos(TO_CIRCUIT(circ
));
133 circuit_clear_cpath(circ
);
137 void dummy_nop_timer(void);
139 //static int dont_stop_libevent = 0;
141 static circuit_t
*client_side
;
142 static circuit_t
*relay_side
;
144 static int n_client_cells
= 0;
145 static int n_relay_cells
= 0;
148 circuit_package_relay_cell_mock(cell_t
*cell
, circuit_t
*circ
,
149 cell_direction_t cell_direction
,
150 crypt_path_t
*layer_hint
, streamid_t on_stream
,
151 const char *filename
, int lineno
);
154 circuitmux_attach_circuit_mock(circuitmux_t
*cmux
, circuit_t
*circ
,
155 cell_direction_t direction
);
158 circuitmux_attach_circuit_mock(circuitmux_t
*cmux
, circuit_t
*circ
,
159 cell_direction_t direction
)
169 circuit_package_relay_cell_mock(cell_t
*cell
, circuit_t
*circ
,
170 cell_direction_t cell_direction
,
171 crypt_path_t
*layer_hint
, streamid_t on_stream
,
172 const char *filename
, int lineno
)
174 (void)cell
; (void)on_stream
; (void)filename
; (void)lineno
;
176 if (circ
== client_side
) {
177 if (cell
->payload
[0] == RELAY_COMMAND_PADDING_NEGOTIATE
) {
179 circpad_handle_padding_negotiate(relay_side
, cell
);
182 int is_target_hop
= circpad_padding_is_from_expected_hop(circ
,
184 tt_int_op(cell_direction
, OP_EQ
, CELL_DIRECTION_OUT
);
185 tt_int_op(is_target_hop
, OP_EQ
, 1);
187 // No need to pretend a padding cell was sent: This event is
188 // now emitted internally when the circuitpadding code sends them.
189 //circpad_cell_event_padding_sent(client_side);
191 // Receive padding cell at middle
192 circpad_deliver_recognized_relay_cell_events(relay_side
,
193 cell
->payload
[0], NULL
);
196 } else if (circ
== relay_side
) {
197 tt_int_op(cell_direction
, OP_EQ
, CELL_DIRECTION_IN
);
199 if (cell
->payload
[0] == RELAY_COMMAND_PADDING_NEGOTIATED
) {
200 // XXX: blah need right layer_hint..
201 if (deliver_negotiated
)
202 circpad_handle_padding_negotiated(client_side
, cell
,
203 TO_ORIGIN_CIRCUIT(client_side
)
205 } else if (cell
->payload
[0] == RELAY_COMMAND_PADDING_NEGOTIATE
) {
206 circpad_handle_padding_negotiate(client_side
, cell
);
208 // No need to pretend a padding cell was sent: This event is
209 // now emitted internally when the circuitpadding code sends them.
210 //circpad_cell_event_padding_sent(relay_side);
212 // Receive padding cell at client
213 circpad_deliver_recognized_relay_cell_events(client_side
,
215 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
);
222 timers_advance_and_run(1);
226 // Test reading and writing padding to strings (or options_t + consensus)
228 test_circuitpadding_serialize(void *arg
)
233 static signed_error_t
234 circpad_send_command_to_hop_mock(origin_circuit_t
*circ
, uint8_t hopnum
,
235 uint8_t relay_command
, const uint8_t *payload
,
240 (void) relay_command
;
247 test_circuitpadding_rtt(void *arg
)
251 * 1. Test RTT measurement server side
252 * a. test usage of measured RTT
253 * 2. Test termination of RTT measurement
254 * a. test non-update of RTT
255 * 3. Test client side circuit and non-application of RTT..
257 circpad_delay_t rtt_estimate
;
258 int64_t actual_mocked_monotime_start
;
261 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
262 MOCK(circpad_send_command_to_hop
, circpad_send_command_to_hop_mock
);
263 testing_enable_reproducible_rng();
265 dummy_channel
.cmux
= circuitmux_alloc();
266 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
267 client_side
= TO_CIRCUIT(origin_circuit_new());
268 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
269 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
272 monotime_enable_test_mocking();
273 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
274 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
275 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
276 curr_mocked_time
= actual_mocked_monotime_start
;
279 circpad_machines_init();
280 helper_create_basic_machine();
282 MOCK(circuit_package_relay_cell
,
283 circuit_package_relay_cell_mock
);
285 client_side
->padding_machine
[0] = &circ_client_machine
;
286 client_side
->padding_info
[0] = circpad_circuit_machineinfo_new(client_side
,
289 relay_side
->padding_machine
[0] = &circ_client_machine
;
290 relay_side
->padding_info
[0] = circpad_circuit_machineinfo_new(client_side
,0);
292 /* Test 1: Test measuring RTT */
293 circpad_cell_event_nonpadding_received(relay_side
);
294 tt_u64_op(relay_side
->padding_info
[0]->last_received_time_usec
, OP_NE
, 0);
296 timers_advance_and_run(20);
298 circpad_cell_event_nonpadding_sent(relay_side
);
299 tt_u64_op(relay_side
->padding_info
[0]->last_received_time_usec
, OP_EQ
, 0);
301 tt_int_op(relay_side
->padding_info
[0]->rtt_estimate_usec
, OP_GE
, 19000);
302 tt_int_op(relay_side
->padding_info
[0]->rtt_estimate_usec
, OP_LE
, 30000);
303 tt_int_op(circpad_histogram_bin_to_usec(relay_side
->padding_info
[0], 0),
305 relay_side
->padding_info
[0]->rtt_estimate_usec
+
306 circpad_machine_current_state(
307 relay_side
->padding_info
[0])->histogram_edges
[0]);
309 circpad_cell_event_nonpadding_received(relay_side
);
310 circpad_cell_event_nonpadding_received(relay_side
);
311 tt_u64_op(relay_side
->padding_info
[0]->last_received_time_usec
, OP_NE
, 0);
312 timers_advance_and_run(20);
313 circpad_cell_event_nonpadding_sent(relay_side
);
314 circpad_cell_event_nonpadding_sent(relay_side
);
315 tt_u64_op(relay_side
->padding_info
[0]->last_received_time_usec
, OP_EQ
, 0);
317 tt_int_op(relay_side
->padding_info
[0]->rtt_estimate_usec
, OP_GE
, 20000);
318 tt_int_op(relay_side
->padding_info
[0]->rtt_estimate_usec
, OP_LE
, 21000);
319 tt_int_op(circpad_histogram_bin_to_usec(relay_side
->padding_info
[0], 0),
321 relay_side
->padding_info
[0]->rtt_estimate_usec
+
322 circpad_machine_current_state(
323 relay_side
->padding_info
[0])->histogram_edges
[0]);
325 /* Test 2: Termination of RTT measurement (from the previous test) */
326 tt_int_op(relay_side
->padding_info
[0]->stop_rtt_update
, OP_EQ
, 1);
327 rtt_estimate
= relay_side
->padding_info
[0]->rtt_estimate_usec
;
329 circpad_cell_event_nonpadding_received(relay_side
);
330 timers_advance_and_run(4);
331 circpad_cell_event_nonpadding_sent(relay_side
);
333 tt_int_op(relay_side
->padding_info
[0]->rtt_estimate_usec
, OP_EQ
,
335 tt_u64_op(relay_side
->padding_info
[0]->last_received_time_usec
, OP_EQ
, 0);
336 tt_int_op(relay_side
->padding_info
[0]->stop_rtt_update
, OP_EQ
, 1);
337 tt_int_op(circpad_histogram_bin_to_usec(relay_side
->padding_info
[0], 0),
339 relay_side
->padding_info
[0]->rtt_estimate_usec
+
340 circpad_machine_current_state(
341 relay_side
->padding_info
[0])->histogram_edges
[0]);
343 /* Test 3: Make sure client side machine properly ignores RTT */
344 circpad_cell_event_nonpadding_received(client_side
);
345 tt_u64_op(client_side
->padding_info
[0]->last_received_time_usec
, OP_EQ
, 0);
347 timers_advance_and_run(20);
348 circpad_cell_event_nonpadding_sent(client_side
);
349 tt_u64_op(client_side
->padding_info
[0]->last_received_time_usec
, OP_EQ
, 0);
351 tt_int_op(client_side
->padding_info
[0]->rtt_estimate_usec
, OP_EQ
, 0);
352 tt_int_op(circpad_histogram_bin_to_usec(client_side
->padding_info
[0], 0),
353 OP_NE
, client_side
->padding_info
[0]->rtt_estimate_usec
);
354 tt_int_op(circpad_histogram_bin_to_usec(client_side
->padding_info
[0], 0),
356 circpad_machine_current_state(
357 client_side
->padding_info
[0])->histogram_edges
[0]);
359 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
360 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
361 circuitmux_free(dummy_channel
.cmux
);
363 monotime_disable_test_mocking();
364 UNMOCK(circuit_package_relay_cell
);
365 UNMOCK(circuitmux_attach_circuit
);
366 tor_free(circ_client_machine
.states
);
367 testing_disable_reproducible_rng();
373 helper_create_basic_machine(void)
376 circpad_machine_states_init(&circ_client_machine
, 2);
378 circ_client_machine
.name
= "basic";
380 circ_client_machine
.states
[CIRCPAD_STATE_START
].
381 next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = CIRCPAD_STATE_BURST
;
382 circ_client_machine
.states
[CIRCPAD_STATE_START
].use_rtt_estimate
= 1;
384 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].
385 next_state
[CIRCPAD_EVENT_PADDING_RECV
] = CIRCPAD_STATE_BURST
;
386 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].
387 next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = CIRCPAD_STATE_BURST
;
389 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].
390 next_state
[CIRCPAD_EVENT_NONPADDING_SENT
] = CIRCPAD_STATE_CANCEL
;
392 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].token_removal
=
393 CIRCPAD_TOKEN_REMOVAL_HIGHER
;
395 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_len
= 5;
397 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 500;
398 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[1] = 2500;
399 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[2] = 5000;
400 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[3] = 10000;
401 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[4] = 20000;
403 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram
[0] = 1;
404 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram
[1] = 0;
405 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram
[2] = 2;
406 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram
[3] = 2;
407 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram
[4] = 2;
409 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_total_tokens
= 7;
410 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].use_rtt_estimate
= 1;
415 #define BIG_HISTOGRAM_LEN 10
417 /** Setup a machine with a big histogram */
419 helper_create_machine_with_big_histogram(circpad_removal_t removal_strategy
)
421 const int tokens_per_bin
= 2;
424 circpad_machine_states_init(&circ_client_machine
, 2);
426 circpad_state_t
*burst_state
=
427 &circ_client_machine
.states
[CIRCPAD_STATE_BURST
];
429 circ_client_machine
.states
[CIRCPAD_STATE_START
].
430 next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = CIRCPAD_STATE_BURST
;
432 burst_state
->next_state
[CIRCPAD_EVENT_PADDING_RECV
] = CIRCPAD_STATE_BURST
;
433 burst_state
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] =CIRCPAD_STATE_BURST
;
435 burst_state
->next_state
[CIRCPAD_EVENT_NONPADDING_SENT
] =CIRCPAD_STATE_CANCEL
;
437 burst_state
->token_removal
= CIRCPAD_TOKEN_REMOVAL_HIGHER
;
439 burst_state
->histogram_len
= BIG_HISTOGRAM_LEN
;
443 for (i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
444 burst_state
->histogram
[i
] = tokens_per_bin
;
445 n_tokens
+= tokens_per_bin
;
448 burst_state
->histogram_edges
[0] = 0;
449 burst_state
->histogram_edges
[1] = 1;
450 burst_state
->histogram_edges
[2] = 7;
451 burst_state
->histogram_edges
[3] = 15;
452 burst_state
->histogram_edges
[4] = 31;
453 burst_state
->histogram_edges
[5] = 62;
454 burst_state
->histogram_edges
[6] = 125;
455 burst_state
->histogram_edges
[7] = 250;
456 burst_state
->histogram_edges
[8] = 500;
457 burst_state
->histogram_edges
[9] = 1000;
459 burst_state
->histogram_total_tokens
= n_tokens
;
460 burst_state
->length_dist
.type
= CIRCPAD_DIST_UNIFORM
;
461 burst_state
->length_dist
.param1
= n_tokens
;
462 burst_state
->length_dist
.param2
= n_tokens
;
463 burst_state
->max_length
= n_tokens
;
464 burst_state
->length_includes_nonpadding
= 1;
465 burst_state
->use_rtt_estimate
= 0;
466 burst_state
->token_removal
= removal_strategy
;
469 static circpad_decision_t
470 circpad_machine_schedule_padding_mock(circpad_machine_runtime_t
*mi
)
477 mock_monotime_absolute_usec(void)
482 /** Test higher token removal strategy by bin */
484 test_circuitpadding_token_removal_higher(void *arg
)
486 circpad_machine_runtime_t
*mi
;
490 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
491 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
492 testing_enable_reproducible_rng();
494 /* Setup test environment (time etc.) */
495 client_side
= TO_CIRCUIT(origin_circuit_new());
496 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
497 monotime_enable_test_mocking();
499 /* Create test machine */
500 helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_HIGHER
);
501 client_side
->padding_machine
[0] = &circ_client_machine
;
502 client_side
->padding_info
[0] =
503 circpad_circuit_machineinfo_new(client_side
, 0);
505 /* move the machine to the right state */
506 circpad_cell_event_nonpadding_received(client_side
);
507 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
508 CIRCPAD_STATE_BURST
);
510 /* Get the machine and setup tokens */
511 mi
= client_side
->padding_info
[0];
514 /*************************************************************************/
516 uint64_t current_time
= monotime_absolute_usec();
518 /* Test left boundaries of each histogram bin: */
519 const circpad_delay_t bin_left_bounds
[] =
520 {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE
};
521 for (int i
= 0; i
<= BIG_HISTOGRAM_LEN
; i
++) {
522 tt_uint_op(bin_left_bounds
[i
], OP_EQ
,
523 circpad_histogram_bin_to_usec(mi
, i
));
526 /* Test right boundaries of each histogram bin: */
527 const circpad_delay_t bin_right_bounds
[] =
528 {0, 6, 14, 30, 61, 124, 249, 499, 999, CIRCPAD_DELAY_INFINITE
-1};
529 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
530 tt_uint_op(bin_right_bounds
[i
], OP_EQ
,
531 histogram_get_bin_upper_bound(mi
, i
));
534 /* Check that all bins have two tokens right now */
535 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
536 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
539 /* This is the right order to remove tokens from this histogram. That is, we
540 * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
541 * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
542 * the same reason, then from the 5th, etc. */
543 const int bin_removal_order
[] = {4, 5, 6, 7, 8};
546 /* Remove all tokens from all bins apart from the infinity bin */
547 for (i
= 0; i
< sizeof(bin_removal_order
)/sizeof(int) ; i
++) {
548 int bin_to_remove
= bin_removal_order
[i
];
549 log_debug(LD_GENERAL
, "Testing that %d attempt removes %d bin",
552 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 2);
554 mi
->padding_scheduled_at_usec
= current_time
- 57;
555 circpad_cell_event_nonpadding_sent(client_side
);
557 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 1);
559 mi
->padding_scheduled_at_usec
= current_time
- 57;
560 circpad_cell_event_nonpadding_sent(client_side
);
562 /* Test that we cleaned out this bin. Don't do this in the case of the last
563 bin since the tokens will get refilled */
564 if (i
!= BIG_HISTOGRAM_LEN
- 2) {
565 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 0);
569 /* Check that all lower bins are not touched */
570 for (i
=0; i
< 4 ; i
++) {
571 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
574 /* Test below the lowest bin, for coverage */
575 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
576 CIRCPAD_STATE_BURST
);
577 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 100;
578 mi
->padding_scheduled_at_usec
= current_time
;
579 circpad_cell_event_nonpadding_sent(client_side
);
580 tt_int_op(mi
->histogram
[0], OP_EQ
, 1);
583 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
584 monotime_disable_test_mocking();
585 tor_free(circ_client_machine
.states
);
586 testing_disable_reproducible_rng();
589 /** Test lower token removal strategy by bin */
591 test_circuitpadding_token_removal_lower(void *arg
)
593 circpad_machine_runtime_t
*mi
;
597 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
598 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
599 testing_enable_reproducible_rng();
601 /* Setup test environment (time etc.) */
602 client_side
= TO_CIRCUIT(origin_circuit_new());
603 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
604 monotime_enable_test_mocking();
606 /* Create test machine */
607 helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_LOWER
);
608 client_side
->padding_machine
[0] = &circ_client_machine
;
609 client_side
->padding_info
[0] =
610 circpad_circuit_machineinfo_new(client_side
, 0);
612 /* move the machine to the right state */
613 circpad_cell_event_nonpadding_received(client_side
);
614 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
615 CIRCPAD_STATE_BURST
);
617 /* Get the machine and setup tokens */
618 mi
= client_side
->padding_info
[0];
621 /*************************************************************************/
623 uint64_t current_time
= monotime_absolute_usec();
625 /* Test left boundaries of each histogram bin: */
626 const circpad_delay_t bin_left_bounds
[] =
627 {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE
};
628 for (int i
= 0; i
<= BIG_HISTOGRAM_LEN
; i
++) {
629 tt_uint_op(bin_left_bounds
[i
], OP_EQ
,
630 circpad_histogram_bin_to_usec(mi
, i
));
633 /* Check that all bins have two tokens right now */
634 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
635 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
638 /* This is the right order to remove tokens from this histogram. That is, we
639 * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
640 * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
641 * the same reason, then from the 5th, etc. */
642 const int bin_removal_order
[] = {4, 3, 2, 1, 0};
645 /* Remove all tokens from all bins apart from the infinity bin */
646 for (i
= 0; i
< sizeof(bin_removal_order
)/sizeof(int) ; i
++) {
647 int bin_to_remove
= bin_removal_order
[i
];
648 log_debug(LD_GENERAL
, "Testing that %d attempt removes %d bin",
651 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 2);
653 mi
->padding_scheduled_at_usec
= current_time
- 57;
654 circpad_cell_event_nonpadding_sent(client_side
);
656 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 1);
658 mi
->padding_scheduled_at_usec
= current_time
- 57;
659 circpad_cell_event_nonpadding_sent(client_side
);
661 /* Test that we cleaned out this bin. Don't do this in the case of the last
662 bin since the tokens will get refilled */
663 if (i
!= BIG_HISTOGRAM_LEN
- 2) {
664 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 0);
668 /* Check that all higher bins are untouched */
669 for (i
= 5; i
< BIG_HISTOGRAM_LEN
; i
++) {
670 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
673 /* Test above the highest bin, for coverage */
674 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
675 CIRCPAD_STATE_BURST
);
676 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].
677 histogram_edges
[BIG_HISTOGRAM_LEN
-2] = 100;
678 mi
->padding_scheduled_at_usec
= current_time
- 29202;
679 circpad_cell_event_nonpadding_sent(client_side
);
680 tt_int_op(mi
->histogram
[BIG_HISTOGRAM_LEN
-2], OP_EQ
, 1);
683 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
684 monotime_disable_test_mocking();
685 tor_free(circ_client_machine
.states
);
686 testing_disable_reproducible_rng();
689 /** Test closest token removal strategy by bin */
691 test_circuitpadding_closest_token_removal(void *arg
)
693 circpad_machine_runtime_t
*mi
;
697 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
698 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
699 testing_enable_reproducible_rng();
701 /* Setup test environment (time etc.) */
702 client_side
= TO_CIRCUIT(origin_circuit_new());
703 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
704 monotime_enable_test_mocking();
706 /* Create test machine */
707 helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_CLOSEST
);
708 client_side
->padding_machine
[0] = &circ_client_machine
;
709 client_side
->padding_info
[0] =
710 circpad_circuit_machineinfo_new(client_side
, 0);
712 /* move the machine to the right state */
713 circpad_cell_event_nonpadding_received(client_side
);
714 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
715 CIRCPAD_STATE_BURST
);
717 /* Get the machine and setup tokens */
718 mi
= client_side
->padding_info
[0];
721 /*************************************************************************/
723 uint64_t current_time
= monotime_absolute_usec();
725 /* Test left boundaries of each histogram bin: */
726 const circpad_delay_t bin_left_bounds
[] =
727 {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE
};
728 for (int i
= 0; i
<= BIG_HISTOGRAM_LEN
; i
++) {
729 tt_uint_op(bin_left_bounds
[i
], OP_EQ
,
730 circpad_histogram_bin_to_usec(mi
, i
));
733 /* Check that all bins have two tokens right now */
734 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
735 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
738 /* This is the right order to remove tokens from this histogram. That is, we
739 * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
740 * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
741 * the same reason, then from the 5th, etc. */
742 const int bin_removal_order
[] = {4, 3, 5, 2, 6, 1, 7, 0, 8, 9};
744 /* Remove all tokens from all bins apart from the infinity bin */
745 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
-1 ; i
++) {
746 int bin_to_remove
= bin_removal_order
[i
];
747 log_debug(LD_GENERAL
, "Testing that %d attempt removes %d bin",
750 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 2);
752 mi
->padding_scheduled_at_usec
= current_time
- 57;
753 circpad_cell_event_nonpadding_sent(client_side
);
755 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 1);
757 mi
->padding_scheduled_at_usec
= current_time
- 57;
758 circpad_cell_event_nonpadding_sent(client_side
);
760 /* Test that we cleaned out this bin. Don't do this in the case of the last
761 bin since the tokens will get refilled */
762 if (i
!= BIG_HISTOGRAM_LEN
- 2) {
763 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 0);
767 /* Check that all bins have been refilled */
768 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
769 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
772 /* Test below the lowest bin, for coverage */
773 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
774 CIRCPAD_STATE_BURST
);
775 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 100;
776 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[1] = 101;
777 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[2] = 120;
778 mi
->padding_scheduled_at_usec
= current_time
- 102;
779 mi
->histogram
[0] = 0;
780 circpad_cell_event_nonpadding_sent(client_side
);
781 tt_int_op(mi
->histogram
[1], OP_EQ
, 1);
783 /* Test above the highest bin, for coverage */
784 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
785 CIRCPAD_STATE_BURST
);
786 mi
->padding_scheduled_at_usec
= current_time
- 29202;
787 circpad_cell_event_nonpadding_sent(client_side
);
788 tt_int_op(mi
->histogram
[BIG_HISTOGRAM_LEN
-2], OP_EQ
, 1);
791 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
792 monotime_disable_test_mocking();
793 tor_free(circ_client_machine
.states
);
794 testing_disable_reproducible_rng();
797 /** Test closest token removal strategy with usec */
799 test_circuitpadding_closest_token_removal_usec(void *arg
)
801 circpad_machine_runtime_t
*mi
;
805 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
806 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
807 testing_enable_reproducible_rng();
809 /* Setup test environment (time etc.) */
810 client_side
= TO_CIRCUIT(origin_circuit_new());
811 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
812 monotime_enable_test_mocking();
814 /* Create test machine */
815 helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_CLOSEST_USEC
);
816 client_side
->padding_machine
[0] = &circ_client_machine
;
817 client_side
->padding_info
[0] =
818 circpad_circuit_machineinfo_new(client_side
, 0);
820 /* move the machine to the right state */
821 circpad_cell_event_nonpadding_received(client_side
);
822 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
823 CIRCPAD_STATE_BURST
);
825 /* Get the machine and setup tokens */
826 mi
= client_side
->padding_info
[0];
829 /*************************************************************************/
831 uint64_t current_time
= monotime_absolute_usec();
833 /* Test left boundaries of each histogram bin: */
834 const circpad_delay_t bin_left_bounds
[] =
835 {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE
};
836 for (int i
= 0; i
<= BIG_HISTOGRAM_LEN
; i
++) {
837 tt_uint_op(bin_left_bounds
[i
], OP_EQ
,
838 circpad_histogram_bin_to_usec(mi
, i
));
841 /* XXX we want to test remove_token_exact and
842 circpad_machine_remove_closest_token() with usec */
844 /* Check that all bins have two tokens right now */
845 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
846 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
849 /* This is the right order to remove tokens from this histogram. That is, we
850 * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
851 * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
852 * the same reason, then from the 5th, etc. */
853 const int bin_removal_order
[] = {4, 3, 5, 2, 1, 0, 6, 7, 8, 9};
855 /* Remove all tokens from all bins apart from the infinity bin */
856 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
-1 ; i
++) {
857 int bin_to_remove
= bin_removal_order
[i
];
858 log_debug(LD_GENERAL
, "Testing that %d attempt removes %d bin",
861 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 2);
863 mi
->padding_scheduled_at_usec
= current_time
- 57;
864 circpad_cell_event_nonpadding_sent(client_side
);
866 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 1);
868 mi
->padding_scheduled_at_usec
= current_time
- 57;
869 circpad_cell_event_nonpadding_sent(client_side
);
871 /* Test that we cleaned out this bin. Don't do this in the case of the last
872 bin since the tokens will get refilled */
873 if (i
!= BIG_HISTOGRAM_LEN
- 2) {
874 tt_int_op(mi
->histogram
[bin_to_remove
], OP_EQ
, 0);
878 /* Check that all bins have been refilled */
879 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
880 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
883 /* Test below the lowest bin, for coverage */
884 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
885 CIRCPAD_STATE_BURST
);
886 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 100;
887 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[1] = 101;
888 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].histogram_edges
[2] = 120;
889 mi
->padding_scheduled_at_usec
= current_time
- 102;
890 mi
->histogram
[0] = 0;
891 circpad_cell_event_nonpadding_sent(client_side
);
892 tt_int_op(mi
->histogram
[1], OP_EQ
, 1);
894 /* Test above the highest bin, for coverage */
895 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
896 CIRCPAD_STATE_BURST
);
897 circ_client_machine
.states
[CIRCPAD_STATE_BURST
].
898 histogram_edges
[BIG_HISTOGRAM_LEN
-2] = 100;
899 mi
->padding_scheduled_at_usec
= current_time
- 29202;
900 circpad_cell_event_nonpadding_sent(client_side
);
901 tt_int_op(mi
->histogram
[BIG_HISTOGRAM_LEN
-2], OP_EQ
, 1);
904 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
905 monotime_disable_test_mocking();
906 tor_free(circ_client_machine
.states
);
907 testing_disable_reproducible_rng();
910 /** Test closest token removal strategy with usec */
912 test_circuitpadding_token_removal_exact(void *arg
)
914 circpad_machine_runtime_t
*mi
;
918 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
919 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
920 testing_enable_reproducible_rng();
922 /* Setup test environment (time etc.) */
923 client_side
= TO_CIRCUIT(origin_circuit_new());
924 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
925 monotime_enable_test_mocking();
927 /* Create test machine */
928 helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_EXACT
);
929 client_side
->padding_machine
[0] = &circ_client_machine
;
930 client_side
->padding_info
[0] =
931 circpad_circuit_machineinfo_new(client_side
, 0);
933 /* move the machine to the right state */
934 circpad_cell_event_nonpadding_received(client_side
);
935 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
936 CIRCPAD_STATE_BURST
);
938 /* Get the machine and setup tokens */
939 mi
= client_side
->padding_info
[0];
942 /**********************************************************************/
943 uint64_t current_time
= monotime_absolute_usec();
945 /* Ensure that we will clear out bin #4 with this usec */
946 mi
->padding_scheduled_at_usec
= current_time
- 57;
947 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
948 circpad_cell_event_nonpadding_sent(client_side
);
949 mi
->padding_scheduled_at_usec
= current_time
- 57;
950 tt_int_op(mi
->histogram
[4], OP_EQ
, 1);
951 circpad_cell_event_nonpadding_sent(client_side
);
952 tt_int_op(mi
->histogram
[4], OP_EQ
, 0);
954 /* Ensure that we will not remove any other tokens even tho we try to, since
955 * this is what the exact strategy dictates */
956 mi
->padding_scheduled_at_usec
= current_time
- 57;
957 circpad_cell_event_nonpadding_sent(client_side
);
958 for (int i
= 0; i
< BIG_HISTOGRAM_LEN
; i
++) {
960 tt_int_op(mi
->histogram
[i
], OP_EQ
, 2);
965 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
966 monotime_disable_test_mocking();
967 tor_free(circ_client_machine
.states
);
968 testing_disable_reproducible_rng();
971 #undef BIG_HISTOGRAM_LEN
974 test_circuitpadding_tokens(void *arg
)
976 const circpad_state_t
*state
;
977 circpad_machine_runtime_t
*mi
;
978 int64_t actual_mocked_monotime_start
;
981 testing_enable_reproducible_rng();
985 * 1. Test symmetry between bin_to_usec and usec_to_bin
987 * b. Test edge transitions (lower, upper)
988 * 2. Test remove higher on an empty bin
993 * 3. Test remove lower
997 * 4. Test remove closest
1001 * d. Closest Infinity
1003 client_side
= TO_CIRCUIT(origin_circuit_new());
1004 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1007 monotime_enable_test_mocking();
1008 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
1009 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
1010 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
1011 curr_mocked_time
= actual_mocked_monotime_start
;
1013 /* This is needed so that we are not considered to be dormant */
1014 note_user_activity(20);
1016 timers_initialize();
1018 helper_create_basic_machine();
1019 client_side
->padding_machine
[0] = &circ_client_machine
;
1020 client_side
->padding_info
[0] = circpad_circuit_machineinfo_new(client_side
,
1023 mi
= client_side
->padding_info
[0];
1025 // Pretend a non-padding cell was sent
1026 circpad_cell_event_nonpadding_received(client_side
);
1027 circpad_cell_event_nonpadding_sent(client_side
);
1028 /* We have to save the infinity bin because one inf delay
1029 * could have been chosen when we transition to burst */
1030 circpad_hist_token_t inf_bin
= mi
->histogram
[4];
1032 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
1033 CIRCPAD_STATE_BURST
);
1035 state
= circpad_machine_current_state(client_side
->padding_info
[0]);
1037 // Test 0: convert bin->usec->bin
1038 // Bin 0+1 have different semantics
1039 for (int bin
= 0; bin
< 2; bin
++) {
1040 circpad_delay_t usec
=
1041 circpad_histogram_bin_to_usec(client_side
->padding_info
[0], bin
);
1042 int bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1044 tt_int_op(bin
, OP_EQ
, bin2
);
1046 for (int bin
= 2; bin
< state
->histogram_len
-1; bin
++) {
1047 circpad_delay_t usec
=
1048 circpad_histogram_bin_to_usec(client_side
->padding_info
[0], bin
);
1049 int bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1051 tt_int_op(bin
, OP_EQ
, bin2
);
1052 /* Verify we round down */
1053 bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1055 tt_int_op(bin
, OP_EQ
, bin2
);
1057 bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1059 tt_int_op(bin
, OP_EQ
, bin2
+1);
1062 // Test 1: converting usec->bin->usec->bin
1063 // Bin 0+1 have different semantics.
1064 for (circpad_delay_t i
= 0; i
<= state
->histogram_edges
[0]; i
++) {
1065 int bin
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1067 circpad_delay_t usec
=
1068 circpad_histogram_bin_to_usec(client_side
->padding_info
[0], bin
);
1069 int bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1071 tt_int_op(bin
, OP_EQ
, bin2
);
1072 tt_int_op(i
, OP_LE
, usec
);
1074 for (circpad_delay_t i
= state
->histogram_edges
[0]+1;
1075 i
<= state
->histogram_edges
[0] +
1076 state
->histogram_edges
[state
->histogram_len
-2]; i
++) {
1077 int bin
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1079 circpad_delay_t usec
=
1080 circpad_histogram_bin_to_usec(client_side
->padding_info
[0], bin
);
1081 int bin2
= circpad_histogram_usec_to_bin(client_side
->padding_info
[0],
1083 tt_int_op(bin
, OP_EQ
, bin2
);
1084 tt_int_op(i
, OP_GE
, usec
);
1087 /* 2.a. Normal higher bin */
1089 tt_int_op(mi
->histogram
[2], OP_EQ
, 2);
1090 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1091 circpad_machine_remove_higher_token(mi
,
1092 circpad_histogram_bin_to_usec(mi
, 2)+1);
1093 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1094 tt_int_op(mi
->histogram
[2], OP_EQ
, 1);
1096 circpad_machine_remove_higher_token(mi
,
1097 circpad_histogram_bin_to_usec(mi
, 2)+1);
1098 tt_int_op(mi
->histogram
[2], OP_EQ
, 0);
1100 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1101 circpad_machine_remove_higher_token(mi
,
1102 circpad_histogram_bin_to_usec(mi
, 2)+1);
1103 circpad_machine_remove_higher_token(mi
,
1104 circpad_histogram_bin_to_usec(mi
, 2)+1);
1105 tt_int_op(mi
->histogram
[3], OP_EQ
, 0);
1106 circpad_machine_remove_higher_token(mi
,
1107 circpad_histogram_bin_to_usec(mi
, 2)+1);
1108 tt_int_op(mi
->histogram
[3], OP_EQ
, 0);
1111 /* 2.b. Higher Infinity bin */
1113 tt_int_op(mi
->histogram
[4], OP_EQ
, inf_bin
);
1114 circpad_machine_remove_higher_token(mi
,
1115 circpad_histogram_bin_to_usec(mi
, 2)+1);
1116 tt_int_op(mi
->histogram
[4], OP_EQ
, inf_bin
);
1118 /* Test past the infinity bin */
1119 circpad_machine_remove_higher_token(mi
,
1120 circpad_histogram_bin_to_usec(mi
, 5)+1000000);
1122 tt_int_op(mi
->histogram
[4], OP_EQ
, inf_bin
);
1127 tt_int_op(mi
->histogram
[0], OP_EQ
, 0);
1128 mi
->histogram
[0] = 1;
1129 circpad_machine_remove_higher_token(mi
, state
->histogram_edges
[0]/2);
1130 tt_int_op(mi
->histogram
[0], OP_EQ
, 0);
1133 /* Drain the infinity bin and cause a refill */
1134 while (inf_bin
!= 0) {
1135 tt_int_op(mi
->histogram
[4], OP_EQ
, inf_bin
);
1136 circpad_cell_event_nonpadding_received(client_side
);
1140 circpad_cell_event_nonpadding_sent(client_side
);
1142 // We should have refilled here.
1143 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
1147 tt_int_op(mi
->histogram
[0], OP_EQ
, 1);
1148 circpad_machine_remove_higher_token(mi
, state
->histogram_edges
[0]/2);
1149 tt_int_op(mi
->histogram
[0], OP_EQ
, 0);
1152 /* 3.b. Test remove lower normal bin */
1154 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1155 circpad_machine_remove_lower_token(mi
,
1156 circpad_histogram_bin_to_usec(mi
, 3)+1);
1157 circpad_machine_remove_lower_token(mi
,
1158 circpad_histogram_bin_to_usec(mi
, 3)+1);
1159 tt_int_op(mi
->histogram
[3], OP_EQ
, 0);
1160 tt_int_op(mi
->histogram
[2], OP_EQ
, 2);
1161 circpad_machine_remove_lower_token(mi
,
1162 circpad_histogram_bin_to_usec(mi
, 3)+1);
1163 circpad_machine_remove_lower_token(mi
,
1164 circpad_histogram_bin_to_usec(mi
, 3)+1);
1166 circpad_machine_remove_lower_token(mi
,
1167 circpad_histogram_bin_to_usec(mi
, 3)+1);
1168 tt_int_op(mi
->histogram
[2], OP_EQ
, 0);
1171 /* 4. Test remove closest
1175 * d. Closest Infinity
1177 circpad_machine_setup_tokens(mi
);
1178 tt_int_op(mi
->histogram
[2], OP_EQ
, 2);
1179 circpad_machine_remove_closest_token(mi
,
1180 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1181 circpad_machine_remove_closest_token(mi
,
1182 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1183 tt_int_op(mi
->histogram
[2], OP_EQ
, 0);
1184 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1185 circpad_machine_remove_closest_token(mi
,
1186 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1187 circpad_machine_remove_closest_token(mi
,
1188 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1189 tt_int_op(mi
->histogram
[3], OP_EQ
, 0);
1190 tt_int_op(mi
->histogram
[0], OP_EQ
, 1);
1191 circpad_machine_remove_closest_token(mi
,
1192 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1193 tt_int_op(mi
->histogram
[0], OP_EQ
, 0);
1194 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
1195 circpad_machine_remove_closest_token(mi
,
1196 circpad_histogram_bin_to_usec(mi
, 2)+1, 0);
1197 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
1199 /* 5. Test remove closest usec
1201 * b. Closest lower (below midpoint)
1202 * c. Closest higher (above midpoint)
1203 * d. Closest Infinity
1205 circpad_machine_setup_tokens(mi
);
1207 tt_int_op(mi
->histogram
[0], OP_EQ
, 1);
1208 circpad_machine_remove_closest_token(mi
,
1209 circpad_histogram_bin_to_usec(mi
, 0)/3, 1);
1210 tt_int_op(mi
->histogram
[0], OP_EQ
, 0);
1211 tt_int_op(mi
->histogram
[2], OP_EQ
, 2);
1212 circpad_machine_remove_closest_token(mi
,
1213 circpad_histogram_bin_to_usec(mi
, 0)/3, 1);
1214 circpad_machine_remove_closest_token(mi
,
1215 circpad_histogram_bin_to_usec(mi
, 0)/3, 1);
1216 tt_int_op(mi
->histogram
[2], OP_EQ
, 0);
1217 tt_int_op(mi
->histogram
[3], OP_EQ
, 2);
1218 circpad_machine_remove_closest_token(mi
,
1219 circpad_histogram_bin_to_usec(mi
, 4), 1);
1220 circpad_machine_remove_closest_token(mi
,
1221 circpad_histogram_bin_to_usec(mi
, 4), 1);
1222 tt_int_op(mi
->histogram
[3], OP_EQ
, 0);
1223 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
1224 circpad_machine_remove_closest_token(mi
,
1225 circpad_histogram_bin_to_usec(mi
, 4), 1);
1226 circpad_machine_remove_closest_token(mi
,
1227 circpad_histogram_bin_to_usec(mi
, 4), 1);
1228 tt_int_op(mi
->histogram
[4], OP_EQ
, 2);
1230 // XXX: Need more coverage of the actual usec branches
1233 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1234 monotime_disable_test_mocking();
1235 tor_free(circ_client_machine
.states
);
1236 testing_disable_reproducible_rng();
1240 test_circuitpadding_wronghop(void *arg
)
1244 * 1. Padding sent from hop 1 and 3 to client
1245 * 2. Send negotiated from hop 1 and 3 to client
1246 * 3. Garbled negotiated cell
1247 * 4. Padding negotiate sent to client
1248 * 5. Send negotiate stop command for unknown machine
1249 * 6. Send negotiated to relay
1250 * 7. Garbled padding negotiate cell
1253 uint32_t read_bw
= 0, overhead_bw
= 0;
1256 origin_circuit_t
*orig_client
;
1257 int64_t actual_mocked_monotime_start
;
1259 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
1261 /* Mock this function so that our cell counting tests don't get confused by
1262 * padding that gets sent by scheduled timers. */
1263 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
1264 testing_enable_reproducible_rng();
1266 client_side
= TO_CIRCUIT(origin_circuit_new());
1267 dummy_channel
.cmux
= circuitmux_alloc();
1268 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
,
1270 orig_client
= TO_ORIGIN_CIRCUIT(client_side
);
1272 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1273 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1277 monotime_enable_test_mocking();
1278 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
1279 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
1280 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
1281 curr_mocked_time
= actual_mocked_monotime_start
;
1283 timers_initialize();
1284 circpad_machines_init();
1286 MOCK(node_get_by_id
,
1287 node_get_by_id_mock
);
1289 MOCK(circuit_package_relay_cell
,
1290 circuit_package_relay_cell_mock
);
1292 /* Build three hops */
1293 simulate_single_hop_extend(client_side
, relay_side
, 1);
1294 simulate_single_hop_extend(client_side
, relay_side
, 1);
1295 simulate_single_hop_extend(client_side
, relay_side
, 1);
1297 /* verify padding was negotiated */
1298 tt_ptr_op(relay_side
->padding_machine
[0], OP_NE
, NULL
);
1299 tt_ptr_op(relay_side
->padding_info
[0], OP_NE
, NULL
);
1301 /* verify echo was sent */
1302 tt_int_op(n_relay_cells
, OP_EQ
, 1);
1303 tt_int_op(n_client_cells
, OP_EQ
, 1);
1305 read_bw
= orig_client
->n_delivered_read_circ_bw
;
1306 overhead_bw
= orig_client
->n_overhead_read_circ_bw
;
1308 /* 1. Test padding from first and third hop */
1309 circpad_deliver_recognized_relay_cell_events(client_side
,
1311 TO_ORIGIN_CIRCUIT(client_side
)->cpath
);
1312 tt_int_op(read_bw
, OP_EQ
,
1313 orig_client
->n_delivered_read_circ_bw
);
1314 tt_int_op(overhead_bw
, OP_EQ
,
1315 orig_client
->n_overhead_read_circ_bw
);
1317 circpad_deliver_recognized_relay_cell_events(client_side
,
1319 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
->next
);
1320 tt_int_op(read_bw
, OP_EQ
,
1321 orig_client
->n_delivered_read_circ_bw
);
1322 tt_int_op(overhead_bw
, OP_EQ
,
1323 orig_client
->n_overhead_read_circ_bw
);
1325 circpad_deliver_recognized_relay_cell_events(client_side
,
1327 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
);
1328 tt_int_op(read_bw
, OP_EQ
,
1329 orig_client
->n_delivered_read_circ_bw
);
1330 tt_int_op(overhead_bw
, OP_LT
,
1331 orig_client
->n_overhead_read_circ_bw
);
1333 /* 2. Test padding negotiated not handled from hops 1,3 */
1334 ret
= circpad_handle_padding_negotiated(client_side
, &cell
,
1335 TO_ORIGIN_CIRCUIT(client_side
)->cpath
);
1336 tt_int_op(ret
, OP_EQ
, -1);
1338 ret
= circpad_handle_padding_negotiated(client_side
, &cell
,
1339 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
->next
);
1340 tt_int_op(ret
, OP_EQ
, -1);
1342 /* 3. Garbled negotiated cell */
1343 memset(&cell
, 255, sizeof(cell
));
1344 ret
= circpad_handle_padding_negotiated(client_side
, &cell
,
1345 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
);
1346 tt_int_op(ret
, OP_EQ
, -1);
1348 /* 4. Test that negotiate is dropped at origin */
1349 read_bw
= orig_client
->n_delivered_read_circ_bw
;
1350 overhead_bw
= orig_client
->n_overhead_read_circ_bw
;
1351 relay_send_command_from_edge(0, relay_side
,
1352 RELAY_COMMAND_PADDING_NEGOTIATE
,
1353 (void*)cell
.payload
,
1355 tt_int_op(read_bw
, OP_EQ
,
1356 orig_client
->n_delivered_read_circ_bw
);
1357 tt_int_op(overhead_bw
, OP_EQ
,
1358 orig_client
->n_overhead_read_circ_bw
);
1360 tt_int_op(n_relay_cells
, OP_EQ
, 2);
1361 tt_int_op(n_client_cells
, OP_EQ
, 1);
1363 /* 5. Test that asking to stop the wrong machine does nothing */
1364 circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side
),
1365 255, 2, CIRCPAD_COMMAND_STOP
, 0);
1366 tt_ptr_op(client_side
->padding_machine
[0], OP_NE
, NULL
);
1367 tt_ptr_op(client_side
->padding_info
[0], OP_NE
, NULL
);
1368 tt_ptr_op(relay_side
->padding_machine
[0], OP_NE
, NULL
);
1369 tt_ptr_op(relay_side
->padding_info
[0], OP_NE
, NULL
);
1370 tt_int_op(n_relay_cells
, OP_EQ
, 2);
1371 tt_int_op(n_client_cells
, OP_EQ
, 2);
1373 /* 6. Sending negotiated command to relay does nothing */
1374 ret
= circpad_handle_padding_negotiated(relay_side
, &cell
, NULL
);
1375 tt_int_op(ret
, OP_EQ
, -1);
1377 /* 7. Test garbled negotiated cell (bad command 255) */
1378 memset(&cell
, 0, sizeof(cell
));
1379 ret
= circpad_handle_padding_negotiate(relay_side
, &cell
);
1380 tt_int_op(ret
, OP_EQ
, -1);
1381 tt_int_op(n_client_cells
, OP_EQ
, 2);
1383 /* Test 2: Test no padding */
1384 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1385 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1387 client_side
= TO_CIRCUIT(origin_circuit_new());
1388 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
,
1390 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1391 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1393 simulate_single_hop_extend(client_side
, relay_side
, 1);
1394 simulate_single_hop_extend(client_side
, relay_side
, 0);
1396 /* verify no padding was negotiated */
1397 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1398 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1400 /* verify no echo was sent */
1401 tt_int_op(n_relay_cells
, OP_EQ
, 2);
1402 tt_int_op(n_client_cells
, OP_EQ
, 2);
1404 /* Finish circuit */
1405 simulate_single_hop_extend(client_side
, relay_side
, 1);
1407 /* Spoof padding negotiated on circuit with no padding */
1408 circpad_padding_negotiated(relay_side
,
1409 CIRCPAD_MACHINE_CIRC_SETUP
,
1410 CIRCPAD_COMMAND_START
,
1411 CIRCPAD_RESPONSE_OK
, 0);
1413 /* verify no padding was negotiated */
1414 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1415 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1417 circpad_padding_negotiated(relay_side
,
1418 CIRCPAD_MACHINE_CIRC_SETUP
,
1419 CIRCPAD_COMMAND_START
,
1420 CIRCPAD_RESPONSE_ERR
, 0);
1422 /* verify no padding was negotiated */
1423 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1424 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1427 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1428 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1429 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
1430 circuitmux_free(dummy_channel
.cmux
);
1431 monotime_disable_test_mocking();
1432 UNMOCK(node_get_by_id
);
1433 UNMOCK(circuit_package_relay_cell
);
1434 UNMOCK(circuitmux_attach_circuit
);
1436 testing_disable_reproducible_rng();
1440 test_circuitpadding_negotiation(void *arg
)
1444 * 1. Test circuit where padding is supported by middle
1445 * a. Make sure padding negotiation is sent
1446 * b. Test padding negotiation delivery and parsing
1447 * 2. Test circuit where padding is unsupported by middle
1448 * a. Make sure padding negotiation is not sent
1449 * 3. Test failure to negotiate a machine due to desync.
1451 int64_t actual_mocked_monotime_start
;
1454 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
1456 client_side
= TO_CIRCUIT(origin_circuit_new());
1457 dummy_channel
.cmux
= circuitmux_alloc();
1458 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
1460 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1461 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1465 monotime_enable_test_mocking();
1466 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
1467 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
1468 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
1469 curr_mocked_time
= actual_mocked_monotime_start
;
1471 timers_initialize();
1472 circpad_machines_init();
1474 MOCK(node_get_by_id
,
1475 node_get_by_id_mock
);
1477 MOCK(circuit_package_relay_cell
,
1478 circuit_package_relay_cell_mock
);
1480 /* Build two hops */
1481 simulate_single_hop_extend(client_side
, relay_side
, 1);
1482 simulate_single_hop_extend(client_side
, relay_side
, 1);
1484 /* verify padding was negotiated */
1485 tt_ptr_op(relay_side
->padding_machine
[0], OP_NE
, NULL
);
1486 tt_ptr_op(relay_side
->padding_info
[0], OP_NE
, NULL
);
1488 /* verify echo was sent */
1489 tt_int_op(n_relay_cells
, OP_EQ
, 1);
1490 tt_int_op(n_client_cells
, OP_EQ
, 1);
1492 /* Finish circuit */
1493 simulate_single_hop_extend(client_side
, relay_side
, 1);
1495 /* Test 2: Test no padding */
1496 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1497 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1499 client_side
= TO_CIRCUIT(origin_circuit_new());
1500 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
1501 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1502 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1504 simulate_single_hop_extend(client_side
, relay_side
, 1);
1505 simulate_single_hop_extend(client_side
, relay_side
, 0);
1507 /* verify no padding was negotiated */
1508 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1509 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1510 tt_int_op(n_relay_cells
, OP_EQ
, 1);
1511 tt_int_op(n_client_cells
, OP_EQ
, 1);
1513 /* verify no echo was sent */
1514 tt_int_op(n_relay_cells
, OP_EQ
, 1);
1515 tt_int_op(n_client_cells
, OP_EQ
, 1);
1517 /* Finish circuit */
1518 simulate_single_hop_extend(client_side
, relay_side
, 1);
1520 /* Force negotiate padding. */
1521 circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side
),
1522 CIRCPAD_MACHINE_CIRC_SETUP
,
1523 2, CIRCPAD_COMMAND_START
, 0);
1525 /* verify no padding was negotiated */
1526 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1527 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1529 /* verify no echo was sent */
1530 tt_int_op(n_relay_cells
, OP_EQ
, 1);
1531 tt_int_op(n_client_cells
, OP_EQ
, 1);
1533 /* 3. Test failure to negotiate a machine due to desync */
1534 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1535 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1537 client_side
= TO_CIRCUIT(origin_circuit_new());
1538 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
1539 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1540 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1542 SMARTLIST_FOREACH(relay_padding_machines
,
1543 circpad_machine_spec_t
*,
1544 m
, tor_free(m
->states
); tor_free(m
));
1545 smartlist_free(relay_padding_machines
);
1546 relay_padding_machines
= smartlist_new();
1548 simulate_single_hop_extend(client_side
, relay_side
, 1);
1549 simulate_single_hop_extend(client_side
, relay_side
, 1);
1551 /* verify echo was sent */
1552 tt_int_op(n_client_cells
, OP_EQ
, 2);
1553 tt_int_op(n_relay_cells
, OP_EQ
, 2);
1555 /* verify no padding was negotiated */
1556 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
1557 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1558 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1559 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
1562 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1563 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1564 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
1565 circuitmux_free(dummy_channel
.cmux
);
1566 monotime_disable_test_mocking();
1567 UNMOCK(node_get_by_id
);
1568 UNMOCK(circuit_package_relay_cell
);
1569 UNMOCK(circuitmux_attach_circuit
);
1574 simulate_single_hop_extend(circuit_t
*client
, circuit_t
*mid_relay
,
1577 char whatevs_key
[CPATH_KEY_MATERIAL_LEN
];
1578 char digest
[DIGEST_LEN
];
1581 // Pretend a non-padding cell was sent
1582 circpad_cell_event_nonpadding_sent(client
);
1584 // Receive extend cell at middle
1585 circpad_cell_event_nonpadding_received(mid_relay
);
1587 // Advance time a tiny bit so we can calculate an RTT
1588 curr_mocked_time
+= 10 * TOR_NSEC_PER_MSEC
;
1589 monotime_coarse_set_mock_time_nsec(curr_mocked_time
);
1590 monotime_set_mock_time_nsec(curr_mocked_time
);
1592 // Receive extended cell at middle
1593 circpad_cell_event_nonpadding_sent(mid_relay
);
1595 // Receive extended cell at first hop
1596 circpad_cell_event_nonpadding_received(client
);
1598 // Add a hop to cpath
1599 crypt_path_t
*hop
= tor_malloc_zero(sizeof(crypt_path_t
));
1600 cpath_extend_linked_list(&TO_ORIGIN_CIRCUIT(client
)->cpath
, hop
);
1602 hop
->magic
= CRYPT_PATH_MAGIC
;
1603 hop
->state
= CPATH_STATE_OPEN
;
1605 // add an extend info to indicate if this node supports padding or not.
1606 // (set the first byte of the digest for our mocked node_get_by_id)
1607 digest
[0] = padding
;
1609 hop
->extend_info
= extend_info_new(
1610 padding
? "padding" : "non-padding",
1611 digest
, NULL
, NULL
, NULL
,
1614 cpath_init_circuit_crypto(hop
, whatevs_key
, sizeof(whatevs_key
), 0, 0);
1616 hop
->package_window
= circuit_initial_package_window();
1617 hop
->deliver_window
= CIRCWINDOW_START
;
1619 // Signal that the hop was added
1620 circpad_machine_event_circ_added_hop(TO_ORIGIN_CIRCUIT(client
));
1623 static circpad_machine_spec_t
*
1624 helper_create_length_machine(void)
1626 circpad_machine_spec_t
*ret
=
1627 tor_malloc_zero(sizeof(circpad_machine_spec_t
));
1630 circpad_machine_states_init(ret
, 2);
1632 ret
->states
[CIRCPAD_STATE_START
].
1633 next_state
[CIRCPAD_EVENT_PADDING_SENT
] = CIRCPAD_STATE_BURST
;
1635 ret
->states
[CIRCPAD_STATE_BURST
].
1636 next_state
[CIRCPAD_EVENT_PADDING_SENT
] = CIRCPAD_STATE_BURST
;
1638 ret
->states
[CIRCPAD_STATE_BURST
].
1639 next_state
[CIRCPAD_EVENT_LENGTH_COUNT
] = CIRCPAD_STATE_END
;
1641 ret
->states
[CIRCPAD_STATE_BURST
].
1642 next_state
[CIRCPAD_EVENT_BINS_EMPTY
] = CIRCPAD_STATE_END
;
1644 /* No token removal.. end via state_length only */
1645 ret
->states
[CIRCPAD_STATE_BURST
].token_removal
=
1646 CIRCPAD_TOKEN_REMOVAL_NONE
;
1648 /* Let's have this one end after 12 packets */
1649 ret
->states
[CIRCPAD_STATE_BURST
].length_dist
.type
= CIRCPAD_DIST_UNIFORM
;
1650 ret
->states
[CIRCPAD_STATE_BURST
].length_dist
.param1
= 12;
1651 ret
->states
[CIRCPAD_STATE_BURST
].length_dist
.param2
= 13;
1652 ret
->states
[CIRCPAD_STATE_BURST
].max_length
= 12;
1654 ret
->states
[CIRCPAD_STATE_BURST
].histogram_len
= 4;
1656 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 0;
1657 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[1] = 1;
1658 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[2] = 1000000;
1659 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[3] = 10000000;
1661 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[0] = 0;
1662 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[1] = 0;
1663 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[2] = 6;
1665 ret
->states
[CIRCPAD_STATE_BURST
].histogram_total_tokens
= 6;
1666 ret
->states
[CIRCPAD_STATE_BURST
].use_rtt_estimate
= 0;
1667 ret
->states
[CIRCPAD_STATE_BURST
].length_includes_nonpadding
= 0;
1672 static circpad_machine_spec_t
*
1673 helper_create_conditional_machine(void)
1675 circpad_machine_spec_t
*ret
=
1676 tor_malloc_zero(sizeof(circpad_machine_spec_t
));
1679 circpad_machine_states_init(ret
, 2);
1681 ret
->states
[CIRCPAD_STATE_START
].
1682 next_state
[CIRCPAD_EVENT_PADDING_SENT
] = CIRCPAD_STATE_BURST
;
1684 ret
->states
[CIRCPAD_STATE_BURST
].
1685 next_state
[CIRCPAD_EVENT_PADDING_SENT
] = CIRCPAD_STATE_BURST
;
1687 ret
->states
[CIRCPAD_STATE_BURST
].
1688 next_state
[CIRCPAD_EVENT_LENGTH_COUNT
] = CIRCPAD_STATE_END
;
1690 /* Use EXACT removal strategy, otherwise setup_tokens() does not work */
1691 ret
->states
[CIRCPAD_STATE_BURST
].token_removal
=
1692 CIRCPAD_TOKEN_REMOVAL_EXACT
;
1694 ret
->states
[CIRCPAD_STATE_BURST
].histogram_len
= 3;
1696 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[0] = 0;
1697 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[1] = 1;
1698 ret
->states
[CIRCPAD_STATE_BURST
].histogram_edges
[2] = 1000000;
1700 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[0] = 6;
1701 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[1] = 0;
1702 ret
->states
[CIRCPAD_STATE_BURST
].histogram
[2] = 0;
1704 ret
->states
[CIRCPAD_STATE_BURST
].histogram_total_tokens
= 6;
1705 ret
->states
[CIRCPAD_STATE_BURST
].use_rtt_estimate
= 0;
1706 ret
->states
[CIRCPAD_STATE_BURST
].length_includes_nonpadding
= 1;
1712 helper_create_conditional_machines(void)
1714 circpad_machine_spec_t
*add
= helper_create_conditional_machine();
1716 if (!origin_padding_machines
)
1717 origin_padding_machines
= smartlist_new();
1718 if (!relay_padding_machines
)
1719 relay_padding_machines
= smartlist_new();
1721 add
->machine_num
= 2;
1722 add
->is_origin_side
= 1;
1723 add
->should_negotiate_end
= 1;
1724 add
->target_hopnum
= 2;
1726 /* Let's have this one end after 4 packets */
1727 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.type
= CIRCPAD_DIST_UNIFORM
;
1728 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.param1
= 4;
1729 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.param2
= 4;
1730 add
->states
[CIRCPAD_STATE_BURST
].max_length
= 4;
1732 add
->conditions
.requires_vanguards
= 0;
1733 add
->conditions
.min_hops
= 2;
1734 add
->conditions
.apply_state_mask
= CIRCPAD_CIRC_BUILDING
|
1735 CIRCPAD_CIRC_NO_STREAMS
|CIRCPAD_CIRC_HAS_RELAY_EARLY
;
1736 add
->conditions
.apply_purpose_mask
= CIRCPAD_PURPOSE_ALL
;
1737 circpad_register_padding_machine(add
, origin_padding_machines
);
1739 add
= helper_create_conditional_machine();
1740 add
->machine_num
= 3;
1741 add
->is_origin_side
= 1;
1742 add
->should_negotiate_end
= 1;
1743 add
->target_hopnum
= 2;
1745 /* Let's have this one end after 4 packets */
1746 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.type
= CIRCPAD_DIST_UNIFORM
;
1747 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.param1
= 4;
1748 add
->states
[CIRCPAD_STATE_BURST
].length_dist
.param2
= 4;
1749 add
->states
[CIRCPAD_STATE_BURST
].max_length
= 4;
1751 add
->conditions
.requires_vanguards
= 1;
1752 add
->conditions
.min_hops
= 3;
1753 add
->conditions
.apply_state_mask
= CIRCPAD_CIRC_OPENED
|
1754 CIRCPAD_CIRC_STREAMS
|CIRCPAD_CIRC_HAS_NO_RELAY_EARLY
;
1755 add
->conditions
.apply_purpose_mask
= CIRCPAD_PURPOSE_ALL
;
1756 circpad_register_padding_machine(add
, origin_padding_machines
);
1758 add
= helper_create_conditional_machine();
1759 add
->machine_num
= 2;
1760 circpad_register_padding_machine(add
, relay_padding_machines
);
1762 add
= helper_create_conditional_machine();
1763 add
->machine_num
= 3;
1764 circpad_register_padding_machine(add
, relay_padding_machines
);
1768 test_circuitpadding_state_length(void *arg
)
1772 * * Explicitly test that with no token removal enabled, we hit
1773 * the state length limit due to either padding, or non-padding.
1774 * * Repeat test with an arbitrary token removal strategy, and
1775 * verify that if we run out of tokens due to padding before we
1776 * hit the state length, we still go to state end (all our
1777 * token removal tests only test nonpadding token removal).
1779 int64_t actual_mocked_monotime_start
;
1781 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
1782 MOCK(circpad_send_command_to_hop
, circpad_send_command_to_hop_mock
);
1785 dummy_channel
.cmux
= circuitmux_alloc();
1786 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
,
1788 client_side
= TO_CIRCUIT(origin_circuit_new());
1789 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1790 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1793 monotime_enable_test_mocking();
1794 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
1795 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
1796 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
1797 curr_mocked_time
= actual_mocked_monotime_start
;
1799 /* This is needed so that we are not considered to be dormant */
1800 note_user_activity(20);
1802 timers_initialize();
1803 circpad_machine_spec_t
*client_machine
=
1804 helper_create_length_machine();
1806 MOCK(circuit_package_relay_cell
,
1807 circuit_package_relay_cell_mock
);
1808 MOCK(node_get_by_id
,
1809 node_get_by_id_mock
);
1811 client_side
->padding_machine
[0] = client_machine
;
1812 client_side
->padding_info
[0] =
1813 circpad_circuit_machineinfo_new(client_side
, 0);
1814 circpad_machine_runtime_t
*mi
= client_side
->padding_info
[0];
1816 circpad_cell_event_padding_sent(client_side
);
1817 tt_i64_op(mi
->state_length
, OP_EQ
, 12);
1818 tt_ptr_op(mi
->histogram
, OP_EQ
, NULL
);
1820 /* Verify that non-padding does not change our state length */
1821 circpad_cell_event_nonpadding_sent(client_side
);
1822 tt_i64_op(mi
->state_length
, OP_EQ
, 12);
1824 /* verify that sending padding changes our state length */
1825 for (uint64_t i
= mi
->state_length
-1; i
> 0; i
--) {
1826 circpad_send_padding_cell_for_callback(mi
);
1827 tt_i64_op(mi
->state_length
, OP_EQ
, i
);
1829 circpad_send_padding_cell_for_callback(mi
);
1831 tt_i64_op(mi
->state_length
, OP_EQ
, -1);
1832 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_END
);
1834 /* Restart machine */
1835 mi
->current_state
= CIRCPAD_STATE_START
;
1837 /* Now, count nonpadding as part of the state length */
1838 client_machine
->states
[CIRCPAD_STATE_BURST
].length_includes_nonpadding
= 1;
1840 circpad_cell_event_padding_sent(client_side
);
1841 tt_i64_op(mi
->state_length
, OP_EQ
, 12);
1843 /* Verify that non-padding does change our state length now */
1844 for (uint64_t i
= mi
->state_length
-1; i
> 0; i
--) {
1845 circpad_cell_event_nonpadding_sent(client_side
);
1846 tt_i64_op(mi
->state_length
, OP_EQ
, i
);
1849 circpad_cell_event_nonpadding_sent(client_side
);
1850 tt_i64_op(mi
->state_length
, OP_EQ
, -1);
1851 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_END
);
1853 /* Now, just test token removal when we send padding */
1854 client_machine
->states
[CIRCPAD_STATE_BURST
].token_removal
=
1855 CIRCPAD_TOKEN_REMOVAL_EXACT
;
1857 /* Restart machine */
1858 mi
->current_state
= CIRCPAD_STATE_START
;
1859 circpad_cell_event_padding_sent(client_side
);
1860 tt_i64_op(mi
->state_length
, OP_EQ
, 12);
1861 tt_ptr_op(mi
->histogram
, OP_NE
, NULL
);
1862 tt_int_op(mi
->chosen_bin
, OP_EQ
, 2);
1864 /* verify that sending padding changes our state length and
1865 * our histogram now */
1866 for (uint32_t i
= mi
->histogram
[2]-1; i
> 0; i
--) {
1867 circpad_send_padding_cell_for_callback(mi
);
1868 tt_int_op(mi
->chosen_bin
, OP_EQ
, 2);
1869 tt_int_op(mi
->histogram
[2], OP_EQ
, i
);
1872 tt_i64_op(mi
->state_length
, OP_EQ
, 7);
1873 tt_int_op(mi
->histogram
[2], OP_EQ
, 1);
1875 circpad_send_padding_cell_for_callback(mi
);
1876 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_END
);
1879 tor_free(client_machine
->states
);
1880 tor_free(client_machine
);
1882 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
1883 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
1885 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
1886 circuitmux_free(dummy_channel
.cmux
);
1888 monotime_disable_test_mocking();
1889 UNMOCK(circuit_package_relay_cell
);
1890 UNMOCK(circuitmux_attach_circuit
);
1891 UNMOCK(node_get_by_id
);
1897 test_circuitpadding_conditions(void *arg
)
1901 * 0. Make a few origin and client machines with diff conditions
1902 * * vanguards, purposes, has_opened circs, no relay early
1903 * * Client side should_negotiate_end
1905 * 1. Test STATE_END transitions
1906 * 2. Test new machine after end with same conditions
1907 * 3. Test new machine due to changed conditions
1908 * * Esp: built event, no relay early, no streams
1910 * 1. Test STATE_END with pending timers
1911 * 2. Test marking a circuit before padding callback fires
1912 * 3. Test freeing a circuit before padding callback fires
1914 int64_t actual_mocked_monotime_start
;
1916 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
1917 testing_enable_reproducible_rng();
1920 dummy_channel
.cmux
= circuitmux_alloc();
1921 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
,
1923 client_side
= TO_CIRCUIT(origin_circuit_new());
1924 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
1925 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
1928 monotime_enable_test_mocking();
1929 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
1930 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
1931 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
1932 curr_mocked_time
= actual_mocked_monotime_start
;
1934 /* This is needed so that we are not considered to be dormant */
1935 note_user_activity(20);
1937 timers_initialize();
1938 helper_create_conditional_machines();
1940 MOCK(circuit_package_relay_cell
,
1941 circuit_package_relay_cell_mock
);
1942 MOCK(node_get_by_id
,
1943 node_get_by_id_mock
);
1945 /* Simulate extend. This should result in the original machine getting
1946 * added, since the circuit is not built */
1947 simulate_single_hop_extend(client_side
, relay_side
, 1);
1948 simulate_single_hop_extend(client_side
, relay_side
, 1);
1950 /* Verify that machine #2 is added */
1951 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1952 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1954 /* Deliver a padding cell to the client, to trigger burst state */
1955 circpad_cell_event_padding_sent(client_side
);
1957 /* This should have trigger length shutdown condition on client.. */
1958 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
1959 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
1961 /* Verify machine is gone from both sides */
1962 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
1963 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
1965 /* Send another event.. verify machine gets re-added properly
1966 * (test race with shutdown) */
1967 simulate_single_hop_extend(client_side
, relay_side
, 1);
1968 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1969 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1971 TO_ORIGIN_CIRCUIT(client_side
)->p_streams
= 0;
1972 circpad_machine_event_circ_has_no_streams(TO_ORIGIN_CIRCUIT(client_side
));
1973 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1974 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1976 /* Now make the circuit opened and send built event */
1977 TO_ORIGIN_CIRCUIT(client_side
)->has_opened
= 1;
1978 circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side
));
1979 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1980 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1982 TO_ORIGIN_CIRCUIT(client_side
)->remaining_relay_early_cells
= 0;
1983 circpad_machine_event_circ_has_no_relay_early(
1984 TO_ORIGIN_CIRCUIT(client_side
));
1985 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1986 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
1988 get_options_mutable()->HSLayer2Nodes
= (void*)1;
1989 TO_ORIGIN_CIRCUIT(client_side
)->p_streams
= (void*)1;
1990 circpad_machine_event_circ_has_streams(TO_ORIGIN_CIRCUIT(client_side
));
1992 /* Verify different machine is added */
1993 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 3);
1994 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 3);
1996 /* Hold off on negotiated */
1997 deliver_negotiated
= 0;
1999 /* Deliver a padding cell to the client, to trigger burst state */
2000 circpad_cell_event_padding_sent(client_side
);
2002 /* This should have trigger length shutdown condition on client
2003 * but not the response for the padding machine */
2004 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2005 tt_ptr_op(client_side
->padding_machine
[0], OP_NE
, NULL
);
2007 /* Verify machine is gone from the relay (but negotiated not back yet */
2008 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2009 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2011 /* Add another hop and verify it's back */
2012 simulate_single_hop_extend(client_side
, relay_side
, 1);
2014 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 3);
2015 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 3);
2017 tt_ptr_op(client_side
->padding_info
[0], OP_NE
, NULL
);
2018 tt_ptr_op(relay_side
->padding_info
[0], OP_NE
, NULL
);
2021 /* XXX: Free everything */
2022 testing_disable_reproducible_rng();
2026 /** Disabled unstable test until #29298 is implemented (see #29122) */
2029 test_circuitpadding_circuitsetup_machine(void *arg
)
2031 int64_t actual_mocked_monotime_start
;
2035 * 1. Simulate a normal circuit setup pattern
2036 * a. Application traffic
2038 * FIXME: This should focus more on exercising the machine
2039 * features rather than actual traffic patterns. For example,
2040 * test cancellation and bins empty/refill
2044 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
2046 dummy_channel
.cmux
= circuitmux_alloc();
2047 client_side
= TO_CIRCUIT(origin_circuit_new());
2048 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
2050 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
2051 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2056 monotime_enable_test_mocking();
2057 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
2058 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
2059 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
2060 curr_mocked_time
= actual_mocked_monotime_start
;
2062 timers_initialize();
2063 circpad_machines_init();
2065 MOCK(circuit_package_relay_cell
,
2066 circuit_package_relay_cell_mock
);
2067 MOCK(node_get_by_id
,
2068 node_get_by_id_mock
);
2070 /* Test case #1: Build a 3 hop circuit, then wait and let pad */
2071 simulate_single_hop_extend(client_side
, relay_side
, 1);
2072 simulate_single_hop_extend(client_side
, relay_side
, 1);
2073 simulate_single_hop_extend(client_side
, relay_side
, 1);
2075 tt_int_op(n_client_cells
, OP_EQ
, 1);
2076 tt_int_op(n_relay_cells
, OP_EQ
, 1);
2077 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
2078 CIRCPAD_STATE_BURST
);
2079 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2080 CIRCPAD_STATE_BURST
);
2082 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2084 tt_int_op(relay_side
->padding_info
[0]->is_padding_timer_scheduled
,
2086 timers_advance_and_run(2000);
2087 tt_int_op(n_client_cells
, OP_EQ
, 2);
2088 tt_int_op(n_relay_cells
, OP_EQ
, 1);
2090 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2093 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2095 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2097 timers_advance_and_run(5000);
2098 tt_int_op(n_client_cells
, OP_EQ
, 2);
2099 tt_int_op(n_relay_cells
, OP_EQ
, 2);
2101 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2103 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2105 timers_advance_and_run(2000);
2106 tt_int_op(n_client_cells
, OP_EQ
, 3);
2107 tt_int_op(n_relay_cells
, OP_EQ
, 2);
2109 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2111 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2113 timers_advance_and_run(5000);
2114 tt_int_op(n_client_cells
, OP_EQ
, 3);
2115 tt_int_op(n_relay_cells
, OP_EQ
, 3);
2117 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2119 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2121 timers_advance_and_run(2000);
2122 tt_int_op(n_client_cells
, OP_EQ
, 4);
2123 tt_int_op(n_relay_cells
, OP_EQ
, 3);
2125 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2127 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2129 timers_advance_and_run(5000);
2130 tt_int_op(n_client_cells
, OP_EQ
, 4);
2131 tt_int_op(n_relay_cells
, OP_EQ
, 4);
2133 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2135 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2137 timers_advance_and_run(2000);
2138 tt_int_op(n_client_cells
, OP_EQ
, 5);
2139 tt_int_op(n_relay_cells
, OP_EQ
, 4);
2141 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2143 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2145 timers_advance_and_run(5000);
2146 tt_int_op(n_client_cells
, OP_EQ
, 5);
2147 tt_int_op(n_relay_cells
, OP_EQ
, 5);
2149 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2151 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2153 timers_advance_and_run(2000);
2154 tt_int_op(n_client_cells
, OP_EQ
, 6);
2155 tt_int_op(n_relay_cells
, OP_EQ
, 5);
2157 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2159 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2161 timers_advance_and_run(5000);
2162 tt_int_op(n_client_cells
, OP_EQ
, 6);
2163 tt_int_op(n_relay_cells
, OP_EQ
, 6);
2165 tt_int_op(client_side
->padding_info
[0]->current_state
,
2166 OP_EQ
, CIRCPAD_STATE_END
);
2167 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2169 tt_int_op(relay_side
->padding_info
[0]->current_state
,
2170 OP_EQ
, CIRCPAD_STATE_GAP
);
2171 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2174 /* Verify we can't schedule padding in END state */
2175 circpad_decision_t ret
=
2176 circpad_machine_schedule_padding(client_side
->padding_info
[0]);
2177 tt_int_op(ret
, OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2179 /* Simulate application traffic */
2180 circpad_cell_event_nonpadding_sent(client_side
);
2181 circpad_deliver_unrecognized_cell_events(relay_side
, CELL_DIRECTION_OUT
);
2182 circpad_deliver_unrecognized_cell_events(relay_side
, CELL_DIRECTION_IN
);
2183 circpad_deliver_recognized_relay_cell_events(client_side
, RELAY_COMMAND_DATA
,
2184 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
);
2186 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2187 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
2189 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2190 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2191 tt_int_op(n_client_cells
, OP_EQ
, 6);
2192 tt_int_op(n_relay_cells
, OP_EQ
, 7);
2194 // Test timer cancellation
2195 simulate_single_hop_extend(client_side
, relay_side
, 1);
2196 simulate_single_hop_extend(client_side
, relay_side
, 1);
2197 timers_advance_and_run(5000);
2198 circpad_cell_event_padding_received(client_side
);
2200 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
2201 CIRCPAD_STATE_BURST
);
2202 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2205 tt_int_op(n_client_cells
, OP_EQ
, 8);
2206 tt_int_op(n_relay_cells
, OP_EQ
, 8);
2207 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2209 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2212 /* Test timer cancel due to state rules */
2213 circpad_cell_event_nonpadding_sent(client_side
);
2214 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2216 circpad_cell_event_padding_received(client_side
);
2217 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2220 /* Simulate application traffic to cancel timer */
2221 circpad_cell_event_nonpadding_sent(client_side
);
2222 circpad_deliver_unrecognized_cell_events(relay_side
, CELL_DIRECTION_OUT
);
2223 circpad_deliver_unrecognized_cell_events(relay_side
, CELL_DIRECTION_IN
);
2224 circpad_deliver_recognized_relay_cell_events(client_side
, RELAY_COMMAND_DATA
,
2225 TO_ORIGIN_CIRCUIT(client_side
)->cpath
->next
);
2227 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2228 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
2230 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2231 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2233 /* No cells sent, except negotiate end from relay */
2234 tt_int_op(n_client_cells
, OP_EQ
, 8);
2235 tt_int_op(n_relay_cells
, OP_EQ
, 9);
2237 /* Test mark for close and free */
2238 simulate_single_hop_extend(client_side
, relay_side
, 1);
2239 simulate_single_hop_extend(client_side
, relay_side
, 1);
2240 timers_advance_and_run(5000);
2241 circpad_cell_event_padding_received(client_side
);
2243 tt_int_op(n_client_cells
, OP_EQ
, 10);
2244 tt_int_op(n_relay_cells
, OP_EQ
, 10);
2246 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
2247 CIRCPAD_STATE_BURST
);
2248 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2251 tt_u64_op(client_side
->padding_info
[0]->padding_scheduled_at_usec
,
2253 tt_u64_op(relay_side
->padding_info
[0]->padding_scheduled_at_usec
,
2255 circuit_mark_for_close(client_side
, END_CIRC_REASON_FLAG_REMOTE
);
2256 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
2257 timers_advance_and_run(5000);
2260 tt_int_op(n_client_cells
, OP_EQ
, 10);
2261 tt_int_op(n_relay_cells
, OP_EQ
, 10);
2264 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
2266 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
2267 circuitmux_free(dummy_channel
.cmux
);
2269 monotime_disable_test_mocking();
2270 UNMOCK(circuit_package_relay_cell
);
2271 UNMOCK(circuitmux_attach_circuit
);
2277 /** Helper function: Initializes a padding machine where every state uses the
2278 * uniform probability distribution. */
2280 helper_circpad_circ_distribution_machine_setup(int min
, int max
)
2282 circpad_machine_states_init(&circ_client_machine
, 7);
2284 circpad_state_t
*zero_st
= &circ_client_machine
.states
[0];
2285 zero_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 1;
2286 zero_st
->iat_dist
.type
= CIRCPAD_DIST_UNIFORM
;
2287 /* param2 is upper bound, param1 is lower */
2288 zero_st
->iat_dist
.param1
= min
;
2289 zero_st
->iat_dist
.param2
= max
;
2290 zero_st
->dist_added_shift_usec
= min
;
2291 zero_st
->dist_max_sample_usec
= max
;
2293 circpad_state_t
*first_st
= &circ_client_machine
.states
[1];
2294 first_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 2;
2295 first_st
->iat_dist
.type
= CIRCPAD_DIST_LOGISTIC
;
2296 /* param1 is Mu, param2 is sigma. */
2297 first_st
->iat_dist
.param1
= 9;
2298 first_st
->iat_dist
.param2
= 3;
2299 first_st
->dist_added_shift_usec
= min
;
2300 first_st
->dist_max_sample_usec
= max
;
2302 circpad_state_t
*second_st
= &circ_client_machine
.states
[2];
2303 second_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 3;
2304 second_st
->iat_dist
.type
= CIRCPAD_DIST_LOG_LOGISTIC
;
2305 /* param1 is Alpha, param2 is 1.0/Beta */
2306 second_st
->iat_dist
.param1
= 1;
2307 second_st
->iat_dist
.param2
= 0.5;
2308 second_st
->dist_added_shift_usec
= min
;
2309 second_st
->dist_max_sample_usec
= max
;
2311 circpad_state_t
*third_st
= &circ_client_machine
.states
[3];
2312 third_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 4;
2313 third_st
->iat_dist
.type
= CIRCPAD_DIST_GEOMETRIC
;
2314 /* param1 is 'p' (success probability) */
2315 third_st
->iat_dist
.param1
= 0.2;
2316 third_st
->dist_added_shift_usec
= min
;
2317 third_st
->dist_max_sample_usec
= max
;
2319 circpad_state_t
*fourth_st
= &circ_client_machine
.states
[4];
2320 fourth_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 5;
2321 fourth_st
->iat_dist
.type
= CIRCPAD_DIST_WEIBULL
;
2322 /* param1 is k, param2 is Lambda */
2323 fourth_st
->iat_dist
.param1
= 1.5;
2324 fourth_st
->iat_dist
.param2
= 1;
2325 fourth_st
->dist_added_shift_usec
= min
;
2326 fourth_st
->dist_max_sample_usec
= max
;
2328 circpad_state_t
*fifth_st
= &circ_client_machine
.states
[5];
2329 fifth_st
->next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = 6;
2330 fifth_st
->iat_dist
.type
= CIRCPAD_DIST_PARETO
;
2331 /* param1 is sigma, param2 is xi */
2332 fifth_st
->iat_dist
.param1
= 1;
2333 fifth_st
->iat_dist
.param2
= 5;
2334 fifth_st
->dist_added_shift_usec
= min
;
2335 fifth_st
->dist_max_sample_usec
= max
;
2338 /** Simple test that the padding delays sampled from a uniform distribution
2339 * actually fail within the uniform distribution range. */
2341 test_circuitpadding_sample_distribution(void *arg
)
2343 circpad_machine_runtime_t
*mi
;
2349 /* mock this function so that we dont actually schedule any padding */
2350 MOCK(circpad_machine_schedule_padding
,
2351 circpad_machine_schedule_padding_mock
);
2352 testing_enable_reproducible_rng();
2354 /* Initialize a machine with multiple probability distributions */
2355 circpad_machines_init();
2356 helper_circpad_circ_distribution_machine_setup(0, 10);
2358 /* Initialize machine and circuits */
2359 client_side
= TO_CIRCUIT(origin_circuit_new());
2360 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2361 client_side
->padding_machine
[0] = &circ_client_machine
;
2362 client_side
->padding_info
[0] =
2363 circpad_circuit_machineinfo_new(client_side
, 0);
2364 mi
= client_side
->padding_info
[0];
2366 /* For every state, sample a bunch of values from the distribution and ensure
2367 * they fall within range. */
2368 for (n_states
= 0 ; n_states
< 6; n_states
++) {
2369 /* Make sure we in the right state */
2370 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
, n_states
);
2372 for (n_samples
= 0; n_samples
< 100; n_samples
++) {
2373 circpad_delay_t delay
= circpad_machine_sample_delay(mi
);
2374 tt_int_op(delay
, OP_GE
, 0);
2375 tt_int_op(delay
, OP_LE
, 10);
2378 /* send a non-padding cell to move to the next machine state */
2379 circpad_cell_event_nonpadding_received(client_side
);
2383 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
2384 UNMOCK(circpad_machine_schedule_padding
);
2385 testing_disable_reproducible_rng();
2388 static circpad_decision_t
2389 circpad_machine_spec_transition_mock(circpad_machine_runtime_t
*mi
,
2390 circpad_event_t event
)
2395 return CIRCPAD_STATE_UNCHANGED
;
2398 /* Test per-machine padding rate limits */
2400 test_circuitpadding_machine_rate_limiting(void *arg
)
2404 circpad_machine_runtime_t
*mi
;
2407 /* Ignore machine transitions for the purposes of this function, we only
2408 * really care about padding counts */
2409 MOCK(circpad_machine_spec_transition
, circpad_machine_spec_transition_mock
);
2410 MOCK(circpad_send_command_to_hop
, circpad_send_command_to_hop_mock
);
2411 testing_enable_reproducible_rng();
2413 /* Setup machine and circuits */
2414 client_side
= TO_CIRCUIT(origin_circuit_new());
2415 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2416 helper_create_basic_machine();
2417 client_side
->padding_machine
[0] = &circ_client_machine
;
2418 client_side
->padding_info
[0] =
2419 circpad_circuit_machineinfo_new(client_side
, 0);
2420 mi
= client_side
->padding_info
[0];
2421 /* Set up the machine info so that we can get through the basic functions */
2422 mi
->state_length
= CIRCPAD_STATE_LENGTH_INFINITE
;
2424 /* First we are going to test the per-machine rate limits */
2425 circ_client_machine
.max_padding_percent
= 50;
2426 circ_client_machine
.allowed_padding_count
= 100;
2428 /* Check padding limit, should be fine since we haven't sent anything yet. */
2429 retval
= circpad_machine_reached_padding_limit(mi
);
2430 tt_int_op(retval
, OP_EQ
, 0);
2432 /* Send 99 padding cells which is below circpad_global_allowed_cells=100, so
2433 * the rate limit will not trigger */
2434 for (i
=0;i
<99;i
++) {
2435 circpad_send_padding_cell_for_callback(mi
);
2437 retval
= circpad_machine_reached_padding_limit(mi
);
2438 tt_int_op(retval
, OP_EQ
, 0);
2440 /* Now send another padding cell to pass circpad_global_allowed_cells=100,
2441 and see that the limit will trigger */
2442 circpad_send_padding_cell_for_callback(mi
);
2443 retval
= circpad_machine_reached_padding_limit(mi
);
2444 tt_int_op(retval
, OP_EQ
, 1);
2446 retval
= circpad_machine_schedule_padding(mi
);
2447 tt_int_op(retval
, OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2450 for (;i
<UINT16_MAX
;i
++) {
2451 circpad_send_padding_cell_for_callback(mi
);
2453 tt_int_op(mi
->padding_sent
, OP_EQ
, UINT16_MAX
/2+1);
2455 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, mi
);
2456 for (i
=0;i
<UINT16_MAX
;i
++) {
2457 circpad_cell_event_nonpadding_sent(client_side
);
2460 tt_int_op(mi
->nonpadding_sent
, OP_EQ
, UINT16_MAX
/2);
2461 tt_int_op(mi
->padding_sent
, OP_EQ
, UINT16_MAX
/4+1);
2464 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
2465 testing_disable_reproducible_rng();
2468 /* Test global padding rate limits */
2470 test_circuitpadding_global_rate_limiting(void *arg
)
2474 circpad_machine_runtime_t
*mi
;
2476 int64_t actual_mocked_monotime_start
;
2478 /* Ignore machine transitions for the purposes of this function, we only
2479 * really care about padding counts */
2480 MOCK(circpad_machine_spec_transition
, circpad_machine_spec_transition_mock
);
2481 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
2482 MOCK(circuit_package_relay_cell
,
2483 circuit_package_relay_cell_mock
);
2484 MOCK(monotime_absolute_usec
, mock_monotime_absolute_usec
);
2485 testing_enable_reproducible_rng();
2488 monotime_enable_test_mocking();
2489 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
2490 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
2491 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
2492 curr_mocked_time
= actual_mocked_monotime_start
;
2493 timers_initialize();
2495 client_side
= TO_CIRCUIT(origin_circuit_new());
2496 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2497 dummy_channel
.cmux
= circuitmux_alloc();
2499 /* Setup machine and circuits */
2500 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
2501 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
2502 helper_create_basic_machine();
2503 relay_side
->padding_machine
[0] = &circ_client_machine
;
2504 relay_side
->padding_info
[0] =
2505 circpad_circuit_machineinfo_new(relay_side
, 0);
2506 mi
= relay_side
->padding_info
[0];
2507 /* Set up the machine info so that we can get through the basic functions */
2508 mi
->state_length
= CIRCPAD_STATE_LENGTH_INFINITE
;
2510 simulate_single_hop_extend(client_side
, relay_side
, 1);
2511 simulate_single_hop_extend(client_side
, relay_side
, 1);
2513 /* Now test the global limits by setting up the consensus */
2514 networkstatus_t vote1
;
2515 vote1
.net_params
= smartlist_new();
2516 smartlist_split_string(vote1
.net_params
,
2517 "circpad_global_allowed_cells=100 circpad_global_max_padding_pct=50",
2519 /* Register global limits with the padding subsystem */
2520 circpad_new_consensus_params(&vote1
);
2522 /* Check padding limit, should be fine since we haven't sent anything yet. */
2523 retval
= circpad_machine_reached_padding_limit(mi
);
2524 tt_int_op(retval
, OP_EQ
, 0);
2526 /* Send 99 padding cells which is below circpad_global_allowed_cells=100, so
2527 * the rate limit will not trigger */
2528 for (i
=0;i
<99;i
++) {
2529 circpad_send_padding_cell_for_callback(mi
);
2531 retval
= circpad_machine_reached_padding_limit(mi
);
2532 tt_int_op(retval
, OP_EQ
, 0);
2534 /* Now send another padding cell to pass circpad_global_allowed_cells=100,
2535 and see that the limit will trigger */
2536 circpad_send_padding_cell_for_callback(mi
);
2537 retval
= circpad_machine_reached_padding_limit(mi
);
2538 tt_int_op(retval
, OP_EQ
, 1);
2540 retval
= circpad_machine_schedule_padding(mi
);
2541 tt_int_op(retval
, OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2543 /* Now send 92 non-padding cells to get near the
2544 * circpad_global_max_padding_pct=50 limit; in particular with 96 non-padding
2545 * cells, the padding traffic is still 51% of total traffic so limit should
2547 for (i
=0;i
<92;i
++) {
2548 circpad_cell_event_nonpadding_sent(relay_side
);
2550 retval
= circpad_machine_reached_padding_limit(mi
);
2551 tt_int_op(retval
, OP_EQ
, 1);
2553 /* Send another non-padding cell to bring the padding traffic to 50% of total
2554 * traffic and get past the limit */
2555 circpad_cell_event_nonpadding_sent(relay_side
);
2556 retval
= circpad_machine_reached_padding_limit(mi
);
2557 tt_int_op(retval
, OP_EQ
, 0);
2560 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
2561 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
2562 circuitmux_free(dummy_channel
.cmux
);
2563 SMARTLIST_FOREACH(vote1
.net_params
, char *, cp
, tor_free(cp
));
2564 smartlist_free(vote1
.net_params
);
2565 testing_disable_reproducible_rng();
2568 /* Test reduced and disabled padding */
2570 test_circuitpadding_reduce_disable(void *arg
)
2573 int64_t actual_mocked_monotime_start
;
2575 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
2576 testing_enable_reproducible_rng();
2579 dummy_channel
.cmux
= circuitmux_alloc();
2580 relay_side
= (circuit_t
*)new_fake_orcirc(&dummy_channel
,
2582 client_side
= (circuit_t
*)origin_circuit_new();
2583 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
2584 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2586 circpad_machines_init();
2587 helper_create_conditional_machines();
2590 monotime_enable_test_mocking();
2591 actual_mocked_monotime_start
= MONOTIME_MOCK_START
;
2592 monotime_set_mock_time_nsec(actual_mocked_monotime_start
);
2593 monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start
);
2594 curr_mocked_time
= actual_mocked_monotime_start
;
2595 timers_initialize();
2597 /* This is needed so that we are not considered to be dormant */
2598 note_user_activity(20);
2600 MOCK(circuit_package_relay_cell
,
2601 circuit_package_relay_cell_mock
);
2602 MOCK(node_get_by_id
,
2603 node_get_by_id_mock
);
2605 /* Simulate extend. This should result in the original machine getting
2606 * added, since the circuit is not built */
2607 simulate_single_hop_extend(client_side
, relay_side
, 1);
2608 simulate_single_hop_extend(client_side
, relay_side
, 1);
2610 /* Verify that machine #2 is added */
2611 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2612 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2614 /* Deliver a padding cell to the client, to trigger burst state */
2615 circpad_cell_event_padding_sent(client_side
);
2617 /* This should have trigger length shutdown condition on client.. */
2618 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2619 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
2621 /* Verify machine is gone from both sides */
2622 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2623 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2625 /* Now test the reduced padding machine by setting up the consensus */
2626 networkstatus_t vote1
;
2627 vote1
.net_params
= smartlist_new();
2628 smartlist_split_string(vote1
.net_params
,
2629 "circpad_padding_reduced=1", NULL
, 0, 0);
2631 /* Register reduced padding machine with the padding subsystem */
2632 circpad_new_consensus_params(&vote1
);
2634 simulate_single_hop_extend(client_side
, relay_side
, 1);
2636 /* Verify that machine #0 is added */
2637 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2638 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2641 circpad_machine_reached_padding_limit(client_side
->padding_info
[0]),
2644 circpad_machine_reached_padding_limit(relay_side
->padding_info
[0]),
2647 /* Test that machines get torn down when padding is disabled */
2648 SMARTLIST_FOREACH(vote1
.net_params
, char *, cp
, tor_free(cp
));
2649 smartlist_free(vote1
.net_params
);
2650 vote1
.net_params
= smartlist_new();
2651 smartlist_split_string(vote1
.net_params
,
2652 "circpad_padding_disabled=1", NULL
, 0, 0);
2654 /* Register reduced padding machine with the padding subsystem */
2655 circpad_new_consensus_params(&vote1
);
2658 circpad_machine_schedule_padding(client_side
->padding_info
[0]),
2659 OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2661 circpad_machine_schedule_padding(relay_side
->padding_info
[0]),
2662 OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2664 /* Signal that circuit is built: this event causes us to re-evaluate
2665 * machine conditions (which don't apply because padding is disabled). */
2666 circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side
));
2668 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2669 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
2670 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2671 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2673 SMARTLIST_FOREACH(vote1
.net_params
, char *, cp
, tor_free(cp
));
2674 smartlist_free(vote1
.net_params
);
2675 vote1
.net_params
= NULL
;
2676 circpad_new_consensus_params(&vote1
);
2678 get_options_mutable()->ReducedCircuitPadding
= 1;
2680 simulate_single_hop_extend(client_side
, relay_side
, 1);
2682 /* Verify that machine #0 is added */
2683 tt_int_op(client_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2684 tt_int_op(relay_side
->padding_machine
[0]->machine_num
, OP_EQ
, 2);
2687 circpad_machine_reached_padding_limit(client_side
->padding_info
[0]),
2690 circpad_machine_reached_padding_limit(relay_side
->padding_info
[0]),
2693 get_options_mutable()->CircuitPadding
= 0;
2696 circpad_machine_schedule_padding(client_side
->padding_info
[0]),
2697 OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2699 circpad_machine_schedule_padding(relay_side
->padding_info
[0]),
2700 OP_EQ
, CIRCPAD_STATE_UNCHANGED
);
2702 /* Signal that circuit is built: this event causes us to re-evaluate
2703 * machine conditions (which don't apply because padding is disabled). */
2705 circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side
));
2707 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
2708 tt_ptr_op(client_side
->padding_machine
[0], OP_EQ
, NULL
);
2709 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
2710 tt_ptr_op(relay_side
->padding_machine
[0], OP_EQ
, NULL
);
2713 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
2714 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
2715 circuitmux_free(dummy_channel
.cmux
);
2716 testing_disable_reproducible_rng();
2719 /** Just a basic machine whose whole purpose is to reach the END state */
2721 helper_create_ender_machine(void)
2724 circpad_machine_states_init(&circ_client_machine
, 2);
2726 circ_client_machine
.states
[CIRCPAD_STATE_START
].
2727 next_state
[CIRCPAD_EVENT_NONPADDING_RECV
] = CIRCPAD_STATE_END
;
2729 circ_client_machine
.conditions
.apply_state_mask
= CIRCPAD_STATE_ALL
;
2730 circ_client_machine
.conditions
.apply_purpose_mask
= CIRCPAD_PURPOSE_ALL
;
2733 static time_t mocked_timeofday
;
2734 /** Set timeval to a mock date and time. This is necessary
2735 * to make tor_gettimeofday() mockable. */
2737 mock_tor_gettimeofday(struct timeval
*timeval
)
2739 timeval
->tv_sec
= mocked_timeofday
;
2740 timeval
->tv_usec
= 0;
2743 /** Test manual managing of circuit lifetimes by the circuitpadding
2744 * subsystem. In particular this test goes through all the cases of the
2745 * circpad_marked_circuit_for_padding() function, via
2746 * circuit_mark_for_close() as well as
2747 * circuit_expire_old_circuits_clientside(). */
2749 test_circuitpadding_manage_circuit_lifetime(void *arg
)
2751 circpad_machine_runtime_t
*mi
;
2755 client_side
= (circuit_t
*)origin_circuit_new();
2756 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2757 monotime_enable_test_mocking();
2758 MOCK(tor_gettimeofday
, mock_tor_gettimeofday
);
2759 mocked_timeofday
= 23;
2761 helper_create_ender_machine();
2763 /* Enable manual circuit lifetime manage for this test */
2764 circ_client_machine
.manage_circ_lifetime
= 1;
2767 client_side
->padding_machine
[0] = &circ_client_machine
;
2768 client_side
->padding_info
[0] =
2769 circpad_circuit_machineinfo_new(client_side
, 0);
2770 mi
= client_side
->padding_info
[0];
2772 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_START
);
2774 /* Check that the circuit is not marked for close */
2775 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2776 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_GENERAL
);
2778 /* Mark this circuit for close due to a remote reason */
2779 circuit_mark_for_close(client_side
,
2780 END_CIRC_REASON_FLAG_REMOTE
|END_CIRC_REASON_NONE
);
2781 tt_ptr_op(client_side
->padding_info
[0], OP_NE
, NULL
);
2782 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2783 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_GENERAL
);
2784 client_side
->marked_for_close
= 0;
2786 /* Mark this circuit for close due to a protocol issue */
2787 circuit_mark_for_close(client_side
, END_CIRC_REASON_TORPROTOCOL
);
2788 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2789 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_GENERAL
);
2790 client_side
->marked_for_close
= 0;
2792 /* Mark a measurement circuit for close */
2793 client_side
->purpose
= CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT
;
2794 circuit_mark_for_close(client_side
, END_CIRC_REASON_NONE
);
2795 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2796 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT
);
2797 client_side
->marked_for_close
= 0;
2799 /* Mark a general circuit for close */
2800 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2801 circuit_mark_for_close(client_side
, END_CIRC_REASON_NONE
);
2803 /* Check that this circuit is still not marked for close since we are
2804 * managing the lifetime manually, but the circuit was tagged as such by the
2805 * circpadding subsystem */
2806 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2807 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING
);
2809 /* We just tested case (1) from the comments of
2810 * circpad_circuit_should_be_marked_for_close() */
2812 /* Transition the machine to the END state but did not delete its machine */
2813 tt_ptr_op(client_side
->padding_info
[0], OP_NE
, NULL
);
2814 circpad_cell_event_nonpadding_received(client_side
);
2815 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_END
);
2817 /* We just tested case (3) from the comments of
2818 * circpad_circuit_should_be_marked_for_close().
2819 * Now let's go for case (2). */
2821 /* Reset the close mark */
2822 client_side
->marked_for_close
= 0;
2824 /* Mark this circuit for close */
2825 circuit_mark_for_close(client_side
, 0);
2827 /* See that the circ got closed since we are already in END state */
2828 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2830 /* We just tested case (2). Now let's see that case (4) is unreachable as
2831 that comment claims */
2833 /* First, reset all close marks and tags */
2834 client_side
->marked_for_close
= 0;
2835 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2837 /* Now re-create the ender machine so that we can transition to END again */
2838 /* Free up some stuff first */
2839 circpad_circuit_free_all_machineinfos(client_side
);
2840 tor_free(circ_client_machine
.states
);
2841 helper_create_ender_machine();
2843 client_side
->padding_machine
[0] = &circ_client_machine
;
2844 client_side
->padding_info
[0] =
2845 circpad_circuit_machineinfo_new(client_side
, 0);
2846 mi
= client_side
->padding_info
[0];
2848 /* Check we are in START. */
2849 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_START
);
2851 /* Test that we don't expire this circuit yet */
2852 client_side
->timestamp_dirty
= 0;
2853 client_side
->state
= CIRCUIT_STATE_OPEN
;
2854 tor_gettimeofday(&client_side
->timestamp_began
);
2855 TO_ORIGIN_CIRCUIT(client_side
)->circuit_idle_timeout
= 23;
2856 mocked_timeofday
+= 24;
2857 circuit_expire_old_circuits_clientside();
2858 circuit_expire_old_circuits_clientside();
2859 circuit_expire_old_circuits_clientside();
2860 tt_int_op(client_side
->timestamp_dirty
, OP_NE
, 0);
2861 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2862 tt_int_op(client_side
->purpose
, OP_EQ
, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING
);
2864 /* Runaway circpad test: if the machine does not transition to end,
2865 * test that after CIRCPAD_DELAY_MAX_SECS, we get marked anyway */
2866 mocked_timeofday
= client_side
->timestamp_dirty
2867 + get_options()->MaxCircuitDirtiness
+ 2;
2868 client_side
->padding_info
[0]->last_cell_time_sec
=
2869 approx_time()-(CIRCPAD_DELAY_MAX_SECS
+10);
2870 circuit_expire_old_circuits_clientside();
2871 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2873 /* Test back to normal: if we had activity, we won't close */
2874 client_side
->padding_info
[0]->last_cell_time_sec
= approx_time();
2875 client_side
->marked_for_close
= 0;
2876 circuit_expire_old_circuits_clientside();
2877 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2879 /* Transition to END, but before we're past the dirty timer */
2880 mocked_timeofday
= client_side
->timestamp_dirty
;
2881 circpad_cell_event_nonpadding_received(client_side
);
2882 tt_int_op(mi
->current_state
, OP_EQ
, CIRCPAD_STATE_END
);
2884 /* Verify that the circuit was not closed. */
2885 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2887 /* Now that we are in END state, we can be closed by expiry, but via
2888 * the timestamp_dirty path, not the idle path. So first test not dirty
2890 mocked_timeofday
= client_side
->timestamp_dirty
;
2891 circuit_expire_old_circuits_clientside();
2892 tt_int_op(client_side
->marked_for_close
, OP_EQ
, 0);
2893 mocked_timeofday
= client_side
->timestamp_dirty
2894 + get_options()->MaxCircuitDirtiness
+ 2;
2895 circuit_expire_old_circuits_clientside();
2896 tt_int_op(client_side
->marked_for_close
, OP_NE
, 0);
2899 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
2900 tor_free(circ_client_machine
.states
);
2901 monotime_disable_test_mocking();
2902 UNMOCK(tor_gettimeofday
);
2905 /** Helper for the test_circuitpadding_hs_machines test:
2907 * - Create a client and relay circuit.
2908 * - Setup right circuit purpose and attach a machine to the client circuit.
2909 * - Verify that state transitions work as intended and state length gets
2912 * This function is able to do this test both for intro and rend circuits
2913 * depending on the value of <b>test_intro_circs</b>.
2916 helper_test_hs_machines(bool test_intro_circs
)
2918 /* Setup the circuits */
2919 origin_circuit_t
*origin_client_side
= origin_circuit_new();
2920 client_side
= TO_CIRCUIT(origin_client_side
);
2921 client_side
->purpose
= CIRCUIT_PURPOSE_C_GENERAL
;
2923 dummy_channel
.cmux
= circuitmux_alloc();
2924 relay_side
= TO_CIRCUIT(new_fake_orcirc(&dummy_channel
, &dummy_channel
));
2925 relay_side
->purpose
= CIRCUIT_PURPOSE_OR
;
2927 /* extend the client circ to two hops */
2928 simulate_single_hop_extend(client_side
, relay_side
, 1);
2929 simulate_single_hop_extend(client_side
, relay_side
, 1);
2931 /* machines only apply on opened circuits */
2932 origin_client_side
->has_opened
= 1;
2934 /************************************/
2936 /* Attaching the client machine now won't work here because of a wrong
2938 tt_assert(!client_side
->padding_machine
[0]);
2939 circpad_add_matching_machines(origin_client_side
, origin_padding_machines
);
2940 tt_assert(!client_side
->padding_machine
[0]);
2942 /* Change the purpose, see the machine getting attached */
2943 client_side
->purpose
= test_intro_circs
?
2944 CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT
: CIRCUIT_PURPOSE_C_REND_JOINED
;
2945 circpad_add_matching_machines(origin_client_side
, origin_padding_machines
);
2946 tt_ptr_op(client_side
->padding_info
[0], OP_NE
, NULL
);
2947 tt_ptr_op(client_side
->padding_machine
[0], OP_NE
, NULL
);
2949 tt_ptr_op(relay_side
->padding_info
[0], OP_NE
, NULL
);
2950 tt_ptr_op(relay_side
->padding_machine
[0], OP_NE
, NULL
);
2952 /* Verify that the right machine is attached */
2953 tt_str_op(client_side
->padding_machine
[0]->name
, OP_EQ
,
2954 test_intro_circs
? "client_ip_circ" : "client_rp_circ");
2955 tt_str_op(relay_side
->padding_machine
[0]->name
, OP_EQ
,
2956 test_intro_circs
? "relay_ip_circ": "relay_rp_circ");
2958 /***********************************/
2960 /* Intro machines are at START state, but rend machines have already skipped
2961 * to OBFUSCATE_CIRC_SETUP because of the sent PADDING_NEGOTIATE. */
2962 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
2963 CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP
);
2964 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2965 CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP
);
2967 /*Send non-padding to move the machines from START to OBFUSCATE_CIRC_SETUP */
2968 circpad_cell_event_nonpadding_received(client_side
);
2969 circpad_cell_event_nonpadding_received(relay_side
);
2970 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
2971 CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP
);
2972 tt_int_op(relay_side
->padding_info
[0]->current_state
, OP_EQ
,
2973 CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP
);
2975 /* Check that the state lengths have been sampled and are within range */
2976 circpad_machine_runtime_t
*client_machine_runtime
=
2977 client_side
->padding_info
[0];
2978 circpad_machine_runtime_t
*relay_machine_runtime
=
2979 relay_side
->padding_info
[0];
2981 if (test_intro_circs
) {
2982 /* on the client side, we don't send any padding so
2983 * state length is not set */
2984 tt_i64_op(client_machine_runtime
->state_length
, OP_EQ
, -1);
2985 /* relay side has state limits. check them */
2986 tt_i64_op(relay_machine_runtime
->state_length
, OP_GE
,
2987 INTRO_MACHINE_MINIMUM_PADDING
);
2988 tt_i64_op(relay_machine_runtime
->state_length
, OP_LT
,
2989 INTRO_MACHINE_MAXIMUM_PADDING
);
2991 tt_i64_op(client_machine_runtime
->state_length
, OP_EQ
, 1);
2992 tt_i64_op(relay_machine_runtime
->state_length
, OP_EQ
, 1);
2995 if (test_intro_circs
) {
2997 /* Send state_length worth of padding from the relay and see that the
2998 * client state goes to END */
2999 for (i
= (int) relay_machine_runtime
->state_length
; i
> 0 ; i
--) {
3000 circpad_send_padding_cell_for_callback(relay_machine_runtime
);
3002 /* See that the machine has been teared down after all the length has been
3003 * exhausted (the padding info should now be null on both sides) */
3004 tt_ptr_op(relay_side
->padding_info
[0], OP_EQ
, NULL
);
3005 tt_ptr_op(client_side
->padding_info
[0], OP_EQ
, NULL
);
3008 /* Send state_length worth of padding and see that the state goes to END */
3009 for (i
= (int) client_machine_runtime
->state_length
; i
> 0 ; i
--) {
3010 circpad_send_padding_cell_for_callback(client_machine_runtime
);
3012 /* See that the machine has been teared down after all the length has been
3014 tt_int_op(client_side
->padding_info
[0]->current_state
, OP_EQ
,
3019 free_fake_orcirc(TO_OR_CIRCUIT(relay_side
));
3020 circuitmux_detach_all_circuits(dummy_channel
.cmux
, NULL
);
3021 circuitmux_free(dummy_channel
.cmux
);
3022 free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side
));
3025 /** Test that the HS circuit padding machines work as intended. */
3027 test_circuitpadding_hs_machines(void *arg
)
3033 * 1) Register the HS machines, which aim to hide the presence of
3034 * onion service traffic on the client-side
3036 * 2) Call helper_test_hs_machines() to perform tests for the intro circuit
3037 * machines and for the rend circuit machines.
3040 MOCK(circuitmux_attach_circuit
, circuitmux_attach_circuit_mock
);
3041 MOCK(circuit_package_relay_cell
, circuit_package_relay_cell_mock
);
3042 MOCK(circuit_get_nth_node
, circuit_get_nth_node_mock
);
3043 MOCK(circpad_machine_schedule_padding
,circpad_machine_schedule_padding_mock
);
3045 origin_padding_machines
= smartlist_new();
3046 relay_padding_machines
= smartlist_new();
3051 monotime_enable_test_mocking();
3052 monotime_set_mock_time_nsec(1*TOR_NSEC_PER_USEC
);
3053 monotime_coarse_set_mock_time_nsec(1*TOR_NSEC_PER_USEC
);
3054 curr_mocked_time
= 1*TOR_NSEC_PER_USEC
;
3056 timers_initialize();
3058 /* This is needed so that we are not considered to be dormant */
3059 note_user_activity(20);
3061 /************************************/
3063 /* Register the HS machines */
3064 circpad_machine_client_hide_intro_circuits(origin_padding_machines
);
3065 circpad_machine_client_hide_rend_circuits(origin_padding_machines
);
3066 circpad_machine_relay_hide_intro_circuits(relay_padding_machines
);
3067 circpad_machine_relay_hide_rend_circuits(relay_padding_machines
);
3069 /***********************************/
3071 /* Do the tests for the intro circuit machines */
3072 helper_test_hs_machines(true);
3073 /* Do the tests for the rend circuit machines */
3074 helper_test_hs_machines(false);
3077 monotime_disable_test_mocking();
3079 SMARTLIST_FOREACH_BEGIN(origin_padding_machines
,
3080 circpad_machine_spec_t
*, m
) {
3081 machine_spec_free(m
);
3082 } SMARTLIST_FOREACH_END(m
);
3084 SMARTLIST_FOREACH_BEGIN(relay_padding_machines
,
3085 circpad_machine_spec_t
*, m
) {
3086 machine_spec_free(m
);
3087 } SMARTLIST_FOREACH_END(m
);
3089 smartlist_free(origin_padding_machines
);
3090 smartlist_free(relay_padding_machines
);
3092 UNMOCK(circuitmux_attach_circuit
);
3093 UNMOCK(circuit_package_relay_cell
);
3094 UNMOCK(circuit_get_nth_node
);
3095 UNMOCK(circpad_machine_schedule_padding
);
3098 /** Test that we effectively ignore non-padding cells in padding circuits. */
3100 test_circuitpadding_ignore_non_padding_cells(void *arg
)
3107 client_side
= (circuit_t
*)origin_circuit_new();
3108 client_side
->purpose
= CIRCUIT_PURPOSE_C_CIRCUIT_PADDING
;
3110 rh
.command
= RELAY_COMMAND_BEGIN
;
3112 setup_full_capture_of_logs(LOG_INFO
);
3113 retval
= handle_relay_cell_command(NULL
, client_side
, NULL
, NULL
, &rh
, 0);
3114 tt_int_op(retval
, OP_EQ
, 0);
3115 expect_log_msg_containing("Ignored cell");
3121 #define TEST_CIRCUITPADDING(name, flags) \
3122 { #name, test_##name, (flags), NULL, NULL }
3124 struct testcase_t circuitpadding_tests
[] = {
3125 TEST_CIRCUITPADDING(circuitpadding_tokens
, TT_FORK
),
3126 TEST_CIRCUITPADDING(circuitpadding_state_length
, TT_FORK
),
3127 TEST_CIRCUITPADDING(circuitpadding_negotiation
, TT_FORK
),
3128 TEST_CIRCUITPADDING(circuitpadding_wronghop
, TT_FORK
),
3129 /** Disabled unstable test until #29298 is implemented (see #29122) */
3130 // TEST_CIRCUITPADDING(circuitpadding_circuitsetup_machine, TT_FORK),
3131 TEST_CIRCUITPADDING(circuitpadding_conditions
, TT_FORK
),
3132 TEST_CIRCUITPADDING(circuitpadding_rtt
, TT_FORK
),
3133 TEST_CIRCUITPADDING(circuitpadding_sample_distribution
, TT_FORK
),
3134 TEST_CIRCUITPADDING(circuitpadding_machine_rate_limiting
, TT_FORK
),
3135 TEST_CIRCUITPADDING(circuitpadding_global_rate_limiting
, TT_FORK
),
3136 TEST_CIRCUITPADDING(circuitpadding_reduce_disable
, TT_FORK
),
3137 TEST_CIRCUITPADDING(circuitpadding_token_removal_lower
, TT_FORK
),
3138 TEST_CIRCUITPADDING(circuitpadding_token_removal_higher
, TT_FORK
),
3139 TEST_CIRCUITPADDING(circuitpadding_closest_token_removal
, TT_FORK
),
3140 TEST_CIRCUITPADDING(circuitpadding_closest_token_removal_usec
, TT_FORK
),
3141 TEST_CIRCUITPADDING(circuitpadding_token_removal_exact
, TT_FORK
),
3142 TEST_CIRCUITPADDING(circuitpadding_manage_circuit_lifetime
, TT_FORK
),
3143 TEST_CIRCUITPADDING(circuitpadding_hs_machines
, TT_FORK
),
3144 TEST_CIRCUITPADDING(circuitpadding_ignore_non_padding_cells
, TT_FORK
),