]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
REORG: mux-quic: extract traces in a dedicated source file
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 19 Sep 2022 14:12:38 +0000 (16:12 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 20 Sep 2022 13:35:09 +0000 (15:35 +0200)
QUIC MUX implements several APIs to interface with stream, quic-conn and
app-ops layers. It is planified to better separate this roles, possibly
by using several files.

The first step is to extract QUIC MUX traces in a dedicated source
files. This will allow to reuse traces in multiple files.

The main objective is to be
able to support both TCP and HTTP proxy mode with a common base and add
specialized modules on top of it.

This should be backported up to 2.6.

Makefile
include/haproxy/mux_quic.h
include/haproxy/qmux_trace.h [new file with mode: 0644]
src/mux_quic.c
src/qmux_trace.c [new file with mode: 0644]

index e798b534f6851c1a8f25373fc62fdcee2186abc8..08d080473c9b3cfe82e6570fdcfe4ef8f8b9e7c5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -646,7 +646,7 @@ OPTIONS_OBJS += src/quic_sock.o src/proto_quic.o src/xprt_quic.o src/quic_tls.o
                 src/cbuf.o src/qpack-dec.o src/qpack-tbl.o src/h3.o src/qpack-enc.o \
                 src/hq_interop.o src/cfgparse-quic.o src/quic_loss.o \
                 src/quic_tp.o src/quic_stream.o src/quic_stats.o src/h3_stats.o \
-                src/quic_cc_cubic.o
+                src/quic_cc_cubic.o src/qmux_trace.o
 endif
 
 ifneq ($(USE_LUA),)
index 892ae91302a5bfe07790ecd21201e04f2323c38b..7d3e47eed0ac3f830ff23d5d83d74f9b6e8876e6 100644 (file)
@@ -71,6 +71,18 @@ static inline int quic_stream_is_bidi(uint64_t id)
        return !quic_stream_is_uni(id);
 }
 
+static inline char *qcs_st_to_str(enum qcs_state st)
+{
+       switch (st) {
+       case QC_SS_IDLE: return "IDL";
+       case QC_SS_OPEN: return "OPN";
+       case QC_SS_HLOC: return "HCL";
+       case QC_SS_HREM: return "HCR";
+       case QC_SS_CLO:  return "CLO";
+       default:         return "???";
+       }
+}
+
 int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops);
 
 static inline struct stconn *qc_attach_sc(struct qcs *qcs, struct buffer *buf)
