MINOR: quic: Add some counters at QUIC connection level

Add some statistical counters to quic_conn struct from quic_counters struct which
are used at listener level to handle them at QUIC connection level. This avoid
calling atomic functions. Furthermore this will be useful soon when a counter will
be added for the total number of packets which have been sent which will be very
often incremented.

Some counters were not added, espcially those which count the number of QUIC errors
by QUIC error types. Indeed such counters would be incremented most of the time
only one time at QUIC connection level.

Implement quic_conn_prx_cntrs_update() which accumulates the QUIC connection level
statistical counters to the listener level statistical counters.

Must be backported to 2.7.
This commit is contained in:
Frdric Lcaille 2023-05-24 11:10:19 +02:00 committed by Willy Tarreau
parent 464281af46
commit bdd64fd71d
4 changed files with 59 additions and 19 deletions

View File

@ -600,6 +600,23 @@ enum qc_mux_state {
QC_MUX_RELEASED, /* released, data can be dropped */
};
/* Counters at QUIC connection level */
struct quic_conn_cntrs {
long long dropped_pkt; /* total number of dropped packets */
long long dropped_pkt_bufoverrun;/* total number of dropped packets because of buffer overrun */
long long dropped_parsing; /* total number of dropped packets upon parsing errors */
long long socket_full; /* total number of EAGAIN errors on sendto() calls */
long long sendto_err; /* total number of errors on sendto() calls, EAGAIN excepted */
long long sendto_err_unknown; /* total number of errors on sendto() calls which are currently not supported */
long long lost_pkt; /* total number of lost packets */
long long conn_migration_done; /* total number of connection migration handled */
/* Streams related counters */
long long data_blocked; /* total number of times DATA_BLOCKED frame was received */
long long stream_data_blocked; /* total number of times STEAM_DATA_BLOCKED frame was received */
long long streams_data_blocked_bidi; /* total number of times STREAMS_DATA_BLOCKED_BIDI frame was received */
long long streams_data_blocked_uni; /* total number of times STREAMS_DATA_BLOCKED_UNI frame was received */
};
/* The number of buffers for outgoing packets (must be a power of two). */
#define QUIC_CONN_TX_BUFS_NB 8
@ -728,6 +745,9 @@ struct quic_conn {
unsigned int nb_pkt_since_cc;
const struct qcc_app_ops *app_ops;
/* QUIC connection level counters */
struct quic_conn_cntrs cntrs;
/* Proxy counters */
struct quic_counters *prx_counters;
struct list el_th_ctx; /* list elem in ha_thread_ctx */

View File

@ -3259,16 +3259,16 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt,
case QUIC_FT_MAX_STREAMS_UNI:
break;
case QUIC_FT_DATA_BLOCKED:
HA_ATOMIC_INC(&qc->prx_counters->data_blocked);
qc->cntrs.data_blocked++;
break;
case QUIC_FT_STREAM_DATA_BLOCKED:
HA_ATOMIC_INC(&qc->prx_counters->stream_data_blocked);
qc->cntrs.stream_data_blocked++;
break;
case QUIC_FT_STREAMS_BLOCKED_BIDI:
HA_ATOMIC_INC(&qc->prx_counters->streams_data_blocked_bidi);
qc->cntrs.streams_data_blocked_bidi++;
break;
case QUIC_FT_STREAMS_BLOCKED_UNI:
HA_ATOMIC_INC(&qc->prx_counters->streams_data_blocked_uni);
qc->cntrs.streams_data_blocked_uni++;
break;
case QUIC_FT_NEW_CONNECTION_ID:
/* XXX TO DO XXX */
@ -4605,7 +4605,7 @@ int qc_treat_rx_pkts(struct quic_conn *qc, struct quic_enc_level *cur_el,
/* Drop the packet */
TRACE_ERROR("packet parsing failed -> dropped",
QUIC_EV_CONN_RXPKT, qc, pkt);
HA_ATOMIC_INC(&qc->prx_counters->dropped_parsing);
qc->cntrs.dropped_parsing++;
}
else {
struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn };
@ -5702,6 +5702,9 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
if (!qc_new_isecs(qc, ictx,qc->original_version, dcid->data, dcid->len, 1))
goto err;
/* Counters initialization */
memset(&qc->cntrs, 0, sizeof qc->cntrs);
LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
@ -5719,6 +5722,25 @@ static struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
return NULL;
}
/* Update the proxy counters of <qc> QUIC connection from its counters */
static inline void quic_conn_prx_cntrs_update(struct quic_conn *qc)
{
BUG_ON(!qc->prx_counters);
HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt, qc->cntrs.dropped_pkt);
HA_ATOMIC_ADD(&qc->prx_counters->dropped_pkt_bufoverrun, qc->cntrs.dropped_pkt_bufoverrun);
HA_ATOMIC_ADD(&qc->prx_counters->dropped_parsing, qc->cntrs.dropped_parsing);
HA_ATOMIC_ADD(&qc->prx_counters->socket_full, qc->cntrs.socket_full);
HA_ATOMIC_ADD(&qc->prx_counters->sendto_err, qc->cntrs.sendto_err);
HA_ATOMIC_ADD(&qc->prx_counters->sendto_err_unknown, qc->cntrs.sendto_err_unknown);
HA_ATOMIC_ADD(&qc->prx_counters->lost_pkt, qc->path->loss.nb_lost_pkt);
HA_ATOMIC_ADD(&qc->prx_counters->conn_migration_done, qc->cntrs.conn_migration_done);
/* Stream related counters */
HA_ATOMIC_ADD(&qc->prx_counters->data_blocked, qc->cntrs.data_blocked);
HA_ATOMIC_ADD(&qc->prx_counters->stream_data_blocked, qc->cntrs.stream_data_blocked);
HA_ATOMIC_ADD(&qc->prx_counters->streams_data_blocked_bidi, qc->cntrs.streams_data_blocked_bidi);
HA_ATOMIC_ADD(&qc->prx_counters->streams_data_blocked_uni, qc->cntrs.streams_data_blocked_uni);
}
/* Release the quic_conn <qc>. The connection is removed from the CIDs tree.
* The connection tasklet is killed.
*
@ -5809,6 +5831,7 @@ void quic_conn_release(struct quic_conn *qc)
qc_detach_th_ctx_list(qc, 0);
quic_conn_prx_cntrs_update(qc);
pool_free(pool_head_quic_conn_rxbuf, qc->rx.buf.area);
pool_free(pool_head_quic_conn, qc);
qc = NULL;
@ -6923,7 +6946,10 @@ static struct quic_conn *quic_rx_pkt_retrieve_conn(struct quic_rx_packet *pkt,
return qc;
err:
HA_ATOMIC_INC(&prx_counters->dropped_pkt);
if (qc)
qc->cntrs.dropped_pkt++;
else
HA_ATOMIC_INC(&prx_counters->dropped_pkt);
TRACE_LEAVE(QUIC_EV_CONN_LPKT);
return NULL;
}
@ -7230,7 +7256,7 @@ static int qc_handle_conn_migration(struct quic_conn *qc,
qc->local_addr = *local_addr;
qc->peer_addr = *peer_addr;
HA_ATOMIC_INC(&qc->prx_counters->conn_migration_done);
qc->cntrs.conn_migration_done++;
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
return 0;
@ -7336,7 +7362,7 @@ static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt,
if (b_tail(&qc->rx.buf) + b_cspace < b_wrap(&qc->rx.buf)) {
TRACE_PROTO("Packet dropped",
QUIC_EV_CONN_LPKT, qc, NULL, NULL, qv);
HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt_bufoverrun);
qc->cntrs.dropped_pkt_bufoverrun++;
goto drop_silent;
}
@ -7349,7 +7375,7 @@ static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt,
if (b_contig_space(&qc->rx.buf) < pkt->len) {
TRACE_PROTO("Too big packet",
QUIC_EV_CONN_LPKT, qc, pkt, &pkt->len, qv);
HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt_bufoverrun);
qc->cntrs.dropped_pkt_bufoverrun++;
goto drop_silent;
}
}
@ -7372,7 +7398,7 @@ static void qc_rx_pkt_handle(struct quic_conn *qc, struct quic_rx_packet *pkt,
return;
drop:
HA_ATOMIC_INC(&qc->prx_counters->dropped_pkt);
qc->cntrs.dropped_pkt++;
TRACE_PROTO("packet drop", QUIC_EV_CONN_LPKT, qc, pkt, NULL, qv);
TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc);
}

View File

@ -190,7 +190,6 @@ void qc_packet_loss_lookup(struct quic_pktns *pktns, struct quic_conn *qc,
eb64_delete(&pkt->pn_node);
LIST_APPEND(lost_pkts, &pkt->list);
ql->nb_lost_pkt++;
HA_ATOMIC_INC(&qc->prx_counters->lost_pkt);
}
else {
if (tick_isset(pktns->tx.loss_time))

View File

@ -631,17 +631,12 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
struct proxy *prx = qc->li->bind_conf->frontend;
struct quic_counters *prx_counters =
EXTRA_COUNTERS_GET(prx->extra_counters_fe,
&quic_stats_module);
if (errno == EAGAIN || errno == EWOULDBLOCK ||
errno == ENOTCONN || errno == EINPROGRESS) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
HA_ATOMIC_INC(&prx_counters->socket_full);
qc->cntrs.socket_full++;
else
HA_ATOMIC_INC(&prx_counters->sendto_err);
qc->cntrs.sendto_err++;
/* transient error */
fd_want_send(qc->fd);
@ -652,7 +647,7 @@ int qc_snd_buf(struct quic_conn *qc, const struct buffer *buf, size_t sz,
}
else {
/* unrecoverable error */
HA_ATOMIC_INC(&prx_counters->sendto_err_unknown);
qc->cntrs.sendto_err_unknown++;
TRACE_PRINTF(TRACE_LEVEL_USER, QUIC_EV_CONN_SPPKTS, qc, 0, 0, 0,
"UDP send failure errno=%d (%s)", errno, strerror(errno));
return -1;