diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index 5e7a3ac9c8..e4422c86a8 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -24,6 +24,7 @@ #include "feature/hs/hs_circuitmap.h" #include "feature/hs/hs_client.h" #include "feature/hs/hs_ident.h" +#include "feature/hs/hs_metrics.h" #include "feature/hs/hs_service.h" #include "feature/nodelist/describe.h" #include "feature/nodelist/nodelist.h" @@ -429,6 +430,9 @@ launch_rendezvous_point_circuit,(const hs_service_t *service, safe_str_client(service->onion_address)); goto end; } + /* Update metrics with this new rendezvous circuit launched. */ + hs_metrics_new_rdv(&service->keys.identity_pk); + log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s " "for %s service %s", safe_str_client(extend_info_describe(info)), @@ -1312,6 +1316,12 @@ hs_circ_cleanup_on_close(circuit_t *circ) cleanup_on_close_client_circ(circ); } + if (circuit_purpose_is_hs_service(circ->purpose)) { + if (circuit_is_hs_v3(circ)) { + hs_service_circuit_cleanup_on_close(circ); + } + } + /* On close, we simply remove it from the circuit map. It can not be used * anymore. We keep this code path fast and lean. */ diff --git a/src/feature/hs/hs_metrics.h b/src/feature/hs/hs_metrics.h index 76eb68a2b1..21af42e01c 100644 --- a/src/feature/hs/hs_metrics.h +++ b/src/feature/hs/hs_metrics.h @@ -43,4 +43,18 @@ void hs_metrics_update_by_service(const hs_metrics_key_t key, #define hs_metrics_app_read_bytes(i, port, n) \ hs_metrics_update_by_ident(HS_METRICS_APP_READ_BYTES, (i), (port), (n)) +/** Newly established rendezvous. This is called as soon as the circuit purpose + * is REND_JOINED which is when the RENDEZVOUS2 cell is sent. */ +#define hs_metrics_new_established_rdv(s) \ + hs_metrics_update_by_service(HS_METRICS_NUM_ESTABLISHED_RDV, (s), 0, 1) + +/** Established rendezvous closed. This is called when the circuit in + * REND_JOINED state is marked for close. */ +#define hs_metrics_close_established_rdv(i) \ + hs_metrics_update_by_ident(HS_METRICS_NUM_ESTABLISHED_RDV, (i), 0, -1) + +/** New rendezvous circuit being launched. */ +#define hs_metrics_new_rdv(i) \ + hs_metrics_update_by_ident(HS_METRICS_NUM_RDV, (i), 0, 1) + #endif /* !defined(TOR_FEATURE_HS_HS_METRICS_H) */ diff --git a/src/feature/hs/hs_metrics_entry.c b/src/feature/hs/hs_metrics_entry.c index 6d0a143503..78f5253327 100644 --- a/src/feature/hs/hs_metrics_entry.c +++ b/src/feature/hs/hs_metrics_entry.c @@ -41,6 +41,18 @@ const hs_metrics_entry_t base_metrics[] = .help = "Total number of bytes read from the application", .port_as_label = true, }, + { + .key = HS_METRICS_NUM_ESTABLISHED_RDV, + .type = METRICS_TYPE_GAUGE, + .name = "hs_rdv_established_count", + .help = "Total number of established rendezvous circuit", + }, + { + .key = HS_METRICS_NUM_RDV, + .type = METRICS_TYPE_COUNTER, + .name = "hs_rdv_num_total", + .help = "Total number of rendezvous circuit created", + }, }; /** Size of base_metrics array that is number of entries. */ diff --git a/src/feature/hs/hs_metrics_entry.h b/src/feature/hs/hs_metrics_entry.h index e4b999fc46..924696df4f 100644 --- a/src/feature/hs/hs_metrics_entry.h +++ b/src/feature/hs/hs_metrics_entry.h @@ -21,6 +21,10 @@ typedef enum { HS_METRICS_APP_WRITE_BYTES = 1, /** Number of bytes read from application to onion service. */ HS_METRICS_APP_READ_BYTES = 2, + /** Number of established rendezsvous. */ + HS_METRICS_NUM_ESTABLISHED_RDV = 3, + /** Number of rendezsvous circuits created. */ + HS_METRICS_NUM_RDV = 4, } hs_metrics_key_t; /** The metadata of an HS metrics. */ diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index 1ccd3e4435..6cf5257eb9 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -3391,6 +3391,15 @@ service_rendezvous_circ_has_opened(origin_circuit_t *circ) /* If the cell can't be sent, the circuit will be closed within this * function. */ hs_circ_service_rp_has_opened(service, circ); + + /* Update metrics that we have an established rendezvous circuit. It is not + * entirely true until the client receives the RENDEZVOUS2 cell and starts + * sending but if that circuit collapes, we'll decrement the counter thus it + * will even out the metric. */ + if (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) { + hs_metrics_new_established_rdv(service); + } + goto done; err: @@ -3579,6 +3588,26 @@ service_encode_descriptor(const hs_service_t *service, /* Public API */ /* ========== */ +/** Called when a circuit was just cleaned up. This is done right before the + * circuit is marked for close. */ +void +hs_service_circuit_cleanup_on_close(const circuit_t *circ) +{ + tor_assert(circ); + tor_assert(CIRCUIT_IS_ORIGIN(circ)); + + switch (circ->purpose) { + case CIRCUIT_PURPOSE_S_REND_JOINED: + /* About to close an established rendezvous circuit. Update the metrics to + * reflect how many we have at the moment. */ + hs_metrics_close_established_rdv( + &CONST_TO_ORIGIN_CIRCUIT(circ)->hs_ident->identity_pk); + break; + default: + break; + } +} + /** This is called everytime the service map (v2 or v3) changes that is if an * element is added or removed. */ void diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h index 136ff744db..974f46b960 100644 --- a/src/feature/hs/hs_service.h +++ b/src/feature/hs/hs_service.h @@ -386,6 +386,7 @@ hs_circuit_id_protocol_t hs_service_exports_circuit_id(const ed25519_public_key_t *pk); void hs_service_dump_stats(int severity); +void hs_service_circuit_cleanup_on_close(const circuit_t *circ); #ifdef HS_SERVICE_PRIVATE