diff --git a/include/haproxy/qmux_trace.h b/include/haproxy/qmux_trace.h
new file mode 100644 (file)
index 0000000..c612c96
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef _HAPROXY_QMUX_TRACE_H
+#define _HAPROXY_QMUX_TRACE_H
+
+#ifdef USE_QUIC
+
+#include <haproxy/api-t.h>
+#include <haproxy/trace.h>
+
+extern struct trace_source trace_qmux;
+#define TRACE_SOURCE    &trace_qmux
+
+static const struct trace_event qmux_trace_events[] = {
+#define           QMUX_EV_QCC_NEW       (1ULL << 0)
+       { .mask = QMUX_EV_QCC_NEW ,     .name = "qcc_new",     .desc = "new QUIC connection" },
+#define           QMUX_EV_QCC_RECV      (1ULL << 1)
+       { .mask = QMUX_EV_QCC_RECV,     .name = "qcc_recv",     .desc = "Rx on QUIC connection" },
+#define           QMUX_EV_QCC_SEND      (1ULL << 2)
+       { .mask = QMUX_EV_QCC_SEND,     .name = "qcc_send",     .desc = "Tx on QUIC connection" },
+#define           QMUX_EV_QCC_WAKE      (1ULL << 3)
+       { .mask = QMUX_EV_QCC_WAKE,     .name = "qcc_wake",     .desc = "QUIC connection woken up" },
+#define           QMUX_EV_QCC_END       (1ULL << 4)
+       { .mask = QMUX_EV_QCC_END,      .name = "qcc_end",      .desc = "QUIC connection terminated" },
+#define           QMUX_EV_QCC_NQCS      (1ULL << 5)
+       { .mask = QMUX_EV_QCC_NQCS,     .name = "qcc_no_qcs",   .desc = "QUIC stream not found" },
+#define           QMUX_EV_QCS_NEW       (1ULL << 6)
+       { .mask = QMUX_EV_QCS_NEW,      .name = "qcs_new",      .desc = "new QUIC stream" },
+#define           QMUX_EV_QCS_RECV      (1ULL << 7)
+       { .mask = QMUX_EV_QCS_RECV,     .name = "qcs_recv",     .desc = "Rx on QUIC stream" },
+#define           QMUX_EV_QCS_SEND      (1ULL << 8)
+       { .mask = QMUX_EV_QCS_SEND,     .name = "qcs_send",     .desc = "Tx on QUIC stream" },
+#define           QMUX_EV_QCS_END       (1ULL << 9)
+       { .mask = QMUX_EV_QCS_END,      .name = "qcs_end",      .desc = "QUIC stream terminated" },
+#define           QMUX_EV_STRM_RECV     (1ULL << 10)
+       { .mask = QMUX_EV_STRM_RECV,    .name = "strm_recv",    .desc = "receiving data for stream" },
+#define           QMUX_EV_STRM_SEND     (1ULL << 11)
+       { .mask = QMUX_EV_STRM_SEND,    .name = "strm_send",    .desc = "sending data for stream" },
+#define           QMUX_EV_STRM_END      (1ULL << 12)
+       { .mask = QMUX_EV_STRM_END,     .name = "strm_end",     .desc = "detaching app-layer stream" },
+#define           QMUX_EV_SEND_FRM      (1ULL << 13)
+       { .mask = QMUX_EV_SEND_FRM,     .name = "send_frm",     .desc = "sending QUIC frame" },
+/* special event dedicated to qcs_xfer_data */
+#define           QMUX_EV_QCS_XFER_DATA  (1ULL << 14)
+       { .mask = QMUX_EV_QCS_XFER_DATA,  .name = "qcs_xfer_data", .desc = "qcs_xfer_data" },
+/* special event dedicated to qcs_build_stream_frm */
+#define           QMUX_EV_QCS_BUILD_STRM (1ULL << 15)
+       { .mask = QMUX_EV_QCS_BUILD_STRM, .name = "qcs_build_stream_frm", .desc = "qcs_build_stream_frm" },
+#define           QMUX_EV_PROTO_ERR     (1ULL << 16)
+       { .mask = QMUX_EV_PROTO_ERR,    .name = "proto_err",    .desc = "protocol error" },
+       { }
+};
+
+/* custom arg for QMUX_EV_QCS_XFER_DATA */
+struct qcs_xfer_data_trace_arg {
+       size_t prep;
+       int xfer;
+};
+
+/* custom arg for QMUX_EV_QCS_BUILD_STRM */
+struct qcs_build_stream_trace_arg {
+       size_t len;
+       char fin;
+       uint64_t offset;
+};
+
+#endif /* USE_QUIC */
+
+#endif /* _HAPROXY_QMUX_TRACE_H */
index 83672cb0b9dbf365ba0df256fa76d6b73f95e1ea..44f449a9f7322c28ff0041960cd08c759deba8c0 100644 (file)
@@ -9,6 +9,7 @@
 #include <haproxy/list.h>
 #include <haproxy/ncbuf.h>
 #include <haproxy/pool.h>
+#include <haproxy/qmux_trace.h>
 #include <haproxy/quic_stream.h>
 #include <haproxy/quic_tp-t.h>
 #include <haproxy/ssl_sock-t.h>
 DECLARE_POOL(pool_head_qcc, "qcc", sizeof(struct qcc));
 DECLARE_POOL(pool_head_qcs, "qcs", sizeof(struct qcs));
 
