blob: 6d84b7afe2c185b3e444591d2a8b23982133a48c [file] [log] [blame]
Amaury Denoyelle36d50bf2022-09-19 16:12:38 +02001#include <haproxy/qmux_trace.h>
2
3#include <import/ist.h>
4#include <haproxy/api.h>
5#include <haproxy/connection.h>
6#include <haproxy/chunk.h>
7#include <haproxy/mux_quic.h>
8
9/* trace source and events */
10static void qmux_trace(enum trace_level level, uint64_t mask,
11 const struct trace_source *src,
12 const struct ist where, const struct ist func,
13 const void *a1, const void *a2, const void *a3, const void *a4);
14
15static const struct name_desc qmux_trace_lockon_args[4] = {
16 /* arg1 */ { /* already used by the connection */ },
17 /* arg2 */ { .name="qcs", .desc="QUIC stream" },
18 /* arg3 */ { },
19 /* arg4 */ { }
20};
21
22static const struct name_desc qmux_trace_decoding[] = {
23#define QMUX_VERB_CLEAN 1
24 { .name="clean", .desc="only user-friendly stuff, generally suitable for level \"user\"" },
25#define QMUX_VERB_MINIMAL 2
26 { .name="minimal", .desc="report only qcc/qcs state and flags, no real decoding" },
27 { /* end */ }
28};
29
30struct trace_source trace_qmux = {
31 .name = IST("qmux"),
32 .desc = "QUIC multiplexer",
33 .arg_def = TRC_ARG1_CONN, /* TRACE()'s first argument is always a connection */
34 .default_cb = qmux_trace,
35 .known_events = qmux_trace_events,
36 .lockon_args = qmux_trace_lockon_args,
37 .decoding = qmux_trace_decoding,
38 .report_events = ~0, /* report everything by default */
39};
40
41
42static void qmux_trace_frm(const struct quic_frame *frm)
43{
44 switch (frm->type) {
45 case QUIC_FT_MAX_STREAMS_BIDI:
46 chunk_appendf(&trace_buf, " max_streams=%llu",
47 (ull)frm->max_streams_bidi.max_streams);
48 break;
49
50 case QUIC_FT_MAX_STREAMS_UNI:
51 chunk_appendf(&trace_buf, " max_streams=%llu",
52 (ull)frm->max_streams_uni.max_streams);
53 break;
54
55 default:
56 break;
57 }
58}
59
60/* quic-mux trace handler */
61static void qmux_trace(enum trace_level level, uint64_t mask,
62 const struct trace_source *src,
63 const struct ist where, const struct ist func,
64 const void *a1, const void *a2, const void *a3, const void *a4)
65{
66 const struct connection *conn = a1;
67 const struct qcc *qcc = conn ? conn->ctx : NULL;
68 const struct qcs *qcs = a2;
69
70 if (!qcc)
71 return;
72
73 if (src->verbosity > QMUX_VERB_CLEAN) {
74 chunk_appendf(&trace_buf, " : qcc=%p(F)", qcc);
75 if (qcc->conn->handle.qc)
76 chunk_appendf(&trace_buf, " qc=%p", qcc->conn->handle.qc);
77
78 if (qcs)
79 chunk_appendf(&trace_buf, " qcs=%p .id=%llu .st=%s",
80 qcs, (ull)qcs->id,
81 qcs_st_to_str(qcs->st));
82
83 if (mask & QMUX_EV_QCC_NQCS) {
84 const uint64_t *id = a3;
85 chunk_appendf(&trace_buf, " id=%llu", (ull)*id);
86 }
87
88 if (mask & QMUX_EV_SEND_FRM)
89 qmux_trace_frm(a3);
90
91 if (mask & QMUX_EV_QCS_XFER_DATA) {
92 const struct qcs_xfer_data_trace_arg *arg = a3;
93 chunk_appendf(&trace_buf, " prep=%llu xfer=%d",
94 (ull)arg->prep, arg->xfer);
95 }
96
97 if (mask & QMUX_EV_QCS_BUILD_STRM) {
98 const struct qcs_build_stream_trace_arg *arg = a3;
99 chunk_appendf(&trace_buf, " len=%llu fin=%d offset=%llu",
100 (ull)arg->len, arg->fin, (ull)arg->offset);
101 }
102 }
103}
104
105
106/* register qmux traces */
107INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);