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
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 */
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 */
/* 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 };
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);
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.
*
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;
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;
}
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;
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;
}
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;
}
}
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);
}
} 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);
}
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;