diff --git a/include/haproxy/quic_conn-t.h b/include/haproxy/quic_conn-t.h index 2d459241c..94b1b1b1e 100644 --- a/include/haproxy/quic_conn-t.h +++ b/include/haproxy/quic_conn-t.h @@ -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 */ diff --git a/src/quic_conn.c b/src/quic_conn.c index 4b8ac5bc2..d5ee3b1fc 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -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 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 . 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); } diff --git a/src/quic_loss.c b/src/quic_loss.c index 737119ade..c44515c67 100644 --- a/src/quic_loss.c +++ b/src/quic_loss.c @@ -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)) diff --git a/src/quic_sock.c b/src/quic_sock.c index c01653b8a..66083ec51 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -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;