aboutsummaryrefslogtreecommitdiff
path: root/src/core/or/command.c
diff options
context:
space:
mode:
authorMike Perry <mikeperry-git@torproject.org>2018-09-13 01:23:17 +0000
committerMike Perry <mikeperry-git@torproject.org>2018-09-13 17:45:45 +0000
commitefa20756701b3434fce29b41f7210bc33423d764 (patch)
tree6af0f09aedc1b4e8e760ef03529215866af65abe /src/core/or/command.c
parent80ffedd3ca78e76e706ef2ac3f469a4fa4aa7a96 (diff)
downloadtor-efa20756701b3434fce29b41f7210bc33423d764.tar.gz
tor-efa20756701b3434fce29b41f7210bc33423d764.zip
Ticket #27678: Emit CIRC_BW events immediately for dropped cells.
We determine that a cell was dropped by inspecting CIRC_BW fields. If we did not update the delivered or overhead fields after processing the cell, the cell was dropped/not processed. Also emit CIRC_BW events for cases where we decide to close the circuit in this function, so vanguards can print messages about dropped cells in those cases, too.
Diffstat (limited to 'src/core/or/command.c')
-rw-r--r--src/core/or/command.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/core/or/command.c b/src/core/or/command.c
index 461e49b629..ebddc4a352 100644
--- a/src/core/or/command.c
+++ b/src/core/or/command.c
@@ -480,6 +480,8 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
const or_options_t *options = get_options();
circuit_t *circ;
int reason, direction;
+ uint32_t orig_delivered_bw = 0;
+ uint32_t orig_overhead_bw = 0;
circ = circuit_get_by_circid_channel(cell->circ_id, chan);
@@ -512,6 +514,15 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
/* Count the payload bytes only. We don't care about cell headers */
ocirc->n_read_circ_bw = tor_add_u32_nowrap(ocirc->n_read_circ_bw,
CELL_PAYLOAD_SIZE);
+
+ /* Stash the original delivered and overhead values. These values are
+ * updated by circuit_read_valid_data() during cell processing by
+ * connection_edge_process_relay_cell(), called from
+ * circuit_receive_relay_cell() below. If they do not change, we inform
+ * the control port about dropped cells immediately after the call
+ * to circuit_receive_relay_cell() below. */
+ orig_delivered_bw = ocirc->n_delivered_read_circ_bw;
+ orig_overhead_bw = ocirc->n_overhead_read_circ_bw;
}
if (!CIRCUIT_IS_ORIGIN(circ) &&
@@ -535,6 +546,8 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
(unsigned)cell->circ_id);
if (CIRCUIT_IS_ORIGIN(circ)) {
circuit_log_path(LOG_WARN, LD_OR, TO_ORIGIN_CIRCUIT(circ));
+ /* Always emit a bandwidth event for closed circs */
+ control_event_circ_bandwidth_used_for_circ(TO_ORIGIN_CIRCUIT(circ));
} else if (circ->n_chan) {
log_warn(LD_OR, " upstream=%s",
channel_get_actual_remote_descr(circ->n_chan));
@@ -560,9 +573,33 @@ command_process_relay_cell(cell_t *cell, channel_t *chan)
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
"(%s) failed. Closing.",
direction==CELL_DIRECTION_OUT?"forward":"backward");
+ /* Always emit a bandwidth event for closed circs */
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ control_event_circ_bandwidth_used_for_circ(TO_ORIGIN_CIRCUIT(circ));
+ }
circuit_mark_for_close(circ, -reason);
}
+ if (CIRCUIT_IS_ORIGIN(circ)) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+
+ /* If neither the delivered nor overhead values changed, this cell
+ * was dropped due to being invalid by one of the error codepaths in
+ * connection_edge_process_relay_cell(), called by
+ * circuit_receive_relay_cell().
+ *
+ * Valid cells, on the other hand, call circuit_read_valid_data()
+ * to update these values upon processing them.
+ *
+ * So, if the values are the same as those stored above,
+ * emit a control port event for CIRC_BW, so the controller can
+ * react quickly to invalid cells. */
+ if (orig_delivered_bw == ocirc->n_delivered_read_circ_bw &&
+ orig_overhead_bw == ocirc->n_overhead_read_circ_bw) {
+ control_event_circ_bandwidth_used_for_circ(ocirc);
+ }
+ }
+
/* If this is a cell in an RP circuit, count it as part of the
hidden service stats */
if (options->HiddenServiceStatistics &&