]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Add some counters at QUIC connection level
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 24 May 2023 09:10:19 +0000 (11:10 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 24 May 2023 14:30:11 +0000 (16:30 +0200)
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.

include/haproxy/quic_conn-t.h
src/quic_conn.c
src/quic_loss.c
src/quic_sock.c

index 2d459241c33e9bd3dcb9d2083d6d349413245d7c..94b1b1b1e7bb06733e0a8e7da1745ca27d05a9a0 100644 (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 */
index 4b8ac5bc297c53fb111b7f954e909c13da56b8d7..d5ee3b1fc690beb15c4306ece1f0eb80dce1c26b 100644 (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);
 }
index 737119ade51bfeaedcd4321fd840ac9e48bd4110..c44515c67901a1f745411e72963a03d418afe0f7 100644 (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))
index c01653b8ad860687e25bbab7f2149468948cb4e4..66083ec513521a8cf0a601327b4907acbf9578ee 100644 (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;