-/* trace source and events */
-static void qmux_trace(enum trace_level level, uint64_t mask,
-                       const struct trace_source *src,
-                       const struct ist where, const struct ist func,
-                       const void *a1, const void *a2, const void *a3, const void *a4);
-
-static const struct trace_event qmux_trace_events[] = {
-#define           QMUX_EV_QCC_NEW       (1ULL << 0)
-       { .mask = QMUX_EV_QCC_NEW ,     .name = "qcc_new",     .desc = "new QUIC connection" },
-#define           QMUX_EV_QCC_RECV      (1ULL << 1)
-       { .mask = QMUX_EV_QCC_RECV,     .name = "qcc_recv",     .desc = "Rx on QUIC connection" },
-#define           QMUX_EV_QCC_SEND      (1ULL << 2)
-       { .mask = QMUX_EV_QCC_SEND,     .name = "qcc_send",     .desc = "Tx on QUIC connection" },
-#define           QMUX_EV_QCC_WAKE      (1ULL << 3)
-       { .mask = QMUX_EV_QCC_WAKE,     .name = "qcc_wake",     .desc = "QUIC connection woken up" },
-#define           QMUX_EV_QCC_END       (1ULL << 4)
-       { .mask = QMUX_EV_QCC_END,      .name = "qcc_end",      .desc = "QUIC connection terminated" },
-#define           QMUX_EV_QCC_NQCS      (1ULL << 5)
-       { .mask = QMUX_EV_QCC_NQCS,     .name = "qcc_no_qcs",   .desc = "QUIC stream not found" },
-#define           QMUX_EV_QCS_NEW       (1ULL << 6)
-       { .mask = QMUX_EV_QCS_NEW,      .name = "qcs_new",      .desc = "new QUIC stream" },
-#define           QMUX_EV_QCS_RECV      (1ULL << 7)
-       { .mask = QMUX_EV_QCS_RECV,     .name = "qcs_recv",     .desc = "Rx on QUIC stream" },
-#define           QMUX_EV_QCS_SEND      (1ULL << 8)
-       { .mask = QMUX_EV_QCS_SEND,     .name = "qcs_send",     .desc = "Tx on QUIC stream" },
-#define           QMUX_EV_QCS_END       (1ULL << 9)
-       { .mask = QMUX_EV_QCS_END,      .name = "qcs_end",      .desc = "QUIC stream terminated" },
-#define           QMUX_EV_STRM_RECV     (1ULL << 10)
-       { .mask = QMUX_EV_STRM_RECV,    .name = "strm_recv",    .desc = "receiving data for stream" },
-#define           QMUX_EV_STRM_SEND     (1ULL << 11)
-       { .mask = QMUX_EV_STRM_SEND,    .name = "strm_send",    .desc = "sending data for stream" },
-#define           QMUX_EV_STRM_END      (1ULL << 12)
-       { .mask = QMUX_EV_STRM_END,     .name = "strm_end",     .desc = "detaching app-layer stream" },
-#define           QMUX_EV_SEND_FRM      (1ULL << 13)
-       { .mask = QMUX_EV_SEND_FRM,     .name = "send_frm",     .desc = "sending QUIC frame" },
-/* special event dedicated to qcs_xfer_data */
-#define           QMUX_EV_QCS_XFER_DATA  (1ULL << 14)
-       { .mask = QMUX_EV_QCS_XFER_DATA,  .name = "qcs_xfer_data", .desc = "qcs_xfer_data" },
-/* special event dedicated to qcs_build_stream_frm */
-#define           QMUX_EV_QCS_BUILD_STRM (1ULL << 15)
-       { .mask = QMUX_EV_QCS_BUILD_STRM, .name = "qcs_build_stream_frm", .desc = "qcs_build_stream_frm" },
-#define           QMUX_EV_PROTO_ERR     (1ULL << 16)
-       { .mask = QMUX_EV_PROTO_ERR,    .name = "proto_err",    .desc = "protocol error" },
-       { }
-};
-
-/* custom arg for QMUX_EV_QCS_XFER_DATA */
-struct qcs_xfer_data_trace_arg {
-       size_t prep;
-       int xfer;
-};
-/* custom arg for QMUX_EV_QCS_BUILD_STRM */
-struct qcs_build_stream_trace_arg {
-       size_t len;
-       char fin;
-       uint64_t offset;
-};
-
-static const struct name_desc qmux_trace_lockon_args[4] = {
-       /* arg1 */ { /* already used by the connection */ },
-       /* arg2 */ { .name="qcs", .desc="QUIC stream" },
-       /* arg3 */ { },
-       /* arg4 */ { }
-};
-
-static const struct name_desc qmux_trace_decoding[] = {
-#define QMUX_VERB_CLEAN    1
-       { .name="clean",    .desc="only user-friendly stuff, generally suitable for level \"user\"" },
-#define QMUX_VERB_MINIMAL  2
-       { .name="minimal",  .desc="report only qcc/qcs state and flags, no real decoding" },
-       { /* end */ }
-};
-
-struct trace_source trace_qmux = {
-       .name = IST("qmux"),
-       .desc = "QUIC multiplexer",
-       .arg_def = TRC_ARG1_CONN,  /* TRACE()'s first argument is always a connection */
-       .default_cb = qmux_trace,
-       .known_events = qmux_trace_events,
-       .lockon_args = qmux_trace_lockon_args,
-       .decoding = qmux_trace_decoding,
-       .report_events = ~0,  /* report everything by default */
-};
-
-#define TRACE_SOURCE    &trace_qmux
-INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
-
 /* Emit a CONNECTION_CLOSE with error <err>. This will interrupt all future
  * send/receive operations.
  */
