From fcd51fd49f8c30ab8d5d1d099d43e510187150c6 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Thu, 23 May 2019 09:29:24 -0400 Subject: [PATCH] Tests for deciding how full our relay cells should be --- src/core/or/relay.c | 2 +- src/core/or/relay.h | 3 ++ src/test/test_sendme.c | 79 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/core/or/relay.c b/src/core/or/relay.c index c48147dff8..9f90a09699 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -2055,7 +2055,7 @@ circuit_reset_sendme_randomness(circuit_t *circ) * Helper. Return the number of bytes that should be put into a cell from a * given edge connection on which n_available bytes are available. */ -static size_t +STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available, int package_partial, circuit_t *on_circuit) diff --git a/src/core/or/relay.h b/src/core/or/relay.h index 0fc308f7df..79036f97bd 100644 --- a/src/core/or/relay.h +++ b/src/core/or/relay.h @@ -123,6 +123,9 @@ STATIC int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint); STATIC size_t get_pad_cell_offset(size_t payload_len); +STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available, + int package_partial, + circuit_t *on_circuit); #endif /* defined(RELAY_PRIVATE) */ diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c index fa5ae115ac..eb402232bc 100644 --- a/src/test/test_sendme.c +++ b/src/test/test_sendme.c @@ -270,6 +270,84 @@ test_cell_version_validation(void *arg) ; } +/* check our decisions about how much stuff to put into relay cells. */ +static void +test_package_payload_len(void *arg) +{ + (void)arg; + /* this is not a real circuit: it only has the fields needed for this + * test. */ + circuit_t *c = tor_malloc_zero(sizeof(circuit_t)); + + /* check initial conditions. */ + circuit_reset_sendme_randomness(c); + tt_assert(! c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_GE, CIRCWINDOW_INCREMENT / 2); + tt_int_op(c->send_randomness_after_n_cells, OP_LT, CIRCWINDOW_INCREMENT); + + /* We have a bunch of cells before we need to send randomness, so the first + * few can be packaged full. */ + int initial = c->send_randomness_after_n_cells; + size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c); + tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); + n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c); + tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); + tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2); + + /* If package_partial isn't set, we won't package a partially full cell at + * all. */ + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0, c); + tt_int_op(n, OP_EQ, 0); + /* no change in our state, since nothing was sent. */ + tt_assert(! c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2); + + /* If package_partial is set and the partial cell is not going to have + * _enough_ randomness, we package it, but we don't consider ourselves to + * have sent a sufficiently random cell. */ + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1, c); + tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-1); + tt_assert(! c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 3); + + /* Make sure we set have_set_sufficiently_random_cell as appropriate. */ + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1, c); + tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-64); + tt_assert(c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 4); + + /* Now let's look at what happens when we get down to zero. Since we have + * sent a sufficiently random cell, we will not force this one to have a gap. + */ + c->send_randomness_after_n_cells = 0; + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE); + /* Now these will be reset. */ + tt_assert(! c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_GE, + CIRCWINDOW_INCREMENT / 2 - 1); + + /* What would happen if we hadn't sent a sufficiently random cell? */ + c->send_randomness_after_n_cells = 0; + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + const size_t reduced_payload_size = RELAY_PAYLOAD_SIZE - 4 - 16; + tt_int_op(n, OP_EQ, reduced_payload_size); + /* Now these will be reset. */ + tt_assert(! c->have_sent_sufficiently_random_cell); + tt_int_op(c->send_randomness_after_n_cells, OP_GE, + CIRCWINDOW_INCREMENT / 2 - 1); + + /* Here is a fun case: if it's time to package a small cell, then + * package_partial==0 should mean we accept that many bytes. + */ + c->send_randomness_after_n_cells = 0; + n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0, c); + tt_int_op(n, OP_EQ, reduced_payload_size); + + done: + tor_free(c); +} + struct testcase_t sendme_tests[] = { { "v1_record_digest", test_v1_record_digest, TT_FORK, NULL, NULL }, @@ -281,6 +359,7 @@ struct testcase_t sendme_tests[] = { NULL, NULL }, { "cell_version_validation", test_cell_version_validation, TT_FORK, NULL, NULL }, + { "package_payload_len", test_package_payload_len, 0, NULL, NULL }, END_OF_TESTCASES };