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.
diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h
index 2d45924..94b1b1b 100644
--- a/include/haproxy/quic_conn-t.h
+++ b/include/haproxy/quic_conn-t.h
@@ -600,6 +600,23 @@
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 @@
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 */
diff --git a/src/quic_conn.c b/src/quic_conn.c
index 4b8ac5b..d5ee3b1 100644
--- a/src/quic_conn.c
+++ b/src/quic_conn.c
@@ -3259,16 +3259,16 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
diff --git a/src/quic_loss.c b/src/quic_loss.c
index 737119a..c44515c 100644
--- a/src/quic_loss.c
+++ b/src/quic_loss.c
@@ -190,7 +190,6 @@
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))
diff --git a/src/quic_sock.c b/src/quic_sock.c
index c01653b..66083ec 100644
--- a/src/quic_sock.c
+++ b/src/quic_sock.c
@@ -631,17 +631,12 @@
} 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 @@
}
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;