@@ -2341,18 +2255,6 @@ static int qc_wake(struct connection *conn)
 }
 
 
-static char *qcs_st_to_str(enum qcs_state st)
-{
-       switch (st) {
-       case QC_SS_IDLE: return "IDL";
-       case QC_SS_OPEN: return "OPN";
-       case QC_SS_HLOC: return "HCL";
-       case QC_SS_HREM: return "HCR";
-       case QC_SS_CLO:  return "CLO";
-       default:         return "???";
-       }
-}
-
 /* for debugging with CLI's "show sess" command. May emit multiple lines, each
  * new one being prefixed with <pfx>, if <pfx> is not NULL, otherwise a single
  * line is used. Each field starts with a space so it's safe to print it after
@@ -2380,70 +2282,6 @@ static int qc_show_sd(struct buffer *msg, struct sedesc *sd, const char *pfx)
 }
 
 
-static void qmux_trace_frm(const struct quic_frame *frm)
-{
-       switch (frm->type) {
-       case QUIC_FT_MAX_STREAMS_BIDI:
-               chunk_appendf(&trace_buf, " max_streams=%llu",
-                             (ull)frm->max_streams_bidi.max_streams);
-               break;
-
-       case QUIC_FT_MAX_STREAMS_UNI:
-               chunk_appendf(&trace_buf, " max_streams=%llu",
-                             (ull)frm->max_streams_uni.max_streams);
-               break;
-
-       default:
-               break;
-       }
-}
-
-/* quic-mux trace handler */
-static void qmux_trace(enum trace_level level, uint64_t mask,
-                       const struct trace_source *src,
-                       const struct ist where, const struct ist func,
-                       const void *a1, const void *a2, const void *a3, const void *a4)
-{
-       const struct connection *conn = a1;
-       const struct qcc *qcc   = conn ? conn->ctx : NULL;
-       const struct qcs *qcs   = a2;
-
-       if (!qcc)
-               return;
-
-       if (src->verbosity > QMUX_VERB_CLEAN) {
-               chunk_appendf(&trace_buf, " : qcc=%p(F)", qcc);
-               if (qcc->conn->handle.qc)
-                       chunk_appendf(&trace_buf, " qc=%p", qcc->conn->handle.qc);
-
-               if (qcs)
-                       chunk_appendf(&trace_buf, " qcs=%p .id=%llu .st=%s",
-                                     qcs, (ull)qcs->id,
-                                     qcs_st_to_str(qcs->st));
-
-               if (mask & QMUX_EV_QCC_NQCS) {
-                       const uint64_t *id = a3;
-                       chunk_appendf(&trace_buf, " id=%llu", (ull)*id);
-               }
-
-               if (mask & QMUX_EV_SEND_FRM)
-                       qmux_trace_frm(a3);
-
-               if (mask & QMUX_EV_QCS_XFER_DATA) {
-                       const struct qcs_xfer_data_trace_arg *arg = a3;
-                       chunk_appendf(&trace_buf, " prep=%llu xfer=%d",
-                                     (ull)arg->prep, arg->xfer);
-               }
-
-               if (mask & QMUX_EV_QCS_BUILD_STRM) {
-                       const struct qcs_build_stream_trace_arg *arg = a3;
-                       chunk_appendf(&trace_buf, " len=%llu fin=%d offset=%llu",
-                                     (ull)arg->len, arg->fin, (ull)arg->offset);
-               }
-       }
-}
-
-
 static const struct mux_ops qc_ops = {
        .init = qc_init,
        .destroy = qc_destroy,
diff --git a/src/qmux_trace.c b/src/qmux_trace.c
new file mode 100644 (file)
index 0000000..6d84b7a
--- /dev/null
@@ -0,0 +1,107 @@
+#include <haproxy/qmux_trace.h>
+
+#include <import/ist.h>
+#include <haproxy/api.h>
+#include <haproxy/connection.h>
+#include <haproxy/chunk.h>
+#include <haproxy/mux_quic.h>
+
+/* trace source and events */
+static void qmux_trace(enum trace_level level, uint64_t mask,
+                       const struct trace_source *src,
+                       const struct ist where, const struct ist func,
+                       const void *a1, const void *a2, const void *a3, const void *a4);
+
+static const struct name_desc qmux_trace_lockon_args[4] = {
+       /* arg1 */ { /* already used by the connection */ },
+       /* arg2 */ { .name="qcs", .desc="QUIC stream" },
+       /* arg3 */ { },
+       /* arg4 */ { }
+};
+
+static const struct name_desc qmux_trace_decoding[] = {
+#define QMUX_VERB_CLEAN    1
+       { .name="clean",    .desc="only user-friendly stuff, generally suitable for level \"user\"" },
+#define QMUX_VERB_MINIMAL  2
+       { .name="minimal",  .desc="report only qcc/qcs state and flags, no real decoding" },
+       { /* end */ }
+};
+
+struct trace_source trace_qmux = {
+       .name = IST("qmux"),
+       .desc = "QUIC multiplexer",
+       .arg_def = TRC_ARG1_CONN,  /* TRACE()'s first argument is always a connection */
+       .default_cb = qmux_trace,
+       .known_events = qmux_trace_events,
+       .lockon_args = qmux_trace_lockon_args,
+       .decoding = qmux_trace_decoding,
+       .report_events = ~0,  /* report everything by default */
+};
+
+
+static void qmux_trace_frm(const struct quic_frame *frm)
+{
+       switch (frm->type) {
+       case QUIC_FT_MAX_STREAMS_BIDI:
+               chunk_appendf(&trace_buf, " max_streams=%llu",
+                             (ull)frm->max_streams_bidi.max_streams);
+               break;
+
+       case QUIC_FT_MAX_STREAMS_UNI:
+               chunk_appendf(&trace_buf, " max_streams=%llu",
+                             (ull)frm->max_streams_uni.max_streams);
+               break;
+
+       default:
+               break;
+       }
+}
+
+/* quic-mux trace handler */
+static void qmux_trace(enum trace_level level, uint64_t mask,
+                       const struct trace_source *src,
+                       const struct ist where, const struct ist func,
+                       const void *a1, const void *a2, const void *a3, const void *a4)
+{
+       const struct connection *conn = a1;
+       const struct qcc *qcc   = conn ? conn->ctx : NULL;
+       const struct qcs *qcs   = a2;
+
+       if (!qcc)
+               return;
+
+       if (src->verbosity > QMUX_VERB_CLEAN) {
+               chunk_appendf(&trace_buf, " : qcc=%p(F)", qcc);
+               if (qcc->conn->handle.qc)
+                       chunk_appendf(&trace_buf, " qc=%p", qcc->conn->handle.qc);
+
+               if (qcs)
+                       chunk_appendf(&trace_buf, " qcs=%p .id=%llu .st=%s",
+                                     qcs, (ull)qcs->id,
+                                     qcs_st_to_str(qcs->st));
+
+               if (mask & QMUX_EV_QCC_NQCS) {
+                       const uint64_t *id = a3;
+                       chunk_appendf(&trace_buf, " id=%llu", (ull)*id);
+               }
+
+               if (mask & QMUX_EV_SEND_FRM)
+                       qmux_trace_frm(a3);
+
+               if (mask & QMUX_EV_QCS_XFER_DATA) {
+                       const struct qcs_xfer_data_trace_arg *arg = a3;
+                       chunk_appendf(&trace_buf, " prep=%llu xfer=%d",
+                                     (ull)arg->prep, arg->xfer);
+               }
+
+               if (mask & QMUX_EV_QCS_BUILD_STRM) {
+                       const struct qcs_build_stream_trace_arg *arg = a3;
+                       chunk_appendf(&trace_buf, " len=%llu fin=%d offset=%llu",
+                                     (ull)arg->len, arg->fin, (ull)arg->offset);
+               }
+       }
+}
+
+
+/* register qmux traces */
+INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);