MINOR: quic_stats: Add transport new counters (lost, stateless reset, drop)

Add new counters to count the number of dropped packet upon parsing error, lost
sent packets and the number of stateless reset packet sent.
Take the oppportunity of this patch to rename CONN_OPENINGS to QUIC_ST_HALF_OPEN_CONN
(total number of half open connections) and QUIC_ST_HDSHK_FAILS to QUIC_ST_HDSHK_FAIL.
This commit is contained in:
Frédéric Lécaille 2022-05-24 16:01:39 +02:00 committed by Amaury Denoyelle
parent 91a211fb08
commit eb79145f01
5 changed files with 52 additions and 27 deletions

View File

@ -9,13 +9,16 @@
extern struct stats_module quic_stats_module;
enum {
QUIC_ST_DROPPED_PACKETS,
QUIC_ST_DROPPED_PACKET,
QUIC_ST_DROPPED_PARSING,
QUIC_ST_LOST_PACKET,
QUIC_ST_TOO_SHORT_INITIAL_DGRAM,
QUIC_ST_RETRY_SENT,
QUIC_ST_RETRY_VALIDATED,
QUIC_ST_RETRY_ERRORS,
QUIC_ST_CONN_OPENINGS,
QUIC_ST_HDSHK_FAILS,
QUIC_ST_HALF_OPEN_CONN,
QUIC_ST_HDSHK_FAIL,
QUIC_ST_STATELESS_RESET_SENT,
/* Transport errors */
QUIC_ST_TRANSP_ERR_NO_ERROR,
QUIC_ST_TRANSP_ERR_INTERNAL_ERROR,
@ -46,12 +49,15 @@ enum {
struct quic_counters {
long long dropped_pkt; /* total number of dropped packets */
long long dropped_parsing; /* total number of dropped packets upon parsing errors */
long long lost_pkt; /* total number of lost packets */
long long too_short_initial_dgram; /* total number of too short datagrams with Initial packets */
long long retry_sent; /* total number of Retry sent */
long long retry_validated; /* total number of validated Retry tokens */
long long retry_error; /* total number of Retry token errors */
long long conn_opening; /* total number of connection openings */
long long half_open_conn; /* total number of half open connections */
long long hdshk_fail; /* total number of handshake failures */
long long stateless_reset_sent; /* total number of handshake failures */
/* Transport errors */
long long quic_transp_err_no_error; /* total number of NO_ERROR connection errors */
long long quic_transp_err_internal_error; /* total number of INTERNAL_ERROR connection errors */

View File

@ -36,6 +36,7 @@
#include <haproxy/quic_cc-t.h>
#include <haproxy/quic_frame-t.h>
#include <haproxy/quic_loss-t.h>
#include <haproxy/quic_stats-t.h>
#include <haproxy/quic_tls-t.h>
#include <haproxy/quic_tp-t.h>
#include <haproxy/task.h>

View File

@ -1,7 +1,9 @@
#include <import/eb64tree.h>
#include <haproxy/quic_loss.h>
#include <haproxy/xprt_quic-t.h>
#include <haproxy/atomic.h>
#include <haproxy/ticks.h>
#include <haproxy/trace.h>
@ -175,6 +177,7 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
(int64_t)largest_acked_pn >= pkt->pn_node.key + QUIC_LOSS_PACKET_THRESHOLD) {
eb64_delete(&pkt->pn_node);
LIST_APPEND(lost_pkts, &pkt->list);
HA_ATOMIC_INC(&qc->prx_counters->lost_pkt);
}
else {
if (tick_isset(pktns->tx.loss_time))

View File

@ -2,8 +2,12 @@
#include <haproxy/stats.h>
static struct name_desc quic_stats[] = {
[QUIC_ST_DROPPED_PACKETS] = { .name = "quic_dropped_pkt",
[QUIC_ST_DROPPED_PACKET] = { .name = "quic_dropped_pkt",
.desc = "Total number of dropped packets" },
[QUIC_ST_DROPPED_PARSING] = { .name = "quic_dropped_parsing_pkt",
.desc = "Total number of dropped packets upon parsing error" },
[QUIC_ST_LOST_PACKET] = { .name = "quic_lost_pkt",
.desc = "Total number of lost sent packets" },
[QUIC_ST_TOO_SHORT_INITIAL_DGRAM] = { .name = "quic_too_short_dgram",
.desc = "Total number of too short dgrams with Initial packets" },
[QUIC_ST_RETRY_SENT] = { .name = "quic_retry_sent",
@ -12,10 +16,12 @@ static struct name_desc quic_stats[] = {
.desc = "Total number of validated Retry tokens" },
[QUIC_ST_RETRY_ERRORS] = { .name = "quic_retry_error",
.desc = "Total number of Retry tokens errors" },
[QUIC_ST_CONN_OPENINGS] = { .name = "quic_conn_opening",
.desc = "Total number of connection openings" },
[QUIC_ST_HDSHK_FAILS] = { .name = "quic_hdshk_fail",
[QUIC_ST_HALF_OPEN_CONN] = { .name = "quic_half_open_conn",
.desc = "Total number of half open connections" },
[QUIC_ST_HDSHK_FAIL] = { .name = "quic_hdshk_fail",
.desc = "Total number of handshake failures" },
[QUIC_ST_STATELESS_RESET_SENT] = { .name = "quic_stless_rst_sent",
.desc = "Total number of stateless reset packet sent" },
/* Transport errors */
[QUIC_ST_TRANSP_ERR_NO_ERROR] = { .name = "quic_transp_err_no_error",
.desc = "Total number of NO_ERROR errors received" },
@ -57,13 +63,13 @@ static struct name_desc quic_stats[] = {
.desc = "Total number of UNKNOWN_ERROR errors received" },
/* Streams related counters */
[QUIC_ST_DATA_BLOCKED] = { .name = "quic_data_blocked",
.desc = "Total number of times DATA_BLOCKED frame was received" },
.desc = "Total number of received DATA_BLOCKED frames" },
[QUIC_ST_STREAM_DATA_BLOCKED] = { .name = "quic_stream_data_blocked",
.desc = "Total number of times STREAMS_BLOCKED frame was received" },
.desc = "Total number of received STREAMS_BLOCKED frames" },
[QUIC_ST_STREAMS_DATA_BLOCKED_BIDI] = { .name = "quic_streams_data_blocked_bidi",
.desc = "Total number of times STREAM_DATA_BLOCKED_BIDI frame was received" },
.desc = "Total number of received STREAM_DATA_BLOCKED_BIDI frames" },
[QUIC_ST_STREAMS_DATA_BLOCKED_UNI] = { .name = "quic_streams_data_blocked_bidi",
.desc = "Total number of times STREAM_DATA_BLOCKED_UNI frame was received" },
.desc = "Total number of received STREAM_DATA_BLOCKED_UNI frames" },
};
struct quic_counters quic_counters;
@ -72,13 +78,16 @@ static void quic_fill_stats(void *data, struct field *stats)
{
struct quic_counters *counters = data;
stats[QUIC_ST_DROPPED_PACKETS] = mkf_u64(FN_COUNTER, counters->dropped_pkt);
stats[QUIC_ST_DROPPED_PACKET] = mkf_u64(FN_COUNTER, counters->dropped_pkt);
stats[QUIC_ST_DROPPED_PARSING] = mkf_u64(FN_COUNTER, counters->dropped_parsing);
stats[QUIC_ST_LOST_PACKET] = mkf_u64(FN_COUNTER, counters->lost_pkt);
stats[QUIC_ST_TOO_SHORT_INITIAL_DGRAM] = mkf_u64(FN_COUNTER, counters->too_short_initial_dgram);
stats[QUIC_ST_RETRY_SENT] = mkf_u64(FN_COUNTER, counters->retry_sent);
stats[QUIC_ST_RETRY_VALIDATED] = mkf_u64(FN_COUNTER, counters->retry_validated);
stats[QUIC_ST_RETRY_ERRORS] = mkf_u64(FN_COUNTER, counters->retry_error);
stats[QUIC_ST_CONN_OPENINGS] = mkf_u64(FN_GAUGE, counters->conn_opening);
stats[QUIC_ST_HDSHK_FAILS] = mkf_u64(FN_COUNTER, counters->hdshk_fail);
stats[QUIC_ST_HALF_OPEN_CONN] = mkf_u64(FN_GAUGE, counters->half_open_conn);
stats[QUIC_ST_HDSHK_FAIL] = mkf_u64(FN_COUNTER, counters->hdshk_fail);
stats[QUIC_ST_STATELESS_RESET_SENT] = mkf_u64(FN_COUNTER, counters->stateless_reset_sent);
/* Transport errors */
stats[QUIC_ST_TRANSP_ERR_NO_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_no_error);
stats[QUIC_ST_TRANSP_ERR_INTERNAL_ERROR] = mkf_u64(FN_COUNTER, counters->quic_transp_err_internal_error);

View File

@ -1120,7 +1120,7 @@ void quic_set_connection_close(struct quic_conn *qc, int err, int app)
/* Set <alert> TLS alert as QUIC CRYPTO_ERROR error */
void quic_set_tls_alert(struct quic_conn *qc, int alert)
{
HA_ATOMIC_DEC(&qc->prx_counters->conn_opening);
HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
quic_set_connection_close(qc, QC_ERR_CRYPTO_ERROR | alert, 0);
qc->flags |= QUIC_FL_CONN_TLS_ALERT;
TRACE_PROTO("Alert set", QUIC_EV_CONN_SSLDATA, qc);
@ -2109,7 +2109,7 @@ static inline int qc_provide_cdata(struct quic_enc_level *el,
}
HA_ATOMIC_INC(&qc->prx_counters->hdshk_fail);
HA_ATOMIC_DEC(&qc->prx_counters->conn_opening);
HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
TRACE_DEVEL("SSL handshake error",
QUIC_EV_CONN_IO_CB, qc, &state, &ssl_err);
qc_ssl_dump_errors(ctx->conn);
@ -2126,7 +2126,7 @@ static inline int qc_provide_cdata(struct quic_enc_level *el,
goto err;
}
HA_ATOMIC_DEC(&qc->prx_counters->conn_opening);
HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
/* I/O callback switch */
ctx->wait_event.tasklet->process = quic_conn_app_io_cb;
if (qc_is_listener(ctx->qc)) {
@ -2564,12 +2564,12 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
qc_cc_err_count_inc(qc->prx_counters, frm.type, frm.connection_close.error_code);
if (!(qc->flags & QUIC_FL_CONN_DRAINING)) {
/* If the connection did not reached the handshake complete state,
* the <conn_opening> counter was not decremented. Note that if
* the <half_open_conn> counter was not decremented. Note that if
* a TLS alert was received from the TLS stack, this counter
* has already been decremented.
*/
if (qc->state < QUIC_HS_ST_COMPLETE && !(qc->flags & QUIC_FL_CONN_TLS_ALERT))
HA_ATOMIC_DEC(&qc->prx_counters->conn_opening);
HA_ATOMIC_DEC(&qc->prx_counters->half_open_conn);
TRACE_PROTO("Entering draining state", QUIC_EV_CONN_PRSHPKT, qc);
/* RFC 9000 10.2. Immediate Close:
* The closing and draining connection states exist to ensure
@ -3559,6 +3559,7 @@ int qc_treat_rx_pkts(struct quic_enc_level *cur_el, struct quic_enc_level *next_
/* Drop the packet */
TRACE_PROTO("packet parsing failed -> dropped",
QUIC_EV_CONN_ELRXPKTS, ctx->qc, pkt);
HA_ATOMIC_INC(&qc->prx_counters->dropped_parsing);
}
else {
struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
@ -4466,12 +4467,12 @@ static struct task *qc_idle_timer_task(struct task *t, void *ctx, unsigned int s
*/
/* If the connection did not reached the handshake complete state,
* the <conn_opening> counter was not decremented. Note that if
* the <half_open_conn> counter was not decremented. Note that if
* a TLS alert was received from the TLS stack, this counter
* has already been decremented.
*/
if (qc_state < QUIC_HS_ST_COMPLETE && !(qc_flags & QUIC_FL_CONN_TLS_ALERT))
HA_ATOMIC_DEC(&prx_counters->conn_opening);
HA_ATOMIC_DEC(&prx_counters->half_open_conn);
return NULL;
}
@ -4721,13 +4722,17 @@ static int send_version_negotiation(int fd, struct sockaddr_storage *addr,
* from <fd> UDP socket to <dst>
* Return 1 if succeeded, 0 if not.
*/
static int send_stateless_reset(int fd, struct sockaddr_storage *dstaddr,
static int send_stateless_reset(struct listener *l, struct sockaddr_storage *dstaddr,
struct quic_rx_packet *rxpkt)
{
int pktlen, rndlen;
unsigned char pkt[64];
const socklen_t addrlen = get_addr_len(dstaddr);
struct proxy *prx;
struct quic_counters *prx_counters;
prx = l->bind_conf->frontend;
prx_counters = EXTRA_COUNTERS_GET(prx->extra_counters_fe, &quic_stats_module);
/* 10.3 Stateless Reset (https://www.rfc-editor.org/rfc/rfc9000.html#section-10.3)
* The resulting minimum size of 21 bytes does not guarantee that a Stateless
* Reset is difficult to distinguish from other packets if the recipient requires
@ -4755,9 +4760,10 @@ static int send_stateless_reset(int fd, struct sockaddr_storage *dstaddr,
rxpkt->dcid.data, rxpkt->dcid.len))
return 0;
if (sendto(fd, pkt, pktlen, 0, (struct sockaddr *)dstaddr, addrlen) < 0)
if (sendto(l->rx.fd, pkt, pktlen, 0, (struct sockaddr *)dstaddr, addrlen) < 0)
return 0;
HA_ATOMIC_INC(&prx_counters->stateless_reset_sent);
TRACE_PROTO("stateless reset sent", QUIC_EV_STATELESS_RST, NULL, &rxpkt->dcid);
return 1;
}
@ -5328,7 +5334,7 @@ static void qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
}
if (global.cluster_secret && !pkt->token_len && !(l->bind_conf->options & BC_O_QUIC_FORCE_RETRY) &&
HA_ATOMIC_LOAD(&prx_counters->conn_opening) >= global.tune.quic_retry_threshold) {
HA_ATOMIC_LOAD(&prx_counters->half_open_conn) >= global.tune.quic_retry_threshold) {
TRACE_PROTO("Initial without token, sending retry", QUIC_EV_CONN_LPKT);
if (send_retry(l->rx.fd, &dgram->saddr, pkt)) {
TRACE_PROTO("Error during Retry generation", QUIC_EV_CONN_LPKT);
@ -5357,7 +5363,7 @@ static void qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
if (qc == NULL)
goto drop;
HA_ATOMIC_INC(&prx_counters->conn_opening);
HA_ATOMIC_INC(&prx_counters->half_open_conn);
/* Insert the DCID the QUIC client has chosen (only for listeners) */
n = ebmb_insert(&quic_dghdlrs[tid].odcids, &qc->odcid_node,
qc->odcid.len + qc->odcid.addrlen);
@ -5414,7 +5420,7 @@ static void qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
if (!qc) {
size_t pktlen = end - buf;
TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT, NULL, pkt, &pktlen);
if (global.cluster_secret && !send_stateless_reset(l->rx.fd, &dgram->saddr, pkt))
if (global.cluster_secret && !send_stateless_reset(l, &dgram->saddr, pkt))
TRACE_PROTO("stateless reset not sent", QUIC_EV_CONN_LPKT, qc);
goto drop;
}