#include <common/net_helper.h>
#include <proto/connection.h>
#include <proto/http_htx.h>
+#include <proto/trace.h>
#include <proto/session.h>
#include <proto/stream.h>
#include <proto/stream_interface.h>
uint8_t ff; /* frame flags */
};
+/* trace source and events */
+
+/* The event representation is split like this :
+ * strm - application layer
+ * h2s - internal H2 stream
+ * h2c - internal H2 connection
+ * conn - external connection
+ *
+ */
+static const struct trace_event h2_trace_events[] = {
+#define H2_EV_H2C_NEW (1ULL << 0)
+ { .mask = H2_EV_H2C_NEW, .name = "H2C_NEW", .desc = "new H2 connection" },
+#define H2_EV_H2C_RECV (1ULL << 1)
+ { .mask = H2_EV_H2C_RECV, .name = "H2C_RECV", .desc = "Rx on H2 connection" },
+#define H2_EV_H2C_SEND (1ULL << 2)
+ { .mask = H2_EV_H2C_SEND, .name = "H2C_SEND", .desc = "Tx on H2 connection" },
+#define H2_EV_H2C_FCTL (1ULL << 3)
+ { .mask = H2_EV_H2C_FCTL, .name = "H2C_FCTL", .desc = "H2 connection flow-controlled" },
+#define H2_EV_H2C_BLK (1ULL << 4)
+ { .mask = H2_EV_H2C_BLK, .name = "H2C_BLK", .desc = "H2 connection blocked" },
+#define H2_EV_H2C_WAKE (1ULL << 5)
+ { .mask = H2_EV_H2C_WAKE, .name = "H2C_WAKE", .desc = "H2 connection woken up" },
+#define H2_EV_H2C_END (1ULL << 6)
+ { .mask = H2_EV_H2C_END, .name = "H2C_END", .desc = "H2 connection terminated" },
+#define H2_EV_H2C_ERR (1ULL << 7)
+ { .mask = H2_EV_H2C_ERR, .name = "H2C_ERR", .desc = "error on H2 connection" },
+#define H2_EV_RX_FHDR (1ULL << 8)
+ { .mask = H2_EV_RX_FHDR, .name = "RX_FHDR", .desc = "H2 frame header received" },
+#define H2_EV_RX_FRAME (1ULL << 9)
+ { .mask = H2_EV_RX_FRAME, .name = "RX_FRAME", .desc = "receipt of any H2 frame" },
+#define H2_EV_RX_EOI (1ULL << 10)
+ { .mask = H2_EV_RX_EOI, .name = "RX_EOI", .desc = "receipt of end of H2 input (ES or RST)" },
+#define H2_EV_RX_PREFACE (1ULL << 11)
+ { .mask = H2_EV_RX_PREFACE, .name = "RX_PREFACE", .desc = "receipt of H2 preface" },
+#define H2_EV_RX_DATA (1ULL << 12)
+ { .mask = H2_EV_RX_DATA, .name = "RX_DATA", .desc = "receipt of H2 DATA frame" },
+#define H2_EV_RX_HDR (1ULL << 13)
+ { .mask = H2_EV_RX_HDR, .name = "RX_HDR", .desc = "receipt of H2 HEADERS frame" },
+#define H2_EV_RX_PRIO (1ULL << 14)
+ { .mask = H2_EV_RX_PRIO, .name = "RX_PRIO", .desc = "receipt of H2 PRIORITY frame" },
+#define H2_EV_RX_RST (1ULL << 15)
+ { .mask = H2_EV_RX_RST, .name = "RX_RST", .desc = "receipt of H2 RST_STREAM frame" },
+#define H2_EV_RX_SETTINGS (1ULL << 16)
+ { .mask = H2_EV_RX_SETTINGS, .name = "RX_SETTINGS", .desc = "receipt of H2 SETTINGS frame" },
+#define H2_EV_RX_PUSH (1ULL << 17)
+ { .mask = H2_EV_RX_PUSH, .name = "RX_PUSH", .desc = "receipt of H2 PUSH_PROMISE frame" },
+#define H2_EV_RX_PING (1ULL << 18)
+ { .mask = H2_EV_RX_PING, .name = "RX_PING", .desc = "receipt of H2 PING frame" },
+#define H2_EV_RX_GOAWAY (1ULL << 19)
+ { .mask = H2_EV_RX_GOAWAY, .name = "RX_GOAWAY", .desc = "receipt of H2 GOAWAY frame" },
+#define H2_EV_RX_WU (1ULL << 20)
+ { .mask = H2_EV_RX_WU, .name = "RX_WU", .desc = "receipt of H2 WINDOW_UPDATE frame" },
+#define H2_EV_RX_CONT (1ULL << 21)
+ { .mask = H2_EV_RX_CONT, .name = "RX_CONT", .desc = "receipt of H2 CONTINUATION frame" },
+#define H2_EV_TX_FRAME (1ULL << 22)
+ { .mask = H2_EV_TX_FRAME, .name = "TX_FRAME", .desc = "transmission of any H2 frame" },
+#define H2_EV_TX_EOI (1ULL << 23)
+ { .mask = H2_EV_TX_EOI, .name = "TX_EOI", .desc = "transmission of H2 end of input (ES or RST)" },
+#define H2_EV_TX_PREFACE (1ULL << 24)
+ { .mask = H2_EV_TX_PREFACE, .name = "TX_PREFACE", .desc = "transmission of H2 preface" },
+#define H2_EV_TX_DATA (1ULL << 25)
+ { .mask = H2_EV_TX_DATA, .name = "TX_DATA", .desc = "transmission of H2 DATA frame" },
+#define H2_EV_TX_HDR (1ULL << 26)
+ { .mask = H2_EV_TX_HDR, .name = "TX_HDR", .desc = "transmission of H2 HEADERS frame" },
+#define H2_EV_TX_PRIO (1ULL << 27)
+ { .mask = H2_EV_TX_PRIO, .name = "TX_PRIO", .desc = "transmission of H2 PRIORITY frame" },
+#define H2_EV_TX_RST (1ULL << 28)
+ { .mask = H2_EV_TX_RST, .name = "TX_RST", .desc = "transmission of H2 RST_STREAM frame" },
+#define H2_EV_TX_SETTINGS (1ULL << 29)
+ { .mask = H2_EV_TX_SETTINGS, .name = "TX_SETTINGS", .desc = "transmission of H2 SETTINGS frame" },
+#define H2_EV_TX_PUSH (1ULL << 30)
+ { .mask = H2_EV_TX_PUSH, .name = "TX_PUSH", .desc = "transmission of H2 PUSH_PROMISE frame" },
+#define H2_EV_TX_PING (1ULL << 31)
+ { .mask = H2_EV_TX_PING, .name = "TX_PING", .desc = "transmission of H2 PING frame" },
+#define H2_EV_TX_GOAWAY (1ULL << 32)
+ { .mask = H2_EV_TX_GOAWAY, .name = "TX_GOAWAY", .desc = "transmission of H2 GOAWAY frame" },
+#define H2_EV_TX_WU (1ULL << 33)
+ { .mask = H2_EV_TX_WU, .name = "TX_WU", .desc = "transmission of H2 WINDOW_UPDATE frame" },
+#define H2_EV_TX_CONT (1ULL << 34)
+ { .mask = H2_EV_TX_CONT, .name = "TX_CONT", .desc = "transmission of H2 CONTINUATION frame" },
+#define H2_EV_H2S_NEW (1ULL << 35)
+ { .mask = H2_EV_H2S_NEW, .name = "H2S_NEW", .desc = "new H2 stream" },
+#define H2_EV_H2S_RECV (1ULL << 36)
+ { .mask = H2_EV_H2S_RECV, .name = "H2S_RECV", .desc = "Rx for H2 stream" },
+#define H2_EV_H2S_SEND (1ULL << 37)
+ { .mask = H2_EV_H2S_SEND, .name = "H2S_SEND", .desc = "Tx for H2 stream" },
+#define H2_EV_H2S_FCTL (1ULL << 38)
+ { .mask = H2_EV_H2S_FCTL, .name = "H2S_FCTL", .desc = "H2 stream flow-controlled" },
+#define H2_EV_H2S_BLK (1ULL << 39)
+ { .mask = H2_EV_H2S_BLK, .name = "H2S_BLK", .desc = "H2 stream blocked" },
+#define H2_EV_H2S_WAKE (1ULL << 40)
+ { .mask = H2_EV_H2S_WAKE, .name = "H2S_WAKE", .desc = "H2 stream woken up" },
+#define H2_EV_H2S_END (1ULL << 41)
+ { .mask = H2_EV_H2S_END, .name = "H2S_END", .desc = "H2 stream terminated" },
+#define H2_EV_H2S_ERR (1ULL << 42)
+ { .mask = H2_EV_H2S_ERR, .name = "H2S_ERR", .desc = "error on H2 stream" },
+#define H2_EV_STRM_NEW (1ULL << 43)
+ { .mask = H2_EV_STRM_NEW, .name = "STRM_NEW", .desc = "app-layer stream creation" },
+#define H2_EV_STRM_RECV (1ULL << 44)
+ { .mask = H2_EV_STRM_RECV, .name = "STRM_RECV", .desc = "receiving data for stream" },
+#define H2_EV_STRM_SEND (1ULL << 45)
+ { .mask = H2_EV_STRM_SEND, .name = "STRM_SEND", .desc = "sending data for stream" },
+#define H2_EV_STRM_FULL (1ULL << 46)
+ { .mask = H2_EV_STRM_FULL, .name = "STRM_FULL", .desc = "stream buffer full" },
+#define H2_EV_STRM_WAKE (1ULL << 47)
+ { .mask = H2_EV_STRM_WAKE, .name = "STRM_WAKE", .desc = "stream woken up" },
+#define H2_EV_STRM_SHUT (1ULL << 48)
+ { .mask = H2_EV_STRM_SHUT, .name = "STRM_SHUT", .desc = "stream shutdown" },
+#define H2_EV_STRM_END (1ULL << 49)
+ { .mask = H2_EV_STRM_END, .name = "STRM_END", .desc = "detaching app-layer stream" },
+#define H2_EV_STRM_ERR (1ULL << 50)
+ { .mask = H2_EV_STRM_ERR, .name = "STRM_ERR", .desc = "stream error" },
+#define H2_EV_PROTO_ERR (1ULL << 51)
+ { .mask = H2_EV_PROTO_ERR, .name = "PROTO_ERR", .desc = "protocol error" },
+ { }
+};
+
+static const struct name_desc h2_trace_lockon_args[4] = {
+ /* arg1 */ { /* already used by the connection */ },
+ /* arg2 */ { .name="h2s", .desc="H2 stream" },
+ /* arg3 */ { },
+ /* arg4 */ { }
+};
+
+static const struct name_desc h2_trace_decoding[] = {
+ { .name="minimal", .desc="report only h2c/h2s state and flags, no real decoding" },
+ { .name="simple", .desc="add request/response status line or frame info when available" },
+ { .name="advanced", .desc="add header fields or frame decoding when available" },
+ { .name="complete", .desc="add full data dump when available" },
+ { /* end */ }
+};
+
+static struct trace_source trace_h2 = {
+ .name = IST("h2"),
+ .desc = "HTTP/2 multiplexer",
+ .arg_def = TRC_ARG1_CONN, // TRACE()'s first argument is always a connection
+ .known_events = h2_trace_events,
+ .lockon_args = h2_trace_lockon_args,
+ .decoding = h2_trace_decoding,
+ .report_events = ~0, // report everything by default
+};
+
+#define TRACE_SOURCE &trace_h2
+INITCALL1(STG_REGISTER, trace_register_source, TRACE_SOURCE);
+
/* the h2c connection pool */
DECLARE_STATIC_POOL(pool_head_h2c, "h2c", sizeof(struct h2c));