[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [tor] 01/10: Added INTRO and REND metrics for relay.



This is an automated email from the git hooks/post-receive script.

dgoulet pushed a commit to branch main
in repository tor.

commit 36076d3c46afd02bb7072c9d2aa9c5196932f024
Author: friendly73 <friendly73@x.x>
AuthorDate: Sun Feb 19 16:17:50 2023 +0000

    Added INTRO and REND metrics for relay.
---
 src/feature/hs/hs_intropoint.c    |  17 +++++
 src/feature/relay/relay_metrics.c | 151 ++++++++++++++++++++++++++++++++++++++
 src/feature/relay/relay_metrics.h |  10 ++-
 src/feature/rend/rendmid.c        |  13 ++++
 src/feature/stats/rephist.c       |  53 +++++++++++++
 src/feature/stats/rephist.h       |  54 ++++++++++++++
 6 files changed, 297 insertions(+), 1 deletion(-)

diff --git a/src/feature/hs/hs_intropoint.c b/src/feature/hs/hs_intropoint.c
index 52bd0cd499..c60f91b884 100644
--- a/src/feature/hs/hs_intropoint.c
+++ b/src/feature/hs/hs_intropoint.c
@@ -419,6 +419,7 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
 
   /* Check that the circuit is in shape to become an intro point */
   if (!hs_intro_circuit_is_suitable_for_establish_intro(circ)) {
+    rep_hist_note_est_intro_action(EST_INTRO_UNSUITABLE_CIRCUIT);
     goto err;
   }
 
@@ -426,6 +427,7 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
   ssize_t parsing_result = trn_cell_establish_intro_parse(&parsed_cell,
                                                          request, request_len);
   if (parsing_result < 0) {
+    rep_hist_note_est_intro_action(EST_INTRO_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Rejecting %s ESTABLISH_INTRO cell.",
            parsing_result == -1 ? "invalid" : "truncated");
@@ -436,6 +438,7 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
                                         (uint8_t *) circ->rend_circ_nonce,
                                         sizeof(circ->rend_circ_nonce));
   if (cell_ok < 0) {
+    rep_hist_note_est_intro_action(EST_INTRO_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Failed to verify ESTABLISH_INTRO cell.");
     goto err;
@@ -444,9 +447,11 @@ handle_establish_intro(or_circuit_t *circ, const uint8_t *request,
   /* This cell is legit. Take the appropriate actions. */
   cell_ok = handle_verified_establish_intro_cell(circ, parsed_cell);
   if (cell_ok < 0) {
+    rep_hist_note_est_intro_action(EST_INTRO_CIRCUIT_DEAD);
     goto err;
   }
 
+  rep_hist_note_est_intro_action(EST_INTRO_SUCCESS);
   /* We are done! */
   retval = 0;
   goto done;
@@ -505,6 +510,7 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
   tor_assert(request);
 
   if (request_len == 0) {
+    rep_hist_note_est_intro_action(EST_INTRO_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Empty ESTABLISH_INTRO cell.");
     goto err;
   }
@@ -517,10 +523,12 @@ hs_intro_received_establish_intro(or_circuit_t *circ, const uint8_t *request,
     case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_LEGACY1:
       /* Likely version 2 onion service which is now obsolete. Avoid a
        * protocol warning considering they still exists on the network. */
+      rep_hist_note_est_intro_action(EST_INTRO_MALFORMED);
       goto err;
     case TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519:
       return handle_establish_intro(circ, request, request_len);
     default:
+      rep_hist_note_est_intro_action(EST_INTRO_MALFORMED);
       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
              "Unrecognized AUTH_KEY_TYPE %u.", first_byte);
       goto err;
@@ -644,6 +652,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
   ssize_t cell_size = trn_cell_introduce1_parse(&parsed_cell, request,
                                                request_len);
   if (cell_size < 0) {
+    rep_hist_note_intro1_action(INTRO1_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Rejecting %s INTRODUCE1 cell. Responding with NACK.",
            cell_size == -1 ? "invalid" : "truncated");
@@ -654,6 +663,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
 
   /* Once parsed validate the cell format. */
   if (validate_introduce1_parsed_cell(parsed_cell) < 0) {
+    rep_hist_note_intro1_action(INTRO1_MALFORMED);
     /* Inform client that the INTRODUCE1 has bad format. */
     status = TRUNNEL_HS_INTRO_ACK_STATUS_BAD_FORMAT;
     goto send_ack;
@@ -665,6 +675,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
     get_auth_key_from_cell(&auth_key, RELAY_COMMAND_INTRODUCE1, parsed_cell);
     service_circ = hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key);
     if (service_circ == NULL) {
+      rep_hist_note_intro1_action(INTRO1_UNKNOWN_SERVICE);
       char b64_key[ED25519_BASE64_LEN + 1];
       ed25519_public_to_base64(b64_key, &auth_key);
       log_info(LD_REND, "No intro circuit found for INTRODUCE1 cell "
@@ -680,6 +691,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
   /* Before sending, lets make sure this cell can be sent on the service
    * circuit asking the DoS defenses. */
   if (!hs_dos_can_send_intro2(service_circ)) {
+    rep_hist_note_intro1_action(INTRO1_RATE_LIMITED);
     char *msg;
     static ratelim_t rlimit = RATELIM_INIT(5 * 60);
     if ((msg = rate_limit_log(&rlimit, approx_time()))) {
@@ -696,6 +708,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
   if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(service_circ),
                                    RELAY_COMMAND_INTRODUCE2,
                                    (char *) request, request_len, NULL)) {
+    rep_hist_note_intro1_action(INTRO1_CIRCUIT_DEAD);
     log_warn(LD_PROTOCOL, "Unable to send INTRODUCE2 cell to the service.");
     /* Inform the client that we can't relay the cell. Use the unknown ID
      * status code since it means that we do not know the service. */
@@ -703,6 +716,7 @@ handle_introduce1(or_circuit_t *client_circ, const uint8_t *request,
     goto send_ack;
   }
 
+  rep_hist_note_intro1_action(INTRO1_SUCCESS);
   /* Success! Send an INTRODUCE_ACK success status onto the client circuit. */
   status = TRUNNEL_HS_INTRO_ACK_STATUS_SUCCESS;
   ret = 0;
@@ -733,6 +747,7 @@ circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
   }
 
   if (circ->already_received_introduce1) {
+    rep_hist_note_intro1_action(INTRO1_CIRCUIT_REUSED);
     log_fn(LOG_PROTOCOL_WARN, LD_REND,
            "Blocking multiple introductions on the same circuit. "
            "Someone might be trying to attack a hidden service through "
@@ -742,6 +757,7 @@ circuit_is_suitable_for_introduce1(const or_circuit_t *circ)
 
   /* Disallow single hop client circuit. */
   if (circ->p_chan && channel_is_client(circ->p_chan)) {
+    rep_hist_note_intro1_action(INTRO1_SINGLE_HOP);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Single hop client was rejected while trying to introduce. "
            "Closing circuit.");
@@ -763,6 +779,7 @@ hs_intro_received_introduce1(or_circuit_t *circ, const uint8_t *request,
 
   /* A cell that can't hold a DIGEST_LEN is invalid. */
   if (request_len < DIGEST_LEN) {
+    rep_hist_note_intro1_action(INTRO1_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Invalid INTRODUCE1 cell length.");
     goto err;
   }
diff --git a/src/feature/relay/relay_metrics.c b/src/feature/relay/relay_metrics.c
index 5309411804..a1cd855b3d 100644
--- a/src/feature/relay/relay_metrics.c
+++ b/src/feature/relay/relay_metrics.c
@@ -59,6 +59,11 @@ static void fill_tcp_exhaustion_values(void);
 static void fill_traffic_values(void);
 static void fill_signing_cert_expiry(void);
 
+static void fill_est_intro_cells(void);
+static void fill_est_rend_cells(void);
+static void fill_intro1_cells(void);
+static void fill_rend1_cells(void);
+
 /** The base metrics that is a static array of metrics added to the metrics
  * store.
  *
@@ -184,6 +189,34 @@ static const relay_metrics_entry_t base_metrics[] =
     .help = "Timestamp at which the current online keys will expire",
     .fill_fn = fill_signing_cert_expiry,
   },
+  {
+    .key = RELAY_METRICS_NUM_EST_REND,
+    .type = METRICS_TYPE_COUNTER,
+    .name = METRICS_NAME(relay_est_rend_total),
+    .help = "Total number of EST_REND cells we received",
+    .fill_fn = fill_est_rend_cells,
+  },
+  {
+    .key = RELAY_METRICS_NUM_EST_INTRO,
+    .type = METRICS_TYPE_COUNTER,
+    .name = METRICS_NAME(relay_est_intro_total),
+    .help = "Total number of EST_INTRO cells we received",
+    .fill_fn = fill_est_intro_cells,
+  },
+  {
+    .key = RELAY_METRICS_NUM_INTRO1_CELLS,
+    .type = METRICS_TYPE_COUNTER,
+    .name = METRICS_NAME(relay_intro1_total),
+    .help = "Total number of INTRO1 cells we received",
+    .fill_fn = fill_intro1_cells,
+  },
+  {
+    .key = RELAY_METRICS_NUM_REND1_CELLS,
+    .type = METRICS_TYPE_COUNTER,
+    .name = METRICS_NAME(relay_rend1_total),
+    .help = "Total number of REND1 cells we received",
+    .fill_fn = fill_rend1_cells,
+  },
 };
 static const size_t num_base_metrics = ARRAY_LENGTH(base_metrics);
 
@@ -1020,6 +1053,124 @@ fill_signing_cert_expiry(void)
   }
 }
 
+static void
+fill_est_intro_cells(void)
+{
+  metrics_store_entry_t *sentry;
+  const relay_metrics_entry_t *rentry =
+      &base_metrics[RELAY_METRICS_NUM_EST_INTRO];
+
+  static struct {
+    const char *name;
+    est_intro_action_t key;
+  } actions[] = {
+      {.name = "success", .key = EST_INTRO_SUCCESS},
+      {.name = "malformed", .key = EST_INTRO_MALFORMED},
+      {.name = "unsuitable_circuit", .key = EST_INTRO_UNSUITABLE_CIRCUIT},
+      {.name = "circuit_dead", .key = EST_INTRO_CIRCUIT_DEAD},
+  };
+  static const size_t num_actions = ARRAY_LENGTH(actions);
+
+  for (size_t i = 0; i < num_actions; ++i) {
+    sentry =
+        metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
+    metrics_store_entry_add_label(
+        sentry, metrics_format_label("action", actions[i].name));
+    metrics_store_entry_update(
+        sentry, (long)rep_hist_get_est_intro_action_count(actions[i].key));
+  }
+}
+
+static void
+fill_est_rend_cells(void)
+{
+  metrics_store_entry_t *sentry;
+  const relay_metrics_entry_t *rentry =
+      &base_metrics[RELAY_METRICS_NUM_EST_REND];
+
+  static struct {
+    const char *name;
+    est_rend_action_t key;
+  } actions[] = {
+      {.name = "success", .key = EST_REND_SUCCESS},
+      {.name = "unsuitable_circuit", .key = EST_REND_UNSUITABLE_CIRCUIT},
+      {.name = "single_hop", .key = EST_REND_SINGLE_HOP},
+      {.name = "malformed", .key = EST_REND_MALFORMED},
+      {.name = "duplicate_cookie", .key = EST_REND_DUPLICATE_COOKIE},
+      {.name = "circuit_dead", .key = EST_REND_CIRCUIT_DEAD},
+  };
+  static const size_t num_actions = ARRAY_LENGTH(actions);
+
+  for (size_t i = 0; i < num_actions; ++i) {
+    sentry =
+        metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
+    metrics_store_entry_add_label(
+        sentry, metrics_format_label("action", actions[i].name));
+    metrics_store_entry_update(
+        sentry, (long)rep_hist_get_est_rend_action_count(actions[i].key));
+  }
+}
+
+static void
+fill_intro1_cells(void)
+{
+  metrics_store_entry_t *sentry;
+  const relay_metrics_entry_t *rentry =
+      &base_metrics[RELAY_METRICS_NUM_INTRO1_CELLS];
+
+  static struct {
+    const char *name;
+    intro1_action_t key;
+  } actions[] = {
+      {.name = "success", .key = INTRO1_SUCCESS},
+      {.name = "circuit_dead", .key = INTRO1_CIRCUIT_DEAD},
+      {.name = "malformed", .key = INTRO1_MALFORMED},
+      {.name = "unknown_service", .key = INTRO1_UNKNOWN_SERVICE},
+      {.name = "rate_limited", .key = INTRO1_RATE_LIMITED},
+      {.name = "circuit_reused", .key = INTRO1_CIRCUIT_REUSED},
+      {.name = "single_hop", .key = INTRO1_SINGLE_HOP},
+  };
+  static const size_t num_actions = ARRAY_LENGTH(actions);
+
+  for (size_t i = 0; i < num_actions; ++i) {
+    sentry =
+        metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
+    metrics_store_entry_add_label(
+        sentry, metrics_format_label("action", actions[i].name));
+    metrics_store_entry_update(
+        sentry, (long)rep_hist_get_intro1_action_count(actions[i].key));
+  }
+}
+
+static void
+fill_rend1_cells(void)
+{
+  metrics_store_entry_t *sentry;
+  const relay_metrics_entry_t *rentry =
+      &base_metrics[RELAY_METRICS_NUM_REND1_CELLS];
+
+  static struct {
+    const char *name;
+    rend1_action_t key;
+  } actions[] = {
+      {.name = "success", .key = REND1_SUCCESS},
+      {.name = "unsuitable_circuit", .key = REND1_UNSUITABLE_CIRCUIT},
+      {.name = "malformed", .key = REND1_MALFORMED},
+      {.name = "unknown_service", .key = REND1_UNKNOWN_SERVICE},
+      {.name = "circuit_dead", .key = REND1_CIRCUIT_DEAD},
+  };
+  static const size_t num_actions = ARRAY_LENGTH(actions);
+
+  for (size_t i = 0; i < num_actions; ++i) {
+    sentry =
+        metrics_store_add(the_store, rentry->type, rentry->name, rentry->help);
+    metrics_store_entry_add_label(
+        sentry, metrics_format_label("action", actions[i].name));
+    metrics_store_entry_update(
+        sentry, (long)rep_hist_get_rend1_action_count(actions[i].key));
+  }
+}
+
 /** Reset the global store and fill it with all the metrics from base_metrics
  * and their associated values.
  *
diff --git a/src/feature/relay/relay_metrics.h b/src/feature/relay/relay_metrics.h
index 100815051b..a2a52737ff 100644
--- a/src/feature/relay/relay_metrics.h
+++ b/src/feature/relay/relay_metrics.h
@@ -48,7 +48,15 @@ typedef enum {
   /** Numer of circuits. */
   RELAY_METRICS_NUM_CIRCUITS,
   /** Timestamp at which the current online keys will expire. */
-  RELAY_METRICS_SIGNING_CERT_EXPIRY
+  RELAY_METRICS_SIGNING_CERT_EXPIRY,
+  /** Number of times we received an EST_REND cell */
+  RELAY_METRICS_NUM_EST_REND,
+  /** Number of times we received an EST_INTRO cell */
+  RELAY_METRICS_NUM_EST_INTRO,
+  /** Number of times we received an INTRO1 cell */
+  RELAY_METRICS_NUM_INTRO1_CELLS,
+  /** Number of times we received a REND1 cell */
+  RELAY_METRICS_NUM_REND1_CELLS,
 } relay_metrics_key_t;
 
 /** The metadata of a relay metric. */
diff --git a/src/feature/rend/rendmid.c b/src/feature/rend/rendmid.c
index 8f6a45dfef..b8336b4250 100644
--- a/src/feature/rend/rendmid.c
+++ b/src/feature/rend/rendmid.c
@@ -19,6 +19,7 @@
 #include "feature/hs/hs_circuitmap.h"
 #include "feature/hs/hs_dos.h"
 #include "feature/hs/hs_intropoint.h"
+#include "feature/stats/rephist.h"
 
 #include "core/or/or_circuit_st.h"
 
@@ -36,6 +37,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
            (unsigned)circ->p_circ_id);
 
   if (circ->base_.purpose != CIRCUIT_PURPOSE_OR) {
+    rep_hist_note_est_rend_action(EST_REND_UNSUITABLE_CIRCUIT);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Tried to establish rendezvous on non-OR circuit with purpose %s",
            circuit_purpose_to_string(circ->base_.purpose));
@@ -46,6 +48,7 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
    * attempt to establish rendezvous points directly to us. */
   if (channel_is_client(circ->p_chan) &&
       dos_should_refuse_single_hop_client()) {
+    rep_hist_note_est_rend_action(EST_REND_SINGLE_HOP);
     /* Note it down for the heartbeat log purposes. */
     dos_note_refuse_single_hop_client();
     /* Silent drop so the client has to time out before moving on. */
@@ -53,18 +56,21 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
   }
 
   if (circ->base_.n_chan) {
+    rep_hist_note_est_rend_action(EST_REND_UNSUITABLE_CIRCUIT);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
              "Tried to establish rendezvous on non-edge circuit");
     goto err;
   }
 
   if (request_len != REND_COOKIE_LEN) {
+    rep_hist_note_est_rend_action(EST_REND_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN,
            LD_PROTOCOL, "Invalid length on ESTABLISH_RENDEZVOUS.");
     goto err;
   }
 
   if (hs_circuitmap_get_rend_circ_relay_side(request)) {
+    rep_hist_note_est_rend_action(EST_REND_DUPLICATE_COOKIE);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Duplicate rendezvous cookie in ESTABLISH_RENDEZVOUS.");
     goto err;
@@ -74,11 +80,13 @@ rend_mid_establish_rendezvous(or_circuit_t *circ, const uint8_t *request,
   if (relay_send_command_from_edge(0,TO_CIRCUIT(circ),
                                    RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
                                    "", 0, NULL)<0) {
+    rep_hist_note_est_rend_action(EST_REND_CIRCUIT_DEAD);
     log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
     /* Stop right now, the circuit has been closed. */
     return -1;
   }
 
+  rep_hist_note_est_rend_action(EST_REND_SUCCESS);
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_REND_POINT_WAITING);
   hs_circuitmap_register_rend_circ_relay_side(circ, request);
 
@@ -108,6 +116,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
   int reason = END_CIRC_REASON_INTERNAL;
 
   if (circ->base_.purpose != CIRCUIT_PURPOSE_OR || circ->base_.n_chan) {
+    rep_hist_note_rend1_action(REND1_UNSUITABLE_CIRCUIT);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Tried to complete rendezvous on non-OR or non-edge circuit %u.",
            (unsigned)circ->p_circ_id);
@@ -116,6 +125,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
   }
 
   if (request_len < REND_COOKIE_LEN) {
+    rep_hist_note_rend1_action(REND1_MALFORMED);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
          "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %u.",
          (int)request_len, (unsigned)circ->p_circ_id);
@@ -135,6 +145,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
      * client gives up on a rendezvous circuit after sending INTRODUCE1, but
      * before the onion service sends the RENDEZVOUS1 cell.
      */
+    rep_hist_note_rend1_action(REND1_UNKNOWN_SERVICE);
     log_fn(LOG_DEBUG, LD_PROTOCOL,
          "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
          hexid);
@@ -155,6 +166,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
                                    RELAY_COMMAND_RENDEZVOUS2,
                                    (char*)(request+REND_COOKIE_LEN),
                                    request_len-REND_COOKIE_LEN, NULL)) {
+    rep_hist_note_rend1_action(REND1_CIRCUIT_DEAD);
     log_warn(LD_GENERAL,
              "Unable to send RENDEZVOUS2 cell to client on circuit %u.",
              (unsigned)rend_circ->p_circ_id);
@@ -162,6 +174,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request,
     return -1;
   }
 
+  rep_hist_note_rend1_action(REND1_SUCCESS);
   /* Join the circuits. */
   log_info(LD_REND,
            "Completing rendezvous: circuit %u joins circuit %u (cookie %s)",
diff --git a/src/feature/stats/rephist.c b/src/feature/stats/rephist.c
index 8f4f33151a..dbd753a233 100644
--- a/src/feature/stats/rephist.c
+++ b/src/feature/stats/rephist.c
@@ -3038,3 +3038,56 @@ rep_hist_get_hs_v3_stats(void)
   return hs_v3_stats;
 }
 #endif /* defined(TOR_UNIT_TESTS) */
+
+static uint64_t est_intro_actions[EST_INTRO_ACTION_COUNT] = {0};
+static uint64_t est_rend_actions[EST_REND_ACTION_COUNT] = {0};
+static uint64_t intro1_actions[INTRO1_ACTION_COUNT] = {0};
+static uint64_t rend1_actions[REND1_ACTION_COUNT] = {0};
+
+void
+rep_hist_note_est_intro_action(est_intro_action_t action)
+{
+  est_intro_actions[action]++;
+}
+
+uint64_t
+rep_hist_get_est_intro_action_count(est_intro_action_t action)
+{
+  return est_rend_actions[action];
+}
+
+void
+rep_hist_note_est_rend_action(est_rend_action_t action)
+{
+  est_rend_actions[action]++;
+}
+
+uint64_t
+rep_hist_get_est_rend_action_count(est_rend_action_t action)
+{
+  return est_rend_actions[action];
+}
+
+void
+rep_hist_note_intro1_action(intro1_action_t action)
+{
+  intro1_actions[action]++;
+}
+
+uint64_t
+rep_hist_get_intro1_action_count(intro1_action_t action)
+{
+  return intro1_actions[action];
+}
+
+void
+rep_hist_note_rend1_action(rend1_action_t action)
+{
+  rend1_actions[action]++;
+}
+
+uint64_t
+rep_hist_get_rend1_action_count(rend1_action_t action)
+{
+  return rend1_actions[action];
+}
diff --git a/src/feature/stats/rephist.h b/src/feature/stats/rephist.h
index fbfab4c451..99cd5c8172 100644
--- a/src/feature/stats/rephist.h
+++ b/src/feature/stats/rephist.h
@@ -200,3 +200,57 @@ const struct hs_v3_stats_t *rep_hist_get_hs_v3_stats(void);
 #endif /* defined(TOR_UNIT_TESTS) */
 
 #endif /* !defined(TOR_REPHIST_H) */
+
+typedef enum {
+  EST_INTRO_SUCCESS,
+  EST_INTRO_MALFORMED,
+  EST_INTRO_UNSUITABLE_CIRCUIT,
+  EST_INTRO_CIRCUIT_DEAD,
+
+  EST_INTRO_ACTION_COUNT
+} est_intro_action_t;
+
+void rep_hist_note_est_intro_action(est_intro_action_t);
+uint64_t rep_hist_get_est_intro_action_count(est_intro_action_t);
+
+typedef enum {
+  EST_REND_SUCCESS,
+  EST_REND_UNSUITABLE_CIRCUIT,
+  EST_REND_SINGLE_HOP,
+  EST_REND_MALFORMED,
+  EST_REND_DUPLICATE_COOKIE,
+  EST_REND_CIRCUIT_DEAD,
+
+  EST_REND_ACTION_COUNT
+} est_rend_action_t;
+
+void rep_hist_note_est_rend_action(est_rend_action_t);
+uint64_t rep_hist_get_est_rend_action_count(est_rend_action_t);
+
+typedef enum {
+  INTRO1_SUCCESS,
+  INTRO1_CIRCUIT_DEAD,
+  INTRO1_MALFORMED,
+  INTRO1_UNKNOWN_SERVICE,
+  INTRO1_RATE_LIMITED,
+  INTRO1_CIRCUIT_REUSED,
+  INTRO1_SINGLE_HOP,
+
+  INTRO1_ACTION_COUNT
+} intro1_action_t;
+
+void rep_hist_note_intro1_action(intro1_action_t);
+uint64_t rep_hist_get_intro1_action_count(intro1_action_t);
+
+typedef enum {
+  REND1_SUCCESS,
+  REND1_UNSUITABLE_CIRCUIT,
+  REND1_MALFORMED,
+  REND1_UNKNOWN_SERVICE,
+  REND1_CIRCUIT_DEAD,
+
+  REND1_ACTION_COUNT
+} rend1_action_t;
+
+void rep_hist_note_rend1_action(rend1_action_t);
+uint64_t rep_hist_get_rend1_action_count(rend1_action_t);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits