├── .clang-format
├── .gitignore
├── CMakeLists.txt
├── README.md
├── generated-quic.cc
├── h2o-probes.d
├── h2olog.cc
├── h2olog.h
├── http.cc
├── json.cc
├── json.h
├── make.sh
├── misc
├── autopep8
└── gen-quic-bpf.py
├── pyproject.toml
├── quic.h
└── quicly-probes.d
/.clang-format:
--------------------------------------------------------------------------------
1 | # requires clang-format >= 3.6
2 | BasedOnStyle: "LLVM"
3 | IndentWidth: 4
4 | ColumnLimit: 132
5 | BreakBeforeBraces: Linux
6 | AllowShortFunctionsOnASingleLine: None
7 | SortIncludes: false
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.old
3 | *~
4 | .DS_Store
5 | CMakeCache.txt
6 | CMakeFiles/
7 | Makefile
8 | cmake_install.cmake
9 | h2olog
10 | build/
11 | .pip3/
12 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
2 |
3 | ENABLE_LANGUAGE(CXX)
4 | SET(CMAKE_CXX_STANDARD 11)
5 | SET(CMAKE_CXX_STANDARD_REQUIRED ON)
6 | SET(CMAKE_CXX_EXTENSIONS OFF)
7 |
8 | INCLUDE(GNUInstallDirs)
9 |
10 | SET(H2O_COMMIT "fb0d55a")
11 |
12 | PROJECT(h2olog)
13 |
14 | IF(NOT CMAKE_BUILD_TYPE)
15 | SET(CMAKE_BUILD_TYPE Release)
16 | ENDIF(NOT CMAKE_BUILD_TYPE)
17 |
18 | SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -flto")
19 |
20 | SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -g3 ${CMAKE_CXX_FLAGS}")
21 |
22 | FIND_PATH(LIBBCC_INCLUDE_DIR NAMES bcc/BPF.h)
23 | FIND_LIBRARY(LIBBCC_LIB "bcc")
24 | IF (LIBBCC_LIB)
25 | IF (LIBBCC_INCLUDE_DIR)
26 | INCLUDE_DIRECTORIES("${LIBBCC_INCLUDE_DIR}")
27 | ELSE (LIBBCC_INCLUDE_DIR)
28 | MESSAGE(SEND_ERROR "libbcc header files not found")
29 | ENDIF (LIBBCC_INCLUDE_DIR)
30 | ELSE (LIBBCC_LIB)
31 | MESSAGE(SEND_ERROR "libbcc not found")
32 | ENDIF (LIBBCC_LIB)
33 |
34 | SET(SOURCE_FILES
35 | "h2olog.h"
36 | "h2olog.cc"
37 | "http.cc"
38 | "json.h"
39 | "json.cc"
40 | "quic.h"
41 | )
42 |
43 | ADD_CUSTOM_COMMAND(
44 | OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/quicly-probes.d"
45 | COMMAND curl -sLf 'https://raw.githubusercontent.com/h2o/h2o/${H2O_COMMIT}/deps/quicly/quicly-probes.d' >${CMAKE_CURRENT_SOURCE_DIR}/quicly-probes.d
46 | )
47 | LIST(APPEND DTRACE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/quicly-probes.d")
48 |
49 | ADD_CUSTOM_COMMAND(
50 | OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/h2o-probes.d"
51 | COMMAND curl -sLf 'https://raw.githubusercontent.com/h2o/h2o/${H2O_COMMIT}/h2o-probes.d' >${CMAKE_CURRENT_SOURCE_DIR}/h2o-probes.d
52 | )
53 | LIST(APPEND DTRACE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/h2o-probes.d")
54 |
55 | ADD_CUSTOM_COMMAND(
56 | OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/generated-quic.cc"
57 | COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/misc/gen-quic-bpf.py" "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/generated-quic.cc"
58 | DEPENDS ${DTRACE_FILES}
59 | DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/misc/gen-quic-bpf.py"
60 | )
61 | LIST(APPEND SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/generated-quic.cc")
62 |
63 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
64 |
65 | ADD_EXECUTABLE(h2olog ${SOURCE_FILES})
66 | TARGET_LINK_LIBRARIES(h2olog ${LIBBCC_LIB})
67 |
68 | INSTALL(TARGETS h2olog RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
69 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # h2olog
2 |
3 | This project has been integrated into [h2o/h2o](https://github.com/h2o/h2o/tree/master/src/h2olog).
4 |
5 | ---
6 |
7 | A [varnishlog](https://varnish-cache.org/docs/trunk/reference/varnishlog.html)-like [BPF](https://www.kernel.org/doc/html/latest/bpf/index.html) ([kernel doc](https://www.kernel.org/doc/Documentation/networking/filter.txt)) backed HTTP request logging client for the [H2O](https://github.com/h2o/h2o) server.
8 | h2olog can also be used to log [QUIC](https://en.wikipedia.org/wiki/QUIC) events for [transport layer](https://en.wikipedia.org/wiki/Transport_layer) observation.
9 | See [Tracing QUIC events](#tracing-quic-events) for how.
10 |
11 | ## Installing from Source
12 |
13 | See [requirements](#requirements) for build prerequisites.
14 |
15 | ```
16 | $ cmake -Bbuild
17 | $ make -Cbuild
18 | $ sudo make -Cbuild install
19 | ```
20 |
21 | If you have `BCC` installed to a non-standard path, give its path as [`-DCMAKE_PREFIX_PATH`](https://cmake.org/cmake/help/latest/variable/CMAKE_PREFIX_PATH.html) to `cmake`.
22 |
23 | For convenience, you can alternatively run the `make.sh` script.
24 |
25 | ## Requirements
26 |
27 | ### For building h2olog
28 |
29 | - LLVM and clang (>= 3.7.1)
30 | - CMake for generating the build files
31 | - Python 3 for the [code generator](https://github.com/toru/h2olog/blob/v2/misc/gen-quic-bpf.py)
32 | - [BCC](https://iovisor.github.io/bcc/) (>= 0.11.0) [installed](https://github.com/iovisor/bcc/blob/master/INSTALL.md) on your system
33 |
34 | For Ubuntu 20.04 or later, you can install dependencies with:
35 |
36 | ```sh
37 | sudo apt install clang cmake python3 systemtap-sdt-dev libbpfcc-dev linux-headers-$(uname -r)
38 | ```
39 |
40 | ### For running h2olog
41 |
42 | - Root privilege to execute the program
43 | - H2O server built after [53e1db42](https://github.com/h2o/h2o/commit/53e1db428772460534191d1c35c79a6dd94e021f) with `-DWITH_DTRACE=on` cmake option
44 |
45 | ## Quickstart
46 |
47 | Root privilege is required to interact with the BPF virtual machine.
48 |
49 | ```
50 | $ sudo h2olog -p $(pgrep -o h2o)
51 |
52 | 11 0 RxProtocol HTTP/3.0
53 | 11 0 RxHeader :authority torumk.com
54 | 11 0 RxHeader :method GET
55 | 11 0 RxHeader :path /
56 | 11 0 RxHeader :scheme https
57 | 11 0 TxStatus 200
58 | 11 0 TxHeader content-length 123
59 | 11 0 TxHeader content-type text/html
60 | ... and more ...
61 | ```
62 |
63 | ## Tracing QUIC events
64 |
65 | Server-side [QUIC](https://en.wikipedia.org/wiki/QUIC) events can be traced using the `quic` subcommand.
66 | Events are rendered in [JSON](https://en.wikipedia.org/wiki/JSON) format.
67 |
68 | ```
69 | $ sudo h2olog quic -p $(pgrep -o h2o)
70 | ^
71 | |_ The quic subcommand
72 | ```
73 |
74 | Here's an example trace.
75 |
76 | ```
77 | {"time":1584380825832,"type":"accept","conn":1,"dcid":"f8aa2066e9c3b3cf"}
78 | {"time":1584380825835,"type":"crypto-decrypt","conn":1,"pn":0,"len":1236}
79 | {"time":1584380825832,"type":"quictrace-recv","conn":1,"pn":0}
80 | {"time":1584380825836,"type":"crypto-handshake","conn":1,"ret":0}
81 | ... and more ...
82 | ```
83 |
84 | ## Program Anatomy
85 |
86 | h2olog is a [BCC](https://github.com/iovisor/bcc) based C++ program.
87 | It was previously implemented using the [BCC Python binding](https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#bcc-python).
88 |
--------------------------------------------------------------------------------
/generated-quic.cc:
--------------------------------------------------------------------------------
1 | // Generated code. Do not edit it here!
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include "h2olog.h"
9 | #include "quic.h"
10 | #include "json.h"
11 |
12 | #define STR_LEN 64
13 | #define STR_LIT(s) s, strlen(s)
14 |
15 | uint64_t seq = 0;
16 |
17 | // BPF modules written in C
18 | const char *bpf_text = R"(
19 |
20 | #include
21 |
22 | #define STR_LEN 64
23 | /*
24 | * Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka, Goro Fuji
25 | *
26 | * Permission is hereby granted, free of charge, to any person obtaining a copy
27 | * of this software and associated documentation files (the "Software"), to
28 | * deal in the Software without restriction, including without limitation the
29 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
30 | * sell copies of the Software, and to permit persons to whom the Software is
31 | * furnished to do so, subject to the following conditions:
32 | *
33 | * The above copyright notice and this permission notice shall be included in
34 | * all copies or substantial portions of the Software.
35 | *
36 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
39 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
40 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
41 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
42 | * IN THE SOFTWARE.
43 | */
44 |
45 | #ifndef H2OLOG_QUIC_H
46 | #define H2OLOG_QUIC_H
47 |
48 | /*
49 | * These structs mirror H2O's internal structs. As the name suggests, dummy
50 | * fields are paddings that are ignored.
51 | */
52 | struct st_quicly_stream_t {
53 | uint64_t dummy;
54 | int64_t stream_id;
55 | };
56 |
57 | struct st_quicly_conn_t {
58 | uint32_t dummy[4];
59 | uint32_t master_id;
60 | };
61 |
62 | struct quicly_rtt_t {
63 | uint32_t minimum;
64 | uint32_t smoothed;
65 | uint32_t variance;
66 | uint32_t latest;
67 | };
68 |
69 | struct st_quicly_address_token_plaintext_t {
70 | int dummy;
71 | };
72 |
73 | struct st_h2o_conn_t {
74 | int dummy;
75 | };
76 |
77 | #endif
78 |
79 |
80 | struct quic_event_t {
81 | uint8_t id;
82 |
83 | union {
84 | struct { // quicly:connect
85 | uint32_t master_id;
86 | int64_t at;
87 | uint32_t version;
88 | } connect;
89 | struct { // quicly:accept
90 | uint32_t master_id;
91 | int64_t at;
92 | char dcid[STR_LEN];
93 | } accept;
94 | struct { // quicly:free
95 | uint32_t master_id;
96 | int64_t at;
97 | } free;
98 | struct { // quicly:send
99 | uint32_t master_id;
100 | int64_t at;
101 | int state;
102 | char dcid[STR_LEN];
103 | } send;
104 | struct { // quicly:receive
105 | uint32_t master_id;
106 | int64_t at;
107 | char dcid[STR_LEN];
108 | uint8_t bytes[1];
109 | size_t num_bytes;
110 | } receive;
111 | struct { // quicly:version_switch
112 | uint32_t master_id;
113 | int64_t at;
114 | uint32_t new_version;
115 | } version_switch;
116 | struct { // quicly:idle_timeout
117 | uint32_t master_id;
118 | int64_t at;
119 | } idle_timeout;
120 | struct { // quicly:stateless_reset_receive
121 | uint32_t master_id;
122 | int64_t at;
123 | } stateless_reset_receive;
124 | struct { // quicly:crypto_decrypt
125 | uint32_t master_id;
126 | int64_t at;
127 | uint64_t pn;
128 | size_t decrypted_len;
129 | } crypto_decrypt;
130 | struct { // quicly:crypto_handshake
131 | uint32_t master_id;
132 | int64_t at;
133 | int ret;
134 | } crypto_handshake;
135 | struct { // quicly:crypto_update_secret
136 | uint32_t master_id;
137 | int64_t at;
138 | int is_enc;
139 | uint8_t epoch;
140 | char label[STR_LEN];
141 | } crypto_update_secret;
142 | struct { // quicly:crypto_send_key_update
143 | uint32_t master_id;
144 | int64_t at;
145 | uint64_t phase;
146 | } crypto_send_key_update;
147 | struct { // quicly:crypto_send_key_update_confirmed
148 | uint32_t master_id;
149 | int64_t at;
150 | uint64_t next_pn;
151 | } crypto_send_key_update_confirmed;
152 | struct { // quicly:crypto_receive_key_update
153 | uint32_t master_id;
154 | int64_t at;
155 | uint64_t phase;
156 | } crypto_receive_key_update;
157 | struct { // quicly:crypto_receive_key_update_prepare
158 | uint32_t master_id;
159 | int64_t at;
160 | uint64_t phase;
161 | } crypto_receive_key_update_prepare;
162 | struct { // quicly:packet_prepare
163 | uint32_t master_id;
164 | int64_t at;
165 | uint8_t first_octet;
166 | char dcid[STR_LEN];
167 | } packet_prepare;
168 | struct { // quicly:packet_commit
169 | uint32_t master_id;
170 | int64_t at;
171 | uint64_t pn;
172 | size_t len;
173 | int ack_only;
174 | } packet_commit;
175 | struct { // quicly:packet_acked
176 | uint32_t master_id;
177 | int64_t at;
178 | uint64_t pn;
179 | int newly_acked;
180 | } packet_acked;
181 | struct { // quicly:packet_lost
182 | uint32_t master_id;
183 | int64_t at;
184 | uint64_t pn;
185 | } packet_lost;
186 | struct { // quicly:pto
187 | uint32_t master_id;
188 | int64_t at;
189 | size_t inflight;
190 | uint32_t cwnd;
191 | int8_t pto_count;
192 | } pto;
193 | struct { // quicly:cc_ack_received
194 | uint32_t master_id;
195 | int64_t at;
196 | uint64_t largest_acked;
197 | size_t bytes_acked;
198 | uint32_t cwnd;
199 | size_t inflight;
200 | } cc_ack_received;
201 | struct { // quicly:cc_congestion
202 | uint32_t master_id;
203 | int64_t at;
204 | uint64_t max_lost_pn;
205 | size_t inflight;
206 | uint32_t cwnd;
207 | } cc_congestion;
208 | struct { // quicly:transport_close_send
209 | uint32_t master_id;
210 | int64_t at;
211 | uint64_t error_code;
212 | uint64_t frame_type;
213 | char reason_phrase[STR_LEN];
214 | } transport_close_send;
215 | struct { // quicly:transport_close_receive
216 | uint32_t master_id;
217 | int64_t at;
218 | uint64_t error_code;
219 | uint64_t frame_type;
220 | char reason_phrase[STR_LEN];
221 | } transport_close_receive;
222 | struct { // quicly:application_close_send
223 | uint32_t master_id;
224 | int64_t at;
225 | uint64_t error_code;
226 | char reason_phrase[STR_LEN];
227 | } application_close_send;
228 | struct { // quicly:application_close_receive
229 | uint32_t master_id;
230 | int64_t at;
231 | uint64_t error_code;
232 | char reason_phrase[STR_LEN];
233 | } application_close_receive;
234 | struct { // quicly:stream_send
235 | uint32_t master_id;
236 | int64_t at;
237 | int64_t stream_id;
238 | uint64_t off;
239 | size_t len;
240 | int is_fin;
241 | } stream_send;
242 | struct { // quicly:stream_receive
243 | uint32_t master_id;
244 | int64_t at;
245 | int64_t stream_id;
246 | uint64_t off;
247 | size_t len;
248 | } stream_receive;
249 | struct { // quicly:stream_acked
250 | uint32_t master_id;
251 | int64_t at;
252 | int64_t stream_id;
253 | uint64_t off;
254 | size_t len;
255 | } stream_acked;
256 | struct { // quicly:stream_lost
257 | uint32_t master_id;
258 | int64_t at;
259 | int64_t stream_id;
260 | uint64_t off;
261 | size_t len;
262 | } stream_lost;
263 | struct { // quicly:max_data_send
264 | uint32_t master_id;
265 | int64_t at;
266 | uint64_t limit;
267 | } max_data_send;
268 | struct { // quicly:max_data_receive
269 | uint32_t master_id;
270 | int64_t at;
271 | uint64_t limit;
272 | } max_data_receive;
273 | struct { // quicly:max_streams_send
274 | uint32_t master_id;
275 | int64_t at;
276 | uint64_t limit;
277 | int is_unidirectional;
278 | } max_streams_send;
279 | struct { // quicly:max_streams_receive
280 | uint32_t master_id;
281 | int64_t at;
282 | uint64_t limit;
283 | int is_unidirectional;
284 | } max_streams_receive;
285 | struct { // quicly:max_stream_data_send
286 | uint32_t master_id;
287 | int64_t at;
288 | int64_t stream_id;
289 | uint64_t limit;
290 | } max_stream_data_send;
291 | struct { // quicly:max_stream_data_receive
292 | uint32_t master_id;
293 | int64_t at;
294 | int64_t stream_id;
295 | uint64_t limit;
296 | } max_stream_data_receive;
297 | struct { // quicly:new_token_send
298 | uint32_t master_id;
299 | int64_t at;
300 | uint8_t token[STR_LEN];
301 | size_t len;
302 | uint64_t generation;
303 | } new_token_send;
304 | struct { // quicly:new_token_acked
305 | uint32_t master_id;
306 | int64_t at;
307 | uint64_t generation;
308 | } new_token_acked;
309 | struct { // quicly:new_token_receive
310 | uint32_t master_id;
311 | int64_t at;
312 | uint8_t token[STR_LEN];
313 | size_t len;
314 | } new_token_receive;
315 | struct { // quicly:handshake_done_send
316 | uint32_t master_id;
317 | int64_t at;
318 | } handshake_done_send;
319 | struct { // quicly:handshake_done_receive
320 | uint32_t master_id;
321 | int64_t at;
322 | } handshake_done_receive;
323 | struct { // quicly:streams_blocked_send
324 | uint32_t master_id;
325 | int64_t at;
326 | uint64_t limit;
327 | int is_unidirectional;
328 | } streams_blocked_send;
329 | struct { // quicly:streams_blocked_receive
330 | uint32_t master_id;
331 | int64_t at;
332 | uint64_t limit;
333 | int is_unidirectional;
334 | } streams_blocked_receive;
335 | struct { // quicly:data_blocked_receive
336 | uint32_t master_id;
337 | int64_t at;
338 | uint64_t off;
339 | } data_blocked_receive;
340 | struct { // quicly:stream_data_blocked_receive
341 | uint32_t master_id;
342 | int64_t at;
343 | int64_t stream_id;
344 | uint64_t limit;
345 | } stream_data_blocked_receive;
346 | struct { // quicly:quictrace_sent
347 | uint32_t master_id;
348 | int64_t at;
349 | uint64_t pn;
350 | size_t len;
351 | uint8_t packet_type;
352 | } quictrace_sent;
353 | struct { // quicly:quictrace_recv
354 | uint32_t master_id;
355 | int64_t at;
356 | uint64_t pn;
357 | } quictrace_recv;
358 | struct { // quicly:quictrace_send_stream
359 | uint32_t master_id;
360 | int64_t at;
361 | int64_t stream_id;
362 | uint64_t off;
363 | size_t len;
364 | int fin;
365 | } quictrace_send_stream;
366 | struct { // quicly:quictrace_recv_stream
367 | uint32_t master_id;
368 | int64_t at;
369 | int64_t stream_id;
370 | uint64_t off;
371 | size_t len;
372 | int fin;
373 | } quictrace_recv_stream;
374 | struct { // quicly:quictrace_recv_ack
375 | uint32_t master_id;
376 | int64_t at;
377 | uint64_t ack_block_begin;
378 | uint64_t ack_block_end;
379 | } quictrace_recv_ack;
380 | struct { // quicly:quictrace_recv_ack_delay
381 | uint32_t master_id;
382 | int64_t at;
383 | int64_t ack_delay;
384 | } quictrace_recv_ack_delay;
385 | struct { // quicly:quictrace_lost
386 | uint32_t master_id;
387 | int64_t at;
388 | uint64_t pn;
389 | } quictrace_lost;
390 | struct { // quicly:quictrace_cc_ack
391 | uint32_t master_id;
392 | int64_t at;
393 | uint32_t minimum;
394 | uint32_t smoothed;
395 | uint32_t variance;
396 | uint32_t latest;
397 | uint32_t cwnd;
398 | size_t inflight;
399 | } quictrace_cc_ack;
400 | struct { // quicly:quictrace_cc_lost
401 | uint32_t master_id;
402 | int64_t at;
403 | uint32_t minimum;
404 | uint32_t smoothed;
405 | uint32_t variance;
406 | uint32_t latest;
407 | uint32_t cwnd;
408 | size_t inflight;
409 | } quictrace_cc_lost;
410 | struct { // h2o:h3_accept
411 | uint64_t conn_id;
412 | uint32_t master_id;
413 | } h3_accept;
414 | struct { // h2o:h3_close
415 | uint64_t conn_id;
416 | uint32_t master_id;
417 | } h3_close;
418 | struct { // h2o:send_response_header
419 | uint64_t conn_id;
420 | uint64_t req_id;
421 | char name[STR_LEN];
422 | size_t name_len;
423 | char value[STR_LEN];
424 | size_t value_len;
425 | uint32_t master_id;
426 | } send_response_header;
427 |
428 | };
429 | };
430 |
431 | BPF_PERF_OUTPUT(events);
432 |
433 | // HTTP/3 tracing
434 | BPF_HASH(h2o_to_quicly_conn, u64, u32);
435 |
436 | // tracepoint sched:sched_process_exit
437 | int trace_sched_process_exit(struct tracepoint__sched__sched_process_exit *ctx) {
438 | const struct task_struct *task = (const struct task_struct*)bpf_get_current_task();
439 | pid_t h2o_pid = task->tgid;
440 | pid_t h2o_tid = task->pid;
441 | if (!(h2o_pid == H2OLOG_H2O_PID && h2o_tid == H2OLOG_H2O_PID)) {
442 | return 0;
443 | }
444 | struct quic_event_t ev = { .id = 1 };
445 | events.perf_submit(ctx, &ev, sizeof(ev));
446 | return 0;
447 | }
448 |
449 | // quicly:connect
450 | int trace_quicly__connect(struct pt_regs *ctx) {
451 | void *buf = NULL;
452 | struct quic_event_t event = { .id = 2 };
453 |
454 | // struct st_quicly_conn_t * conn
455 | struct st_quicly_conn_t conn = {};
456 | bpf_usdt_readarg(1, ctx, &buf);
457 | bpf_probe_read(&conn, sizeof(conn), buf);
458 | event.connect.master_id = conn.master_id; /* uint32_t */
459 | // int64_t at
460 | bpf_usdt_readarg(2, ctx, &event.connect.at);
461 | // uint32_t version
462 | bpf_usdt_readarg(3, ctx, &event.connect.version);
463 |
464 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
465 | bpf_trace_printk("failed to perf_submit\n");
466 |
467 | return 0;
468 | }
469 | // quicly:accept
470 | int trace_quicly__accept(struct pt_regs *ctx) {
471 | void *buf = NULL;
472 | struct quic_event_t event = { .id = 3 };
473 |
474 | // struct st_quicly_conn_t * conn
475 | struct st_quicly_conn_t conn = {};
476 | bpf_usdt_readarg(1, ctx, &buf);
477 | bpf_probe_read(&conn, sizeof(conn), buf);
478 | event.accept.master_id = conn.master_id; /* uint32_t */
479 | // int64_t at
480 | bpf_usdt_readarg(2, ctx, &event.accept.at);
481 | // const char * dcid
482 | bpf_usdt_readarg(3, ctx, &buf);
483 | bpf_probe_read(&event.accept.dcid, sizeof(event.accept.dcid), buf);
484 | // struct st_quicly_address_token_plaintext_t * address_token
485 | struct st_quicly_address_token_plaintext_t address_token = {};
486 | bpf_usdt_readarg(4, ctx, &buf);
487 | bpf_probe_read(&address_token, sizeof(address_token), buf);
488 |
489 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
490 | bpf_trace_printk("failed to perf_submit\n");
491 |
492 | return 0;
493 | }
494 | // quicly:free
495 | int trace_quicly__free(struct pt_regs *ctx) {
496 | void *buf = NULL;
497 | struct quic_event_t event = { .id = 4 };
498 |
499 | // struct st_quicly_conn_t * conn
500 | struct st_quicly_conn_t conn = {};
501 | bpf_usdt_readarg(1, ctx, &buf);
502 | bpf_probe_read(&conn, sizeof(conn), buf);
503 | event.free.master_id = conn.master_id; /* uint32_t */
504 | // int64_t at
505 | bpf_usdt_readarg(2, ctx, &event.free.at);
506 |
507 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
508 | bpf_trace_printk("failed to perf_submit\n");
509 |
510 | return 0;
511 | }
512 | // quicly:send
513 | int trace_quicly__send(struct pt_regs *ctx) {
514 | void *buf = NULL;
515 | struct quic_event_t event = { .id = 5 };
516 |
517 | // struct st_quicly_conn_t * conn
518 | struct st_quicly_conn_t conn = {};
519 | bpf_usdt_readarg(1, ctx, &buf);
520 | bpf_probe_read(&conn, sizeof(conn), buf);
521 | event.send.master_id = conn.master_id; /* uint32_t */
522 | // int64_t at
523 | bpf_usdt_readarg(2, ctx, &event.send.at);
524 | // int state
525 | bpf_usdt_readarg(3, ctx, &event.send.state);
526 | // const char * dcid
527 | bpf_usdt_readarg(4, ctx, &buf);
528 | bpf_probe_read(&event.send.dcid, sizeof(event.send.dcid), buf);
529 |
530 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
531 | bpf_trace_printk("failed to perf_submit\n");
532 |
533 | return 0;
534 | }
535 | // quicly:receive
536 | int trace_quicly__receive(struct pt_regs *ctx) {
537 | void *buf = NULL;
538 | struct quic_event_t event = { .id = 6 };
539 |
540 | // struct st_quicly_conn_t * conn
541 | struct st_quicly_conn_t conn = {};
542 | bpf_usdt_readarg(1, ctx, &buf);
543 | bpf_probe_read(&conn, sizeof(conn), buf);
544 | event.receive.master_id = conn.master_id; /* uint32_t */
545 | // int64_t at
546 | bpf_usdt_readarg(2, ctx, &event.receive.at);
547 | // const char * dcid
548 | bpf_usdt_readarg(3, ctx, &buf);
549 | bpf_probe_read(&event.receive.dcid, sizeof(event.receive.dcid), buf);
550 | // const void * bytes
551 | bpf_usdt_readarg(4, ctx, &buf);
552 | bpf_probe_read(&event.receive.bytes, sizeof(event.receive.bytes), buf);
553 | // size_t num_bytes
554 | bpf_usdt_readarg(5, ctx, &event.receive.num_bytes);
555 |
556 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
557 | bpf_trace_printk("failed to perf_submit\n");
558 |
559 | return 0;
560 | }
561 | // quicly:version_switch
562 | int trace_quicly__version_switch(struct pt_regs *ctx) {
563 | void *buf = NULL;
564 | struct quic_event_t event = { .id = 7 };
565 |
566 | // struct st_quicly_conn_t * conn
567 | struct st_quicly_conn_t conn = {};
568 | bpf_usdt_readarg(1, ctx, &buf);
569 | bpf_probe_read(&conn, sizeof(conn), buf);
570 | event.version_switch.master_id = conn.master_id; /* uint32_t */
571 | // int64_t at
572 | bpf_usdt_readarg(2, ctx, &event.version_switch.at);
573 | // uint32_t new_version
574 | bpf_usdt_readarg(3, ctx, &event.version_switch.new_version);
575 |
576 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
577 | bpf_trace_printk("failed to perf_submit\n");
578 |
579 | return 0;
580 | }
581 | // quicly:idle_timeout
582 | int trace_quicly__idle_timeout(struct pt_regs *ctx) {
583 | void *buf = NULL;
584 | struct quic_event_t event = { .id = 8 };
585 |
586 | // struct st_quicly_conn_t * conn
587 | struct st_quicly_conn_t conn = {};
588 | bpf_usdt_readarg(1, ctx, &buf);
589 | bpf_probe_read(&conn, sizeof(conn), buf);
590 | event.idle_timeout.master_id = conn.master_id; /* uint32_t */
591 | // int64_t at
592 | bpf_usdt_readarg(2, ctx, &event.idle_timeout.at);
593 |
594 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
595 | bpf_trace_printk("failed to perf_submit\n");
596 |
597 | return 0;
598 | }
599 | // quicly:stateless_reset_receive
600 | int trace_quicly__stateless_reset_receive(struct pt_regs *ctx) {
601 | void *buf = NULL;
602 | struct quic_event_t event = { .id = 9 };
603 |
604 | // struct st_quicly_conn_t * conn
605 | struct st_quicly_conn_t conn = {};
606 | bpf_usdt_readarg(1, ctx, &buf);
607 | bpf_probe_read(&conn, sizeof(conn), buf);
608 | event.stateless_reset_receive.master_id = conn.master_id; /* uint32_t */
609 | // int64_t at
610 | bpf_usdt_readarg(2, ctx, &event.stateless_reset_receive.at);
611 |
612 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
613 | bpf_trace_printk("failed to perf_submit\n");
614 |
615 | return 0;
616 | }
617 | // quicly:crypto_decrypt
618 | int trace_quicly__crypto_decrypt(struct pt_regs *ctx) {
619 | void *buf = NULL;
620 | struct quic_event_t event = { .id = 10 };
621 |
622 | // struct st_quicly_conn_t * conn
623 | struct st_quicly_conn_t conn = {};
624 | bpf_usdt_readarg(1, ctx, &buf);
625 | bpf_probe_read(&conn, sizeof(conn), buf);
626 | event.crypto_decrypt.master_id = conn.master_id; /* uint32_t */
627 | // int64_t at
628 | bpf_usdt_readarg(2, ctx, &event.crypto_decrypt.at);
629 | // uint64_t pn
630 | bpf_usdt_readarg(3, ctx, &event.crypto_decrypt.pn);
631 | // const void * decrypted (ignored)
632 | // size_t decrypted_len
633 | bpf_usdt_readarg(5, ctx, &event.crypto_decrypt.decrypted_len);
634 |
635 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
636 | bpf_trace_printk("failed to perf_submit\n");
637 |
638 | return 0;
639 | }
640 | // quicly:crypto_handshake
641 | int trace_quicly__crypto_handshake(struct pt_regs *ctx) {
642 | void *buf = NULL;
643 | struct quic_event_t event = { .id = 11 };
644 |
645 | // struct st_quicly_conn_t * conn
646 | struct st_quicly_conn_t conn = {};
647 | bpf_usdt_readarg(1, ctx, &buf);
648 | bpf_probe_read(&conn, sizeof(conn), buf);
649 | event.crypto_handshake.master_id = conn.master_id; /* uint32_t */
650 | // int64_t at
651 | bpf_usdt_readarg(2, ctx, &event.crypto_handshake.at);
652 | // int ret
653 | bpf_usdt_readarg(3, ctx, &event.crypto_handshake.ret);
654 |
655 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
656 | bpf_trace_printk("failed to perf_submit\n");
657 |
658 | return 0;
659 | }
660 | // quicly:crypto_update_secret
661 | int trace_quicly__crypto_update_secret(struct pt_regs *ctx) {
662 | void *buf = NULL;
663 | struct quic_event_t event = { .id = 12 };
664 |
665 | // struct st_quicly_conn_t * conn
666 | struct st_quicly_conn_t conn = {};
667 | bpf_usdt_readarg(1, ctx, &buf);
668 | bpf_probe_read(&conn, sizeof(conn), buf);
669 | event.crypto_update_secret.master_id = conn.master_id; /* uint32_t */
670 | // int64_t at
671 | bpf_usdt_readarg(2, ctx, &event.crypto_update_secret.at);
672 | // int is_enc
673 | bpf_usdt_readarg(3, ctx, &event.crypto_update_secret.is_enc);
674 | // uint8_t epoch
675 | bpf_usdt_readarg(4, ctx, &event.crypto_update_secret.epoch);
676 | // const char * label
677 | bpf_usdt_readarg(5, ctx, &buf);
678 | bpf_probe_read(&event.crypto_update_secret.label, sizeof(event.crypto_update_secret.label), buf);
679 | // const char * secret (ignored)
680 |
681 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
682 | bpf_trace_printk("failed to perf_submit\n");
683 |
684 | return 0;
685 | }
686 | // quicly:crypto_send_key_update
687 | int trace_quicly__crypto_send_key_update(struct pt_regs *ctx) {
688 | void *buf = NULL;
689 | struct quic_event_t event = { .id = 13 };
690 |
691 | // struct st_quicly_conn_t * conn
692 | struct st_quicly_conn_t conn = {};
693 | bpf_usdt_readarg(1, ctx, &buf);
694 | bpf_probe_read(&conn, sizeof(conn), buf);
695 | event.crypto_send_key_update.master_id = conn.master_id; /* uint32_t */
696 | // int64_t at
697 | bpf_usdt_readarg(2, ctx, &event.crypto_send_key_update.at);
698 | // uint64_t phase
699 | bpf_usdt_readarg(3, ctx, &event.crypto_send_key_update.phase);
700 | // const char * secret (ignored)
701 |
702 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
703 | bpf_trace_printk("failed to perf_submit\n");
704 |
705 | return 0;
706 | }
707 | // quicly:crypto_send_key_update_confirmed
708 | int trace_quicly__crypto_send_key_update_confirmed(struct pt_regs *ctx) {
709 | void *buf = NULL;
710 | struct quic_event_t event = { .id = 14 };
711 |
712 | // struct st_quicly_conn_t * conn
713 | struct st_quicly_conn_t conn = {};
714 | bpf_usdt_readarg(1, ctx, &buf);
715 | bpf_probe_read(&conn, sizeof(conn), buf);
716 | event.crypto_send_key_update_confirmed.master_id = conn.master_id; /* uint32_t */
717 | // int64_t at
718 | bpf_usdt_readarg(2, ctx, &event.crypto_send_key_update_confirmed.at);
719 | // uint64_t next_pn
720 | bpf_usdt_readarg(3, ctx, &event.crypto_send_key_update_confirmed.next_pn);
721 |
722 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
723 | bpf_trace_printk("failed to perf_submit\n");
724 |
725 | return 0;
726 | }
727 | // quicly:crypto_receive_key_update
728 | int trace_quicly__crypto_receive_key_update(struct pt_regs *ctx) {
729 | void *buf = NULL;
730 | struct quic_event_t event = { .id = 15 };
731 |
732 | // struct st_quicly_conn_t * conn
733 | struct st_quicly_conn_t conn = {};
734 | bpf_usdt_readarg(1, ctx, &buf);
735 | bpf_probe_read(&conn, sizeof(conn), buf);
736 | event.crypto_receive_key_update.master_id = conn.master_id; /* uint32_t */
737 | // int64_t at
738 | bpf_usdt_readarg(2, ctx, &event.crypto_receive_key_update.at);
739 | // uint64_t phase
740 | bpf_usdt_readarg(3, ctx, &event.crypto_receive_key_update.phase);
741 | // const char * secret (ignored)
742 |
743 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
744 | bpf_trace_printk("failed to perf_submit\n");
745 |
746 | return 0;
747 | }
748 | // quicly:crypto_receive_key_update_prepare
749 | int trace_quicly__crypto_receive_key_update_prepare(struct pt_regs *ctx) {
750 | void *buf = NULL;
751 | struct quic_event_t event = { .id = 16 };
752 |
753 | // struct st_quicly_conn_t * conn
754 | struct st_quicly_conn_t conn = {};
755 | bpf_usdt_readarg(1, ctx, &buf);
756 | bpf_probe_read(&conn, sizeof(conn), buf);
757 | event.crypto_receive_key_update_prepare.master_id = conn.master_id; /* uint32_t */
758 | // int64_t at
759 | bpf_usdt_readarg(2, ctx, &event.crypto_receive_key_update_prepare.at);
760 | // uint64_t phase
761 | bpf_usdt_readarg(3, ctx, &event.crypto_receive_key_update_prepare.phase);
762 | // const char * secret (ignored)
763 |
764 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
765 | bpf_trace_printk("failed to perf_submit\n");
766 |
767 | return 0;
768 | }
769 | // quicly:packet_prepare
770 | int trace_quicly__packet_prepare(struct pt_regs *ctx) {
771 | void *buf = NULL;
772 | struct quic_event_t event = { .id = 17 };
773 |
774 | // struct st_quicly_conn_t * conn
775 | struct st_quicly_conn_t conn = {};
776 | bpf_usdt_readarg(1, ctx, &buf);
777 | bpf_probe_read(&conn, sizeof(conn), buf);
778 | event.packet_prepare.master_id = conn.master_id; /* uint32_t */
779 | // int64_t at
780 | bpf_usdt_readarg(2, ctx, &event.packet_prepare.at);
781 | // uint8_t first_octet
782 | bpf_usdt_readarg(3, ctx, &event.packet_prepare.first_octet);
783 | // const char * dcid
784 | bpf_usdt_readarg(4, ctx, &buf);
785 | bpf_probe_read(&event.packet_prepare.dcid, sizeof(event.packet_prepare.dcid), buf);
786 |
787 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
788 | bpf_trace_printk("failed to perf_submit\n");
789 |
790 | return 0;
791 | }
792 | // quicly:packet_commit
793 | int trace_quicly__packet_commit(struct pt_regs *ctx) {
794 | void *buf = NULL;
795 | struct quic_event_t event = { .id = 18 };
796 |
797 | // struct st_quicly_conn_t * conn
798 | struct st_quicly_conn_t conn = {};
799 | bpf_usdt_readarg(1, ctx, &buf);
800 | bpf_probe_read(&conn, sizeof(conn), buf);
801 | event.packet_commit.master_id = conn.master_id; /* uint32_t */
802 | // int64_t at
803 | bpf_usdt_readarg(2, ctx, &event.packet_commit.at);
804 | // uint64_t pn
805 | bpf_usdt_readarg(3, ctx, &event.packet_commit.pn);
806 | // size_t len
807 | bpf_usdt_readarg(4, ctx, &event.packet_commit.len);
808 | // int ack_only
809 | bpf_usdt_readarg(5, ctx, &event.packet_commit.ack_only);
810 |
811 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
812 | bpf_trace_printk("failed to perf_submit\n");
813 |
814 | return 0;
815 | }
816 | // quicly:packet_acked
817 | int trace_quicly__packet_acked(struct pt_regs *ctx) {
818 | void *buf = NULL;
819 | struct quic_event_t event = { .id = 19 };
820 |
821 | // struct st_quicly_conn_t * conn
822 | struct st_quicly_conn_t conn = {};
823 | bpf_usdt_readarg(1, ctx, &buf);
824 | bpf_probe_read(&conn, sizeof(conn), buf);
825 | event.packet_acked.master_id = conn.master_id; /* uint32_t */
826 | // int64_t at
827 | bpf_usdt_readarg(2, ctx, &event.packet_acked.at);
828 | // uint64_t pn
829 | bpf_usdt_readarg(3, ctx, &event.packet_acked.pn);
830 | // int newly_acked
831 | bpf_usdt_readarg(4, ctx, &event.packet_acked.newly_acked);
832 |
833 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
834 | bpf_trace_printk("failed to perf_submit\n");
835 |
836 | return 0;
837 | }
838 | // quicly:packet_lost
839 | int trace_quicly__packet_lost(struct pt_regs *ctx) {
840 | void *buf = NULL;
841 | struct quic_event_t event = { .id = 20 };
842 |
843 | // struct st_quicly_conn_t * conn
844 | struct st_quicly_conn_t conn = {};
845 | bpf_usdt_readarg(1, ctx, &buf);
846 | bpf_probe_read(&conn, sizeof(conn), buf);
847 | event.packet_lost.master_id = conn.master_id; /* uint32_t */
848 | // int64_t at
849 | bpf_usdt_readarg(2, ctx, &event.packet_lost.at);
850 | // uint64_t pn
851 | bpf_usdt_readarg(3, ctx, &event.packet_lost.pn);
852 |
853 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
854 | bpf_trace_printk("failed to perf_submit\n");
855 |
856 | return 0;
857 | }
858 | // quicly:pto
859 | int trace_quicly__pto(struct pt_regs *ctx) {
860 | void *buf = NULL;
861 | struct quic_event_t event = { .id = 21 };
862 |
863 | // struct st_quicly_conn_t * conn
864 | struct st_quicly_conn_t conn = {};
865 | bpf_usdt_readarg(1, ctx, &buf);
866 | bpf_probe_read(&conn, sizeof(conn), buf);
867 | event.pto.master_id = conn.master_id; /* uint32_t */
868 | // int64_t at
869 | bpf_usdt_readarg(2, ctx, &event.pto.at);
870 | // size_t inflight
871 | bpf_usdt_readarg(3, ctx, &event.pto.inflight);
872 | // uint32_t cwnd
873 | bpf_usdt_readarg(4, ctx, &event.pto.cwnd);
874 | // int8_t pto_count
875 | bpf_usdt_readarg(5, ctx, &event.pto.pto_count);
876 |
877 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
878 | bpf_trace_printk("failed to perf_submit\n");
879 |
880 | return 0;
881 | }
882 | // quicly:cc_ack_received
883 | int trace_quicly__cc_ack_received(struct pt_regs *ctx) {
884 | void *buf = NULL;
885 | struct quic_event_t event = { .id = 22 };
886 |
887 | // struct st_quicly_conn_t * conn
888 | struct st_quicly_conn_t conn = {};
889 | bpf_usdt_readarg(1, ctx, &buf);
890 | bpf_probe_read(&conn, sizeof(conn), buf);
891 | event.cc_ack_received.master_id = conn.master_id; /* uint32_t */
892 | // int64_t at
893 | bpf_usdt_readarg(2, ctx, &event.cc_ack_received.at);
894 | // uint64_t largest_acked
895 | bpf_usdt_readarg(3, ctx, &event.cc_ack_received.largest_acked);
896 | // size_t bytes_acked
897 | bpf_usdt_readarg(4, ctx, &event.cc_ack_received.bytes_acked);
898 | // uint32_t cwnd
899 | bpf_usdt_readarg(5, ctx, &event.cc_ack_received.cwnd);
900 | // size_t inflight
901 | bpf_usdt_readarg(6, ctx, &event.cc_ack_received.inflight);
902 |
903 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
904 | bpf_trace_printk("failed to perf_submit\n");
905 |
906 | return 0;
907 | }
908 | // quicly:cc_congestion
909 | int trace_quicly__cc_congestion(struct pt_regs *ctx) {
910 | void *buf = NULL;
911 | struct quic_event_t event = { .id = 23 };
912 |
913 | // struct st_quicly_conn_t * conn
914 | struct st_quicly_conn_t conn = {};
915 | bpf_usdt_readarg(1, ctx, &buf);
916 | bpf_probe_read(&conn, sizeof(conn), buf);
917 | event.cc_congestion.master_id = conn.master_id; /* uint32_t */
918 | // int64_t at
919 | bpf_usdt_readarg(2, ctx, &event.cc_congestion.at);
920 | // uint64_t max_lost_pn
921 | bpf_usdt_readarg(3, ctx, &event.cc_congestion.max_lost_pn);
922 | // size_t inflight
923 | bpf_usdt_readarg(4, ctx, &event.cc_congestion.inflight);
924 | // uint32_t cwnd
925 | bpf_usdt_readarg(5, ctx, &event.cc_congestion.cwnd);
926 |
927 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
928 | bpf_trace_printk("failed to perf_submit\n");
929 |
930 | return 0;
931 | }
932 | // quicly:transport_close_send
933 | int trace_quicly__transport_close_send(struct pt_regs *ctx) {
934 | void *buf = NULL;
935 | struct quic_event_t event = { .id = 24 };
936 |
937 | // struct st_quicly_conn_t * conn
938 | struct st_quicly_conn_t conn = {};
939 | bpf_usdt_readarg(1, ctx, &buf);
940 | bpf_probe_read(&conn, sizeof(conn), buf);
941 | event.transport_close_send.master_id = conn.master_id; /* uint32_t */
942 | // int64_t at
943 | bpf_usdt_readarg(2, ctx, &event.transport_close_send.at);
944 | // uint64_t error_code
945 | bpf_usdt_readarg(3, ctx, &event.transport_close_send.error_code);
946 | // uint64_t frame_type
947 | bpf_usdt_readarg(4, ctx, &event.transport_close_send.frame_type);
948 | // const char * reason_phrase
949 | bpf_usdt_readarg(5, ctx, &buf);
950 | bpf_probe_read(&event.transport_close_send.reason_phrase, sizeof(event.transport_close_send.reason_phrase), buf);
951 |
952 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
953 | bpf_trace_printk("failed to perf_submit\n");
954 |
955 | return 0;
956 | }
957 | // quicly:transport_close_receive
958 | int trace_quicly__transport_close_receive(struct pt_regs *ctx) {
959 | void *buf = NULL;
960 | struct quic_event_t event = { .id = 25 };
961 |
962 | // struct st_quicly_conn_t * conn
963 | struct st_quicly_conn_t conn = {};
964 | bpf_usdt_readarg(1, ctx, &buf);
965 | bpf_probe_read(&conn, sizeof(conn), buf);
966 | event.transport_close_receive.master_id = conn.master_id; /* uint32_t */
967 | // int64_t at
968 | bpf_usdt_readarg(2, ctx, &event.transport_close_receive.at);
969 | // uint64_t error_code
970 | bpf_usdt_readarg(3, ctx, &event.transport_close_receive.error_code);
971 | // uint64_t frame_type
972 | bpf_usdt_readarg(4, ctx, &event.transport_close_receive.frame_type);
973 | // const char * reason_phrase
974 | bpf_usdt_readarg(5, ctx, &buf);
975 | bpf_probe_read(&event.transport_close_receive.reason_phrase, sizeof(event.transport_close_receive.reason_phrase), buf);
976 |
977 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
978 | bpf_trace_printk("failed to perf_submit\n");
979 |
980 | return 0;
981 | }
982 | // quicly:application_close_send
983 | int trace_quicly__application_close_send(struct pt_regs *ctx) {
984 | void *buf = NULL;
985 | struct quic_event_t event = { .id = 26 };
986 |
987 | // struct st_quicly_conn_t * conn
988 | struct st_quicly_conn_t conn = {};
989 | bpf_usdt_readarg(1, ctx, &buf);
990 | bpf_probe_read(&conn, sizeof(conn), buf);
991 | event.application_close_send.master_id = conn.master_id; /* uint32_t */
992 | // int64_t at
993 | bpf_usdt_readarg(2, ctx, &event.application_close_send.at);
994 | // uint64_t error_code
995 | bpf_usdt_readarg(3, ctx, &event.application_close_send.error_code);
996 | // const char * reason_phrase
997 | bpf_usdt_readarg(4, ctx, &buf);
998 | bpf_probe_read(&event.application_close_send.reason_phrase, sizeof(event.application_close_send.reason_phrase), buf);
999 |
1000 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1001 | bpf_trace_printk("failed to perf_submit\n");
1002 |
1003 | return 0;
1004 | }
1005 | // quicly:application_close_receive
1006 | int trace_quicly__application_close_receive(struct pt_regs *ctx) {
1007 | void *buf = NULL;
1008 | struct quic_event_t event = { .id = 27 };
1009 |
1010 | // struct st_quicly_conn_t * conn
1011 | struct st_quicly_conn_t conn = {};
1012 | bpf_usdt_readarg(1, ctx, &buf);
1013 | bpf_probe_read(&conn, sizeof(conn), buf);
1014 | event.application_close_receive.master_id = conn.master_id; /* uint32_t */
1015 | // int64_t at
1016 | bpf_usdt_readarg(2, ctx, &event.application_close_receive.at);
1017 | // uint64_t error_code
1018 | bpf_usdt_readarg(3, ctx, &event.application_close_receive.error_code);
1019 | // const char * reason_phrase
1020 | bpf_usdt_readarg(4, ctx, &buf);
1021 | bpf_probe_read(&event.application_close_receive.reason_phrase, sizeof(event.application_close_receive.reason_phrase), buf);
1022 |
1023 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1024 | bpf_trace_printk("failed to perf_submit\n");
1025 |
1026 | return 0;
1027 | }
1028 | // quicly:stream_send
1029 | int trace_quicly__stream_send(struct pt_regs *ctx) {
1030 | void *buf = NULL;
1031 | struct quic_event_t event = { .id = 28 };
1032 |
1033 | // struct st_quicly_conn_t * conn
1034 | struct st_quicly_conn_t conn = {};
1035 | bpf_usdt_readarg(1, ctx, &buf);
1036 | bpf_probe_read(&conn, sizeof(conn), buf);
1037 | event.stream_send.master_id = conn.master_id; /* uint32_t */
1038 | // int64_t at
1039 | bpf_usdt_readarg(2, ctx, &event.stream_send.at);
1040 | // struct st_quicly_stream_t * stream
1041 | struct st_quicly_stream_t stream = {};
1042 | bpf_usdt_readarg(3, ctx, &buf);
1043 | bpf_probe_read(&stream, sizeof(stream), buf);
1044 | event.stream_send.stream_id = stream.stream_id; /* int64_t */
1045 | // uint64_t off
1046 | bpf_usdt_readarg(4, ctx, &event.stream_send.off);
1047 | // size_t len
1048 | bpf_usdt_readarg(5, ctx, &event.stream_send.len);
1049 | // int is_fin
1050 | bpf_usdt_readarg(6, ctx, &event.stream_send.is_fin);
1051 |
1052 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1053 | bpf_trace_printk("failed to perf_submit\n");
1054 |
1055 | return 0;
1056 | }
1057 | // quicly:stream_receive
1058 | int trace_quicly__stream_receive(struct pt_regs *ctx) {
1059 | void *buf = NULL;
1060 | struct quic_event_t event = { .id = 29 };
1061 |
1062 | // struct st_quicly_conn_t * conn
1063 | struct st_quicly_conn_t conn = {};
1064 | bpf_usdt_readarg(1, ctx, &buf);
1065 | bpf_probe_read(&conn, sizeof(conn), buf);
1066 | event.stream_receive.master_id = conn.master_id; /* uint32_t */
1067 | // int64_t at
1068 | bpf_usdt_readarg(2, ctx, &event.stream_receive.at);
1069 | // struct st_quicly_stream_t * stream
1070 | struct st_quicly_stream_t stream = {};
1071 | bpf_usdt_readarg(3, ctx, &buf);
1072 | bpf_probe_read(&stream, sizeof(stream), buf);
1073 | event.stream_receive.stream_id = stream.stream_id; /* int64_t */
1074 | // uint64_t off
1075 | bpf_usdt_readarg(4, ctx, &event.stream_receive.off);
1076 | // size_t len
1077 | bpf_usdt_readarg(5, ctx, &event.stream_receive.len);
1078 |
1079 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1080 | bpf_trace_printk("failed to perf_submit\n");
1081 |
1082 | return 0;
1083 | }
1084 | // quicly:stream_acked
1085 | int trace_quicly__stream_acked(struct pt_regs *ctx) {
1086 | void *buf = NULL;
1087 | struct quic_event_t event = { .id = 30 };
1088 |
1089 | // struct st_quicly_conn_t * conn
1090 | struct st_quicly_conn_t conn = {};
1091 | bpf_usdt_readarg(1, ctx, &buf);
1092 | bpf_probe_read(&conn, sizeof(conn), buf);
1093 | event.stream_acked.master_id = conn.master_id; /* uint32_t */
1094 | // int64_t at
1095 | bpf_usdt_readarg(2, ctx, &event.stream_acked.at);
1096 | // int64_t stream_id
1097 | bpf_usdt_readarg(3, ctx, &event.stream_acked.stream_id);
1098 | // uint64_t off
1099 | bpf_usdt_readarg(4, ctx, &event.stream_acked.off);
1100 | // size_t len
1101 | bpf_usdt_readarg(5, ctx, &event.stream_acked.len);
1102 |
1103 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1104 | bpf_trace_printk("failed to perf_submit\n");
1105 |
1106 | return 0;
1107 | }
1108 | // quicly:stream_lost
1109 | int trace_quicly__stream_lost(struct pt_regs *ctx) {
1110 | void *buf = NULL;
1111 | struct quic_event_t event = { .id = 31 };
1112 |
1113 | // struct st_quicly_conn_t * conn
1114 | struct st_quicly_conn_t conn = {};
1115 | bpf_usdt_readarg(1, ctx, &buf);
1116 | bpf_probe_read(&conn, sizeof(conn), buf);
1117 | event.stream_lost.master_id = conn.master_id; /* uint32_t */
1118 | // int64_t at
1119 | bpf_usdt_readarg(2, ctx, &event.stream_lost.at);
1120 | // int64_t stream_id
1121 | bpf_usdt_readarg(3, ctx, &event.stream_lost.stream_id);
1122 | // uint64_t off
1123 | bpf_usdt_readarg(4, ctx, &event.stream_lost.off);
1124 | // size_t len
1125 | bpf_usdt_readarg(5, ctx, &event.stream_lost.len);
1126 |
1127 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1128 | bpf_trace_printk("failed to perf_submit\n");
1129 |
1130 | return 0;
1131 | }
1132 | // quicly:max_data_send
1133 | int trace_quicly__max_data_send(struct pt_regs *ctx) {
1134 | void *buf = NULL;
1135 | struct quic_event_t event = { .id = 32 };
1136 |
1137 | // struct st_quicly_conn_t * conn
1138 | struct st_quicly_conn_t conn = {};
1139 | bpf_usdt_readarg(1, ctx, &buf);
1140 | bpf_probe_read(&conn, sizeof(conn), buf);
1141 | event.max_data_send.master_id = conn.master_id; /* uint32_t */
1142 | // int64_t at
1143 | bpf_usdt_readarg(2, ctx, &event.max_data_send.at);
1144 | // uint64_t limit
1145 | bpf_usdt_readarg(3, ctx, &event.max_data_send.limit);
1146 |
1147 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1148 | bpf_trace_printk("failed to perf_submit\n");
1149 |
1150 | return 0;
1151 | }
1152 | // quicly:max_data_receive
1153 | int trace_quicly__max_data_receive(struct pt_regs *ctx) {
1154 | void *buf = NULL;
1155 | struct quic_event_t event = { .id = 33 };
1156 |
1157 | // struct st_quicly_conn_t * conn
1158 | struct st_quicly_conn_t conn = {};
1159 | bpf_usdt_readarg(1, ctx, &buf);
1160 | bpf_probe_read(&conn, sizeof(conn), buf);
1161 | event.max_data_receive.master_id = conn.master_id; /* uint32_t */
1162 | // int64_t at
1163 | bpf_usdt_readarg(2, ctx, &event.max_data_receive.at);
1164 | // uint64_t limit
1165 | bpf_usdt_readarg(3, ctx, &event.max_data_receive.limit);
1166 |
1167 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1168 | bpf_trace_printk("failed to perf_submit\n");
1169 |
1170 | return 0;
1171 | }
1172 | // quicly:max_streams_send
1173 | int trace_quicly__max_streams_send(struct pt_regs *ctx) {
1174 | void *buf = NULL;
1175 | struct quic_event_t event = { .id = 34 };
1176 |
1177 | // struct st_quicly_conn_t * conn
1178 | struct st_quicly_conn_t conn = {};
1179 | bpf_usdt_readarg(1, ctx, &buf);
1180 | bpf_probe_read(&conn, sizeof(conn), buf);
1181 | event.max_streams_send.master_id = conn.master_id; /* uint32_t */
1182 | // int64_t at
1183 | bpf_usdt_readarg(2, ctx, &event.max_streams_send.at);
1184 | // uint64_t limit
1185 | bpf_usdt_readarg(3, ctx, &event.max_streams_send.limit);
1186 | // int is_unidirectional
1187 | bpf_usdt_readarg(4, ctx, &event.max_streams_send.is_unidirectional);
1188 |
1189 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1190 | bpf_trace_printk("failed to perf_submit\n");
1191 |
1192 | return 0;
1193 | }
1194 | // quicly:max_streams_receive
1195 | int trace_quicly__max_streams_receive(struct pt_regs *ctx) {
1196 | void *buf = NULL;
1197 | struct quic_event_t event = { .id = 35 };
1198 |
1199 | // struct st_quicly_conn_t * conn
1200 | struct st_quicly_conn_t conn = {};
1201 | bpf_usdt_readarg(1, ctx, &buf);
1202 | bpf_probe_read(&conn, sizeof(conn), buf);
1203 | event.max_streams_receive.master_id = conn.master_id; /* uint32_t */
1204 | // int64_t at
1205 | bpf_usdt_readarg(2, ctx, &event.max_streams_receive.at);
1206 | // uint64_t limit
1207 | bpf_usdt_readarg(3, ctx, &event.max_streams_receive.limit);
1208 | // int is_unidirectional
1209 | bpf_usdt_readarg(4, ctx, &event.max_streams_receive.is_unidirectional);
1210 |
1211 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1212 | bpf_trace_printk("failed to perf_submit\n");
1213 |
1214 | return 0;
1215 | }
1216 | // quicly:max_stream_data_send
1217 | int trace_quicly__max_stream_data_send(struct pt_regs *ctx) {
1218 | void *buf = NULL;
1219 | struct quic_event_t event = { .id = 36 };
1220 |
1221 | // struct st_quicly_conn_t * conn
1222 | struct st_quicly_conn_t conn = {};
1223 | bpf_usdt_readarg(1, ctx, &buf);
1224 | bpf_probe_read(&conn, sizeof(conn), buf);
1225 | event.max_stream_data_send.master_id = conn.master_id; /* uint32_t */
1226 | // int64_t at
1227 | bpf_usdt_readarg(2, ctx, &event.max_stream_data_send.at);
1228 | // struct st_quicly_stream_t * stream
1229 | struct st_quicly_stream_t stream = {};
1230 | bpf_usdt_readarg(3, ctx, &buf);
1231 | bpf_probe_read(&stream, sizeof(stream), buf);
1232 | event.max_stream_data_send.stream_id = stream.stream_id; /* int64_t */
1233 | // uint64_t limit
1234 | bpf_usdt_readarg(4, ctx, &event.max_stream_data_send.limit);
1235 |
1236 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1237 | bpf_trace_printk("failed to perf_submit\n");
1238 |
1239 | return 0;
1240 | }
1241 | // quicly:max_stream_data_receive
1242 | int trace_quicly__max_stream_data_receive(struct pt_regs *ctx) {
1243 | void *buf = NULL;
1244 | struct quic_event_t event = { .id = 37 };
1245 |
1246 | // struct st_quicly_conn_t * conn
1247 | struct st_quicly_conn_t conn = {};
1248 | bpf_usdt_readarg(1, ctx, &buf);
1249 | bpf_probe_read(&conn, sizeof(conn), buf);
1250 | event.max_stream_data_receive.master_id = conn.master_id; /* uint32_t */
1251 | // int64_t at
1252 | bpf_usdt_readarg(2, ctx, &event.max_stream_data_receive.at);
1253 | // int64_t stream_id
1254 | bpf_usdt_readarg(3, ctx, &event.max_stream_data_receive.stream_id);
1255 | // uint64_t limit
1256 | bpf_usdt_readarg(4, ctx, &event.max_stream_data_receive.limit);
1257 |
1258 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1259 | bpf_trace_printk("failed to perf_submit\n");
1260 |
1261 | return 0;
1262 | }
1263 | // quicly:new_token_send
1264 | int trace_quicly__new_token_send(struct pt_regs *ctx) {
1265 | void *buf = NULL;
1266 | struct quic_event_t event = { .id = 38 };
1267 |
1268 | // struct st_quicly_conn_t * conn
1269 | struct st_quicly_conn_t conn = {};
1270 | bpf_usdt_readarg(1, ctx, &buf);
1271 | bpf_probe_read(&conn, sizeof(conn), buf);
1272 | event.new_token_send.master_id = conn.master_id; /* uint32_t */
1273 | // int64_t at
1274 | bpf_usdt_readarg(2, ctx, &event.new_token_send.at);
1275 | // uint8_t * token
1276 | bpf_usdt_readarg(3, ctx, &buf);
1277 | bpf_probe_read(&event.new_token_send.token, sizeof(event.new_token_send.token), buf);
1278 | // size_t len
1279 | bpf_usdt_readarg(4, ctx, &event.new_token_send.len);
1280 | // uint64_t generation
1281 | bpf_usdt_readarg(5, ctx, &event.new_token_send.generation);
1282 |
1283 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1284 | bpf_trace_printk("failed to perf_submit\n");
1285 |
1286 | return 0;
1287 | }
1288 | // quicly:new_token_acked
1289 | int trace_quicly__new_token_acked(struct pt_regs *ctx) {
1290 | void *buf = NULL;
1291 | struct quic_event_t event = { .id = 39 };
1292 |
1293 | // struct st_quicly_conn_t * conn
1294 | struct st_quicly_conn_t conn = {};
1295 | bpf_usdt_readarg(1, ctx, &buf);
1296 | bpf_probe_read(&conn, sizeof(conn), buf);
1297 | event.new_token_acked.master_id = conn.master_id; /* uint32_t */
1298 | // int64_t at
1299 | bpf_usdt_readarg(2, ctx, &event.new_token_acked.at);
1300 | // uint64_t generation
1301 | bpf_usdt_readarg(3, ctx, &event.new_token_acked.generation);
1302 |
1303 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1304 | bpf_trace_printk("failed to perf_submit\n");
1305 |
1306 | return 0;
1307 | }
1308 | // quicly:new_token_receive
1309 | int trace_quicly__new_token_receive(struct pt_regs *ctx) {
1310 | void *buf = NULL;
1311 | struct quic_event_t event = { .id = 40 };
1312 |
1313 | // struct st_quicly_conn_t * conn
1314 | struct st_quicly_conn_t conn = {};
1315 | bpf_usdt_readarg(1, ctx, &buf);
1316 | bpf_probe_read(&conn, sizeof(conn), buf);
1317 | event.new_token_receive.master_id = conn.master_id; /* uint32_t */
1318 | // int64_t at
1319 | bpf_usdt_readarg(2, ctx, &event.new_token_receive.at);
1320 | // uint8_t * token
1321 | bpf_usdt_readarg(3, ctx, &buf);
1322 | bpf_probe_read(&event.new_token_receive.token, sizeof(event.new_token_receive.token), buf);
1323 | // size_t len
1324 | bpf_usdt_readarg(4, ctx, &event.new_token_receive.len);
1325 |
1326 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1327 | bpf_trace_printk("failed to perf_submit\n");
1328 |
1329 | return 0;
1330 | }
1331 | // quicly:handshake_done_send
1332 | int trace_quicly__handshake_done_send(struct pt_regs *ctx) {
1333 | void *buf = NULL;
1334 | struct quic_event_t event = { .id = 41 };
1335 |
1336 | // struct st_quicly_conn_t * conn
1337 | struct st_quicly_conn_t conn = {};
1338 | bpf_usdt_readarg(1, ctx, &buf);
1339 | bpf_probe_read(&conn, sizeof(conn), buf);
1340 | event.handshake_done_send.master_id = conn.master_id; /* uint32_t */
1341 | // int64_t at
1342 | bpf_usdt_readarg(2, ctx, &event.handshake_done_send.at);
1343 |
1344 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1345 | bpf_trace_printk("failed to perf_submit\n");
1346 |
1347 | return 0;
1348 | }
1349 | // quicly:handshake_done_receive
1350 | int trace_quicly__handshake_done_receive(struct pt_regs *ctx) {
1351 | void *buf = NULL;
1352 | struct quic_event_t event = { .id = 42 };
1353 |
1354 | // struct st_quicly_conn_t * conn
1355 | struct st_quicly_conn_t conn = {};
1356 | bpf_usdt_readarg(1, ctx, &buf);
1357 | bpf_probe_read(&conn, sizeof(conn), buf);
1358 | event.handshake_done_receive.master_id = conn.master_id; /* uint32_t */
1359 | // int64_t at
1360 | bpf_usdt_readarg(2, ctx, &event.handshake_done_receive.at);
1361 |
1362 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1363 | bpf_trace_printk("failed to perf_submit\n");
1364 |
1365 | return 0;
1366 | }
1367 | // quicly:streams_blocked_send
1368 | int trace_quicly__streams_blocked_send(struct pt_regs *ctx) {
1369 | void *buf = NULL;
1370 | struct quic_event_t event = { .id = 43 };
1371 |
1372 | // struct st_quicly_conn_t * conn
1373 | struct st_quicly_conn_t conn = {};
1374 | bpf_usdt_readarg(1, ctx, &buf);
1375 | bpf_probe_read(&conn, sizeof(conn), buf);
1376 | event.streams_blocked_send.master_id = conn.master_id; /* uint32_t */
1377 | // int64_t at
1378 | bpf_usdt_readarg(2, ctx, &event.streams_blocked_send.at);
1379 | // uint64_t limit
1380 | bpf_usdt_readarg(3, ctx, &event.streams_blocked_send.limit);
1381 | // int is_unidirectional
1382 | bpf_usdt_readarg(4, ctx, &event.streams_blocked_send.is_unidirectional);
1383 |
1384 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1385 | bpf_trace_printk("failed to perf_submit\n");
1386 |
1387 | return 0;
1388 | }
1389 | // quicly:streams_blocked_receive
1390 | int trace_quicly__streams_blocked_receive(struct pt_regs *ctx) {
1391 | void *buf = NULL;
1392 | struct quic_event_t event = { .id = 44 };
1393 |
1394 | // struct st_quicly_conn_t * conn
1395 | struct st_quicly_conn_t conn = {};
1396 | bpf_usdt_readarg(1, ctx, &buf);
1397 | bpf_probe_read(&conn, sizeof(conn), buf);
1398 | event.streams_blocked_receive.master_id = conn.master_id; /* uint32_t */
1399 | // int64_t at
1400 | bpf_usdt_readarg(2, ctx, &event.streams_blocked_receive.at);
1401 | // uint64_t limit
1402 | bpf_usdt_readarg(3, ctx, &event.streams_blocked_receive.limit);
1403 | // int is_unidirectional
1404 | bpf_usdt_readarg(4, ctx, &event.streams_blocked_receive.is_unidirectional);
1405 |
1406 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1407 | bpf_trace_printk("failed to perf_submit\n");
1408 |
1409 | return 0;
1410 | }
1411 | // quicly:data_blocked_receive
1412 | int trace_quicly__data_blocked_receive(struct pt_regs *ctx) {
1413 | void *buf = NULL;
1414 | struct quic_event_t event = { .id = 45 };
1415 |
1416 | // struct st_quicly_conn_t * conn
1417 | struct st_quicly_conn_t conn = {};
1418 | bpf_usdt_readarg(1, ctx, &buf);
1419 | bpf_probe_read(&conn, sizeof(conn), buf);
1420 | event.data_blocked_receive.master_id = conn.master_id; /* uint32_t */
1421 | // int64_t at
1422 | bpf_usdt_readarg(2, ctx, &event.data_blocked_receive.at);
1423 | // uint64_t off
1424 | bpf_usdt_readarg(3, ctx, &event.data_blocked_receive.off);
1425 |
1426 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1427 | bpf_trace_printk("failed to perf_submit\n");
1428 |
1429 | return 0;
1430 | }
1431 | // quicly:stream_data_blocked_receive
1432 | int trace_quicly__stream_data_blocked_receive(struct pt_regs *ctx) {
1433 | void *buf = NULL;
1434 | struct quic_event_t event = { .id = 46 };
1435 |
1436 | // struct st_quicly_conn_t * conn
1437 | struct st_quicly_conn_t conn = {};
1438 | bpf_usdt_readarg(1, ctx, &buf);
1439 | bpf_probe_read(&conn, sizeof(conn), buf);
1440 | event.stream_data_blocked_receive.master_id = conn.master_id; /* uint32_t */
1441 | // int64_t at
1442 | bpf_usdt_readarg(2, ctx, &event.stream_data_blocked_receive.at);
1443 | // int64_t stream_id
1444 | bpf_usdt_readarg(3, ctx, &event.stream_data_blocked_receive.stream_id);
1445 | // uint64_t limit
1446 | bpf_usdt_readarg(4, ctx, &event.stream_data_blocked_receive.limit);
1447 |
1448 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1449 | bpf_trace_printk("failed to perf_submit\n");
1450 |
1451 | return 0;
1452 | }
1453 | // quicly:quictrace_sent
1454 | int trace_quicly__quictrace_sent(struct pt_regs *ctx) {
1455 | void *buf = NULL;
1456 | struct quic_event_t event = { .id = 47 };
1457 |
1458 | // struct st_quicly_conn_t * conn
1459 | struct st_quicly_conn_t conn = {};
1460 | bpf_usdt_readarg(1, ctx, &buf);
1461 | bpf_probe_read(&conn, sizeof(conn), buf);
1462 | event.quictrace_sent.master_id = conn.master_id; /* uint32_t */
1463 | // int64_t at
1464 | bpf_usdt_readarg(2, ctx, &event.quictrace_sent.at);
1465 | // uint64_t pn
1466 | bpf_usdt_readarg(3, ctx, &event.quictrace_sent.pn);
1467 | // size_t len
1468 | bpf_usdt_readarg(4, ctx, &event.quictrace_sent.len);
1469 | // uint8_t packet_type
1470 | bpf_usdt_readarg(5, ctx, &event.quictrace_sent.packet_type);
1471 |
1472 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1473 | bpf_trace_printk("failed to perf_submit\n");
1474 |
1475 | return 0;
1476 | }
1477 | // quicly:quictrace_recv
1478 | int trace_quicly__quictrace_recv(struct pt_regs *ctx) {
1479 | void *buf = NULL;
1480 | struct quic_event_t event = { .id = 48 };
1481 |
1482 | // struct st_quicly_conn_t * conn
1483 | struct st_quicly_conn_t conn = {};
1484 | bpf_usdt_readarg(1, ctx, &buf);
1485 | bpf_probe_read(&conn, sizeof(conn), buf);
1486 | event.quictrace_recv.master_id = conn.master_id; /* uint32_t */
1487 | // int64_t at
1488 | bpf_usdt_readarg(2, ctx, &event.quictrace_recv.at);
1489 | // uint64_t pn
1490 | bpf_usdt_readarg(3, ctx, &event.quictrace_recv.pn);
1491 |
1492 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1493 | bpf_trace_printk("failed to perf_submit\n");
1494 |
1495 | return 0;
1496 | }
1497 | // quicly:quictrace_send_stream
1498 | int trace_quicly__quictrace_send_stream(struct pt_regs *ctx) {
1499 | void *buf = NULL;
1500 | struct quic_event_t event = { .id = 49 };
1501 |
1502 | // struct st_quicly_conn_t * conn
1503 | struct st_quicly_conn_t conn = {};
1504 | bpf_usdt_readarg(1, ctx, &buf);
1505 | bpf_probe_read(&conn, sizeof(conn), buf);
1506 | event.quictrace_send_stream.master_id = conn.master_id; /* uint32_t */
1507 | // int64_t at
1508 | bpf_usdt_readarg(2, ctx, &event.quictrace_send_stream.at);
1509 | // struct st_quicly_stream_t * stream
1510 | struct st_quicly_stream_t stream = {};
1511 | bpf_usdt_readarg(3, ctx, &buf);
1512 | bpf_probe_read(&stream, sizeof(stream), buf);
1513 | event.quictrace_send_stream.stream_id = stream.stream_id; /* int64_t */
1514 | // uint64_t off
1515 | bpf_usdt_readarg(4, ctx, &event.quictrace_send_stream.off);
1516 | // size_t len
1517 | bpf_usdt_readarg(5, ctx, &event.quictrace_send_stream.len);
1518 | // int fin
1519 | bpf_usdt_readarg(6, ctx, &event.quictrace_send_stream.fin);
1520 |
1521 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1522 | bpf_trace_printk("failed to perf_submit\n");
1523 |
1524 | return 0;
1525 | }
1526 | // quicly:quictrace_recv_stream
1527 | int trace_quicly__quictrace_recv_stream(struct pt_regs *ctx) {
1528 | void *buf = NULL;
1529 | struct quic_event_t event = { .id = 50 };
1530 |
1531 | // struct st_quicly_conn_t * conn
1532 | struct st_quicly_conn_t conn = {};
1533 | bpf_usdt_readarg(1, ctx, &buf);
1534 | bpf_probe_read(&conn, sizeof(conn), buf);
1535 | event.quictrace_recv_stream.master_id = conn.master_id; /* uint32_t */
1536 | // int64_t at
1537 | bpf_usdt_readarg(2, ctx, &event.quictrace_recv_stream.at);
1538 | // int64_t stream_id
1539 | bpf_usdt_readarg(3, ctx, &event.quictrace_recv_stream.stream_id);
1540 | // uint64_t off
1541 | bpf_usdt_readarg(4, ctx, &event.quictrace_recv_stream.off);
1542 | // size_t len
1543 | bpf_usdt_readarg(5, ctx, &event.quictrace_recv_stream.len);
1544 | // int fin
1545 | bpf_usdt_readarg(6, ctx, &event.quictrace_recv_stream.fin);
1546 |
1547 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1548 | bpf_trace_printk("failed to perf_submit\n");
1549 |
1550 | return 0;
1551 | }
1552 | // quicly:quictrace_recv_ack
1553 | int trace_quicly__quictrace_recv_ack(struct pt_regs *ctx) {
1554 | void *buf = NULL;
1555 | struct quic_event_t event = { .id = 51 };
1556 |
1557 | // struct st_quicly_conn_t * conn
1558 | struct st_quicly_conn_t conn = {};
1559 | bpf_usdt_readarg(1, ctx, &buf);
1560 | bpf_probe_read(&conn, sizeof(conn), buf);
1561 | event.quictrace_recv_ack.master_id = conn.master_id; /* uint32_t */
1562 | // int64_t at
1563 | bpf_usdt_readarg(2, ctx, &event.quictrace_recv_ack.at);
1564 | // uint64_t ack_block_begin
1565 | bpf_usdt_readarg(3, ctx, &event.quictrace_recv_ack.ack_block_begin);
1566 | // uint64_t ack_block_end
1567 | bpf_usdt_readarg(4, ctx, &event.quictrace_recv_ack.ack_block_end);
1568 |
1569 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1570 | bpf_trace_printk("failed to perf_submit\n");
1571 |
1572 | return 0;
1573 | }
1574 | // quicly:quictrace_recv_ack_delay
1575 | int trace_quicly__quictrace_recv_ack_delay(struct pt_regs *ctx) {
1576 | void *buf = NULL;
1577 | struct quic_event_t event = { .id = 52 };
1578 |
1579 | // struct st_quicly_conn_t * conn
1580 | struct st_quicly_conn_t conn = {};
1581 | bpf_usdt_readarg(1, ctx, &buf);
1582 | bpf_probe_read(&conn, sizeof(conn), buf);
1583 | event.quictrace_recv_ack_delay.master_id = conn.master_id; /* uint32_t */
1584 | // int64_t at
1585 | bpf_usdt_readarg(2, ctx, &event.quictrace_recv_ack_delay.at);
1586 | // int64_t ack_delay
1587 | bpf_usdt_readarg(3, ctx, &event.quictrace_recv_ack_delay.ack_delay);
1588 |
1589 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1590 | bpf_trace_printk("failed to perf_submit\n");
1591 |
1592 | return 0;
1593 | }
1594 | // quicly:quictrace_lost
1595 | int trace_quicly__quictrace_lost(struct pt_regs *ctx) {
1596 | void *buf = NULL;
1597 | struct quic_event_t event = { .id = 53 };
1598 |
1599 | // struct st_quicly_conn_t * conn
1600 | struct st_quicly_conn_t conn = {};
1601 | bpf_usdt_readarg(1, ctx, &buf);
1602 | bpf_probe_read(&conn, sizeof(conn), buf);
1603 | event.quictrace_lost.master_id = conn.master_id; /* uint32_t */
1604 | // int64_t at
1605 | bpf_usdt_readarg(2, ctx, &event.quictrace_lost.at);
1606 | // uint64_t pn
1607 | bpf_usdt_readarg(3, ctx, &event.quictrace_lost.pn);
1608 |
1609 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1610 | bpf_trace_printk("failed to perf_submit\n");
1611 |
1612 | return 0;
1613 | }
1614 | // quicly:quictrace_cc_ack
1615 | int trace_quicly__quictrace_cc_ack(struct pt_regs *ctx) {
1616 | void *buf = NULL;
1617 | struct quic_event_t event = { .id = 54 };
1618 |
1619 | // struct st_quicly_conn_t * conn
1620 | struct st_quicly_conn_t conn = {};
1621 | bpf_usdt_readarg(1, ctx, &buf);
1622 | bpf_probe_read(&conn, sizeof(conn), buf);
1623 | event.quictrace_cc_ack.master_id = conn.master_id; /* uint32_t */
1624 | // int64_t at
1625 | bpf_usdt_readarg(2, ctx, &event.quictrace_cc_ack.at);
1626 | // struct quicly_rtt_t * rtt
1627 | struct quicly_rtt_t rtt = {};
1628 | bpf_usdt_readarg(3, ctx, &buf);
1629 | bpf_probe_read(&rtt, sizeof(rtt), buf);
1630 | event.quictrace_cc_ack.minimum = rtt.minimum; /* uint32_t */
1631 | event.quictrace_cc_ack.smoothed = rtt.smoothed; /* uint32_t */
1632 | event.quictrace_cc_ack.variance = rtt.variance; /* uint32_t */
1633 | event.quictrace_cc_ack.latest = rtt.latest; /* uint32_t */
1634 | // uint32_t cwnd
1635 | bpf_usdt_readarg(4, ctx, &event.quictrace_cc_ack.cwnd);
1636 | // size_t inflight
1637 | bpf_usdt_readarg(5, ctx, &event.quictrace_cc_ack.inflight);
1638 |
1639 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1640 | bpf_trace_printk("failed to perf_submit\n");
1641 |
1642 | return 0;
1643 | }
1644 | // quicly:quictrace_cc_lost
1645 | int trace_quicly__quictrace_cc_lost(struct pt_regs *ctx) {
1646 | void *buf = NULL;
1647 | struct quic_event_t event = { .id = 55 };
1648 |
1649 | // struct st_quicly_conn_t * conn
1650 | struct st_quicly_conn_t conn = {};
1651 | bpf_usdt_readarg(1, ctx, &buf);
1652 | bpf_probe_read(&conn, sizeof(conn), buf);
1653 | event.quictrace_cc_lost.master_id = conn.master_id; /* uint32_t */
1654 | // int64_t at
1655 | bpf_usdt_readarg(2, ctx, &event.quictrace_cc_lost.at);
1656 | // struct quicly_rtt_t * rtt
1657 | struct quicly_rtt_t rtt = {};
1658 | bpf_usdt_readarg(3, ctx, &buf);
1659 | bpf_probe_read(&rtt, sizeof(rtt), buf);
1660 | event.quictrace_cc_lost.minimum = rtt.minimum; /* uint32_t */
1661 | event.quictrace_cc_lost.smoothed = rtt.smoothed; /* uint32_t */
1662 | event.quictrace_cc_lost.variance = rtt.variance; /* uint32_t */
1663 | event.quictrace_cc_lost.latest = rtt.latest; /* uint32_t */
1664 | // uint32_t cwnd
1665 | bpf_usdt_readarg(4, ctx, &event.quictrace_cc_lost.cwnd);
1666 | // size_t inflight
1667 | bpf_usdt_readarg(5, ctx, &event.quictrace_cc_lost.inflight);
1668 |
1669 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1670 | bpf_trace_printk("failed to perf_submit\n");
1671 |
1672 | return 0;
1673 | }
1674 | // h2o:h3_accept
1675 | int trace_h2o__h3_accept(struct pt_regs *ctx) {
1676 | void *buf = NULL;
1677 | struct quic_event_t event = { .id = 60 };
1678 |
1679 | // uint64_t conn_id
1680 | bpf_usdt_readarg(1, ctx, &event.h3_accept.conn_id);
1681 | // struct st_h2o_conn_t * conn (ignored)
1682 | // struct st_quicly_conn_t * quic
1683 | struct st_quicly_conn_t quic = {};
1684 | bpf_usdt_readarg(3, ctx, &buf);
1685 | bpf_probe_read(&quic, sizeof(quic), buf);
1686 | event.h3_accept.master_id = quic.master_id; /* uint32_t */
1687 |
1688 | h2o_to_quicly_conn.update(&event.h3_accept.conn_id, &event.h3_accept.master_id);
1689 |
1690 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1691 | bpf_trace_printk("failed to perf_submit\n");
1692 |
1693 | return 0;
1694 | }
1695 | // h2o:h3_close
1696 | int trace_h2o__h3_close(struct pt_regs *ctx) {
1697 | void *buf = NULL;
1698 | struct quic_event_t event = { .id = 61 };
1699 |
1700 | // uint64_t conn_id
1701 | bpf_usdt_readarg(1, ctx, &event.h3_close.conn_id);
1702 |
1703 | const uint32_t *master_conn_id_ptr = h2o_to_quicly_conn.lookup(&event.h3_close.conn_id);
1704 | if (master_conn_id_ptr != NULL) {
1705 | event.h3_close.master_id = *master_conn_id_ptr;
1706 | } else {
1707 | bpf_trace_printk("h2o's conn_id=%lu is not associated to master_conn_id\n", event.h3_close.conn_id);
1708 | }
1709 | h2o_to_quicly_conn.delete(&event.h3_close.conn_id);
1710 |
1711 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1712 | bpf_trace_printk("failed to perf_submit\n");
1713 |
1714 | return 0;
1715 | }
1716 | // h2o:send_response_header
1717 | int trace_h2o__send_response_header(struct pt_regs *ctx) {
1718 | void *buf = NULL;
1719 | struct quic_event_t event = { .id = 70 };
1720 |
1721 | // uint64_t conn_id
1722 | bpf_usdt_readarg(1, ctx, &event.send_response_header.conn_id);
1723 | // uint64_t req_id
1724 | bpf_usdt_readarg(2, ctx, &event.send_response_header.req_id);
1725 | // const char * name
1726 | bpf_usdt_readarg(3, ctx, &buf);
1727 | bpf_probe_read(&event.send_response_header.name, sizeof(event.send_response_header.name), buf);
1728 | // size_t name_len
1729 | bpf_usdt_readarg(4, ctx, &event.send_response_header.name_len);
1730 | // const char * value
1731 | bpf_usdt_readarg(5, ctx, &buf);
1732 | bpf_probe_read(&event.send_response_header.value, sizeof(event.send_response_header.value), buf);
1733 | // size_t value_len
1734 | bpf_usdt_readarg(6, ctx, &event.send_response_header.value_len);
1735 |
1736 | const uint32_t *master_conn_id_ptr = h2o_to_quicly_conn.lookup(&event.send_response_header.conn_id);
1737 | if (master_conn_id_ptr == NULL)
1738 | return 0;
1739 | event.send_response_header.master_id = *master_conn_id_ptr;
1740 |
1741 | #ifdef CHECK_ALLOWED_RES_HEADER_NAME
1742 | if (!CHECK_ALLOWED_RES_HEADER_NAME(event.send_response_header.name, event.send_response_header.name_len))
1743 | return 0;
1744 | #endif
1745 |
1746 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
1747 | bpf_trace_printk("failed to perf_submit\n");
1748 |
1749 | return 0;
1750 | }
1751 |
1752 | )";
1753 |
1754 | static uint64_t time_milliseconds()
1755 | {
1756 | struct timeval tv;
1757 | gettimeofday(&tv, NULL);
1758 | return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
1759 | }
1760 |
1761 |
1762 | static
1763 | std::vector quic_init_usdt_probes(pid_t pid) {
1764 | const std::vector probes = {
1765 | ebpf::USDT(pid, "quicly", "connect", "trace_quicly__connect"),
1766 | ebpf::USDT(pid, "quicly", "accept", "trace_quicly__accept"),
1767 | ebpf::USDT(pid, "quicly", "free", "trace_quicly__free"),
1768 | ebpf::USDT(pid, "quicly", "send", "trace_quicly__send"),
1769 | ebpf::USDT(pid, "quicly", "receive", "trace_quicly__receive"),
1770 | ebpf::USDT(pid, "quicly", "version_switch", "trace_quicly__version_switch"),
1771 | ebpf::USDT(pid, "quicly", "idle_timeout", "trace_quicly__idle_timeout"),
1772 | ebpf::USDT(pid, "quicly", "stateless_reset_receive", "trace_quicly__stateless_reset_receive"),
1773 | ebpf::USDT(pid, "quicly", "crypto_decrypt", "trace_quicly__crypto_decrypt"),
1774 | ebpf::USDT(pid, "quicly", "crypto_handshake", "trace_quicly__crypto_handshake"),
1775 | ebpf::USDT(pid, "quicly", "crypto_update_secret", "trace_quicly__crypto_update_secret"),
1776 | ebpf::USDT(pid, "quicly", "crypto_send_key_update", "trace_quicly__crypto_send_key_update"),
1777 | ebpf::USDT(pid, "quicly", "crypto_send_key_update_confirmed", "trace_quicly__crypto_send_key_update_confirmed"),
1778 | ebpf::USDT(pid, "quicly", "crypto_receive_key_update", "trace_quicly__crypto_receive_key_update"),
1779 | ebpf::USDT(pid, "quicly", "crypto_receive_key_update_prepare", "trace_quicly__crypto_receive_key_update_prepare"),
1780 | ebpf::USDT(pid, "quicly", "packet_prepare", "trace_quicly__packet_prepare"),
1781 | ebpf::USDT(pid, "quicly", "packet_commit", "trace_quicly__packet_commit"),
1782 | ebpf::USDT(pid, "quicly", "packet_acked", "trace_quicly__packet_acked"),
1783 | ebpf::USDT(pid, "quicly", "packet_lost", "trace_quicly__packet_lost"),
1784 | ebpf::USDT(pid, "quicly", "pto", "trace_quicly__pto"),
1785 | ebpf::USDT(pid, "quicly", "cc_ack_received", "trace_quicly__cc_ack_received"),
1786 | ebpf::USDT(pid, "quicly", "cc_congestion", "trace_quicly__cc_congestion"),
1787 | ebpf::USDT(pid, "quicly", "transport_close_send", "trace_quicly__transport_close_send"),
1788 | ebpf::USDT(pid, "quicly", "transport_close_receive", "trace_quicly__transport_close_receive"),
1789 | ebpf::USDT(pid, "quicly", "application_close_send", "trace_quicly__application_close_send"),
1790 | ebpf::USDT(pid, "quicly", "application_close_receive", "trace_quicly__application_close_receive"),
1791 | ebpf::USDT(pid, "quicly", "stream_send", "trace_quicly__stream_send"),
1792 | ebpf::USDT(pid, "quicly", "stream_receive", "trace_quicly__stream_receive"),
1793 | ebpf::USDT(pid, "quicly", "stream_acked", "trace_quicly__stream_acked"),
1794 | ebpf::USDT(pid, "quicly", "stream_lost", "trace_quicly__stream_lost"),
1795 | ebpf::USDT(pid, "quicly", "max_data_send", "trace_quicly__max_data_send"),
1796 | ebpf::USDT(pid, "quicly", "max_data_receive", "trace_quicly__max_data_receive"),
1797 | ebpf::USDT(pid, "quicly", "max_streams_send", "trace_quicly__max_streams_send"),
1798 | ebpf::USDT(pid, "quicly", "max_streams_receive", "trace_quicly__max_streams_receive"),
1799 | ebpf::USDT(pid, "quicly", "max_stream_data_send", "trace_quicly__max_stream_data_send"),
1800 | ebpf::USDT(pid, "quicly", "max_stream_data_receive", "trace_quicly__max_stream_data_receive"),
1801 | ebpf::USDT(pid, "quicly", "new_token_send", "trace_quicly__new_token_send"),
1802 | ebpf::USDT(pid, "quicly", "new_token_acked", "trace_quicly__new_token_acked"),
1803 | ebpf::USDT(pid, "quicly", "new_token_receive", "trace_quicly__new_token_receive"),
1804 | ebpf::USDT(pid, "quicly", "handshake_done_send", "trace_quicly__handshake_done_send"),
1805 | ebpf::USDT(pid, "quicly", "handshake_done_receive", "trace_quicly__handshake_done_receive"),
1806 | ebpf::USDT(pid, "quicly", "streams_blocked_send", "trace_quicly__streams_blocked_send"),
1807 | ebpf::USDT(pid, "quicly", "streams_blocked_receive", "trace_quicly__streams_blocked_receive"),
1808 | ebpf::USDT(pid, "quicly", "data_blocked_receive", "trace_quicly__data_blocked_receive"),
1809 | ebpf::USDT(pid, "quicly", "stream_data_blocked_receive", "trace_quicly__stream_data_blocked_receive"),
1810 | ebpf::USDT(pid, "quicly", "quictrace_sent", "trace_quicly__quictrace_sent"),
1811 | ebpf::USDT(pid, "quicly", "quictrace_recv", "trace_quicly__quictrace_recv"),
1812 | ebpf::USDT(pid, "quicly", "quictrace_send_stream", "trace_quicly__quictrace_send_stream"),
1813 | ebpf::USDT(pid, "quicly", "quictrace_recv_stream", "trace_quicly__quictrace_recv_stream"),
1814 | ebpf::USDT(pid, "quicly", "quictrace_recv_ack", "trace_quicly__quictrace_recv_ack"),
1815 | ebpf::USDT(pid, "quicly", "quictrace_recv_ack_delay", "trace_quicly__quictrace_recv_ack_delay"),
1816 | ebpf::USDT(pid, "quicly", "quictrace_lost", "trace_quicly__quictrace_lost"),
1817 | ebpf::USDT(pid, "quicly", "quictrace_cc_ack", "trace_quicly__quictrace_cc_ack"),
1818 | ebpf::USDT(pid, "quicly", "quictrace_cc_lost", "trace_quicly__quictrace_cc_lost"),
1819 | ebpf::USDT(pid, "h2o", "h3_accept", "trace_h2o__h3_accept"),
1820 | ebpf::USDT(pid, "h2o", "h3_close", "trace_h2o__h3_close"),
1821 | ebpf::USDT(pid, "h2o", "send_response_header", "trace_h2o__send_response_header"),
1822 |
1823 | };
1824 | return probes;
1825 | }
1826 |
1827 |
1828 | struct quic_event_t {
1829 | uint8_t id;
1830 |
1831 | union {
1832 | struct { // quicly:connect
1833 | uint32_t master_id;
1834 | int64_t at;
1835 | uint32_t version;
1836 | } connect;
1837 | struct { // quicly:accept
1838 | uint32_t master_id;
1839 | int64_t at;
1840 | char dcid[STR_LEN];
1841 | } accept;
1842 | struct { // quicly:free
1843 | uint32_t master_id;
1844 | int64_t at;
1845 | } free;
1846 | struct { // quicly:send
1847 | uint32_t master_id;
1848 | int64_t at;
1849 | int state;
1850 | char dcid[STR_LEN];
1851 | } send;
1852 | struct { // quicly:receive
1853 | uint32_t master_id;
1854 | int64_t at;
1855 | char dcid[STR_LEN];
1856 | uint8_t bytes[1];
1857 | size_t num_bytes;
1858 | } receive;
1859 | struct { // quicly:version_switch
1860 | uint32_t master_id;
1861 | int64_t at;
1862 | uint32_t new_version;
1863 | } version_switch;
1864 | struct { // quicly:idle_timeout
1865 | uint32_t master_id;
1866 | int64_t at;
1867 | } idle_timeout;
1868 | struct { // quicly:stateless_reset_receive
1869 | uint32_t master_id;
1870 | int64_t at;
1871 | } stateless_reset_receive;
1872 | struct { // quicly:crypto_decrypt
1873 | uint32_t master_id;
1874 | int64_t at;
1875 | uint64_t pn;
1876 | size_t decrypted_len;
1877 | } crypto_decrypt;
1878 | struct { // quicly:crypto_handshake
1879 | uint32_t master_id;
1880 | int64_t at;
1881 | int ret;
1882 | } crypto_handshake;
1883 | struct { // quicly:crypto_update_secret
1884 | uint32_t master_id;
1885 | int64_t at;
1886 | int is_enc;
1887 | uint8_t epoch;
1888 | char label[STR_LEN];
1889 | } crypto_update_secret;
1890 | struct { // quicly:crypto_send_key_update
1891 | uint32_t master_id;
1892 | int64_t at;
1893 | uint64_t phase;
1894 | } crypto_send_key_update;
1895 | struct { // quicly:crypto_send_key_update_confirmed
1896 | uint32_t master_id;
1897 | int64_t at;
1898 | uint64_t next_pn;
1899 | } crypto_send_key_update_confirmed;
1900 | struct { // quicly:crypto_receive_key_update
1901 | uint32_t master_id;
1902 | int64_t at;
1903 | uint64_t phase;
1904 | } crypto_receive_key_update;
1905 | struct { // quicly:crypto_receive_key_update_prepare
1906 | uint32_t master_id;
1907 | int64_t at;
1908 | uint64_t phase;
1909 | } crypto_receive_key_update_prepare;
1910 | struct { // quicly:packet_prepare
1911 | uint32_t master_id;
1912 | int64_t at;
1913 | uint8_t first_octet;
1914 | char dcid[STR_LEN];
1915 | } packet_prepare;
1916 | struct { // quicly:packet_commit
1917 | uint32_t master_id;
1918 | int64_t at;
1919 | uint64_t pn;
1920 | size_t len;
1921 | int ack_only;
1922 | } packet_commit;
1923 | struct { // quicly:packet_acked
1924 | uint32_t master_id;
1925 | int64_t at;
1926 | uint64_t pn;
1927 | int newly_acked;
1928 | } packet_acked;
1929 | struct { // quicly:packet_lost
1930 | uint32_t master_id;
1931 | int64_t at;
1932 | uint64_t pn;
1933 | } packet_lost;
1934 | struct { // quicly:pto
1935 | uint32_t master_id;
1936 | int64_t at;
1937 | size_t inflight;
1938 | uint32_t cwnd;
1939 | int8_t pto_count;
1940 | } pto;
1941 | struct { // quicly:cc_ack_received
1942 | uint32_t master_id;
1943 | int64_t at;
1944 | uint64_t largest_acked;
1945 | size_t bytes_acked;
1946 | uint32_t cwnd;
1947 | size_t inflight;
1948 | } cc_ack_received;
1949 | struct { // quicly:cc_congestion
1950 | uint32_t master_id;
1951 | int64_t at;
1952 | uint64_t max_lost_pn;
1953 | size_t inflight;
1954 | uint32_t cwnd;
1955 | } cc_congestion;
1956 | struct { // quicly:transport_close_send
1957 | uint32_t master_id;
1958 | int64_t at;
1959 | uint64_t error_code;
1960 | uint64_t frame_type;
1961 | char reason_phrase[STR_LEN];
1962 | } transport_close_send;
1963 | struct { // quicly:transport_close_receive
1964 | uint32_t master_id;
1965 | int64_t at;
1966 | uint64_t error_code;
1967 | uint64_t frame_type;
1968 | char reason_phrase[STR_LEN];
1969 | } transport_close_receive;
1970 | struct { // quicly:application_close_send
1971 | uint32_t master_id;
1972 | int64_t at;
1973 | uint64_t error_code;
1974 | char reason_phrase[STR_LEN];
1975 | } application_close_send;
1976 | struct { // quicly:application_close_receive
1977 | uint32_t master_id;
1978 | int64_t at;
1979 | uint64_t error_code;
1980 | char reason_phrase[STR_LEN];
1981 | } application_close_receive;
1982 | struct { // quicly:stream_send
1983 | uint32_t master_id;
1984 | int64_t at;
1985 | int64_t stream_id;
1986 | uint64_t off;
1987 | size_t len;
1988 | int is_fin;
1989 | } stream_send;
1990 | struct { // quicly:stream_receive
1991 | uint32_t master_id;
1992 | int64_t at;
1993 | int64_t stream_id;
1994 | uint64_t off;
1995 | size_t len;
1996 | } stream_receive;
1997 | struct { // quicly:stream_acked
1998 | uint32_t master_id;
1999 | int64_t at;
2000 | int64_t stream_id;
2001 | uint64_t off;
2002 | size_t len;
2003 | } stream_acked;
2004 | struct { // quicly:stream_lost
2005 | uint32_t master_id;
2006 | int64_t at;
2007 | int64_t stream_id;
2008 | uint64_t off;
2009 | size_t len;
2010 | } stream_lost;
2011 | struct { // quicly:max_data_send
2012 | uint32_t master_id;
2013 | int64_t at;
2014 | uint64_t limit;
2015 | } max_data_send;
2016 | struct { // quicly:max_data_receive
2017 | uint32_t master_id;
2018 | int64_t at;
2019 | uint64_t limit;
2020 | } max_data_receive;
2021 | struct { // quicly:max_streams_send
2022 | uint32_t master_id;
2023 | int64_t at;
2024 | uint64_t limit;
2025 | int is_unidirectional;
2026 | } max_streams_send;
2027 | struct { // quicly:max_streams_receive
2028 | uint32_t master_id;
2029 | int64_t at;
2030 | uint64_t limit;
2031 | int is_unidirectional;
2032 | } max_streams_receive;
2033 | struct { // quicly:max_stream_data_send
2034 | uint32_t master_id;
2035 | int64_t at;
2036 | int64_t stream_id;
2037 | uint64_t limit;
2038 | } max_stream_data_send;
2039 | struct { // quicly:max_stream_data_receive
2040 | uint32_t master_id;
2041 | int64_t at;
2042 | int64_t stream_id;
2043 | uint64_t limit;
2044 | } max_stream_data_receive;
2045 | struct { // quicly:new_token_send
2046 | uint32_t master_id;
2047 | int64_t at;
2048 | uint8_t token[STR_LEN];
2049 | size_t len;
2050 | uint64_t generation;
2051 | } new_token_send;
2052 | struct { // quicly:new_token_acked
2053 | uint32_t master_id;
2054 | int64_t at;
2055 | uint64_t generation;
2056 | } new_token_acked;
2057 | struct { // quicly:new_token_receive
2058 | uint32_t master_id;
2059 | int64_t at;
2060 | uint8_t token[STR_LEN];
2061 | size_t len;
2062 | } new_token_receive;
2063 | struct { // quicly:handshake_done_send
2064 | uint32_t master_id;
2065 | int64_t at;
2066 | } handshake_done_send;
2067 | struct { // quicly:handshake_done_receive
2068 | uint32_t master_id;
2069 | int64_t at;
2070 | } handshake_done_receive;
2071 | struct { // quicly:streams_blocked_send
2072 | uint32_t master_id;
2073 | int64_t at;
2074 | uint64_t limit;
2075 | int is_unidirectional;
2076 | } streams_blocked_send;
2077 | struct { // quicly:streams_blocked_receive
2078 | uint32_t master_id;
2079 | int64_t at;
2080 | uint64_t limit;
2081 | int is_unidirectional;
2082 | } streams_blocked_receive;
2083 | struct { // quicly:data_blocked_receive
2084 | uint32_t master_id;
2085 | int64_t at;
2086 | uint64_t off;
2087 | } data_blocked_receive;
2088 | struct { // quicly:stream_data_blocked_receive
2089 | uint32_t master_id;
2090 | int64_t at;
2091 | int64_t stream_id;
2092 | uint64_t limit;
2093 | } stream_data_blocked_receive;
2094 | struct { // quicly:quictrace_sent
2095 | uint32_t master_id;
2096 | int64_t at;
2097 | uint64_t pn;
2098 | size_t len;
2099 | uint8_t packet_type;
2100 | } quictrace_sent;
2101 | struct { // quicly:quictrace_recv
2102 | uint32_t master_id;
2103 | int64_t at;
2104 | uint64_t pn;
2105 | } quictrace_recv;
2106 | struct { // quicly:quictrace_send_stream
2107 | uint32_t master_id;
2108 | int64_t at;
2109 | int64_t stream_id;
2110 | uint64_t off;
2111 | size_t len;
2112 | int fin;
2113 | } quictrace_send_stream;
2114 | struct { // quicly:quictrace_recv_stream
2115 | uint32_t master_id;
2116 | int64_t at;
2117 | int64_t stream_id;
2118 | uint64_t off;
2119 | size_t len;
2120 | int fin;
2121 | } quictrace_recv_stream;
2122 | struct { // quicly:quictrace_recv_ack
2123 | uint32_t master_id;
2124 | int64_t at;
2125 | uint64_t ack_block_begin;
2126 | uint64_t ack_block_end;
2127 | } quictrace_recv_ack;
2128 | struct { // quicly:quictrace_recv_ack_delay
2129 | uint32_t master_id;
2130 | int64_t at;
2131 | int64_t ack_delay;
2132 | } quictrace_recv_ack_delay;
2133 | struct { // quicly:quictrace_lost
2134 | uint32_t master_id;
2135 | int64_t at;
2136 | uint64_t pn;
2137 | } quictrace_lost;
2138 | struct { // quicly:quictrace_cc_ack
2139 | uint32_t master_id;
2140 | int64_t at;
2141 | uint32_t minimum;
2142 | uint32_t smoothed;
2143 | uint32_t variance;
2144 | uint32_t latest;
2145 | uint32_t cwnd;
2146 | size_t inflight;
2147 | } quictrace_cc_ack;
2148 | struct { // quicly:quictrace_cc_lost
2149 | uint32_t master_id;
2150 | int64_t at;
2151 | uint32_t minimum;
2152 | uint32_t smoothed;
2153 | uint32_t variance;
2154 | uint32_t latest;
2155 | uint32_t cwnd;
2156 | size_t inflight;
2157 | } quictrace_cc_lost;
2158 | struct { // h2o:h3_accept
2159 | uint64_t conn_id;
2160 | uint32_t master_id;
2161 | } h3_accept;
2162 | struct { // h2o:h3_close
2163 | uint64_t conn_id;
2164 | uint32_t master_id;
2165 | } h3_close;
2166 | struct { // h2o:send_response_header
2167 | uint64_t conn_id;
2168 | uint64_t req_id;
2169 | char name[STR_LEN];
2170 | size_t name_len;
2171 | char value[STR_LEN];
2172 | size_t value_len;
2173 | uint32_t master_id;
2174 | } send_response_header;
2175 |
2176 | };
2177 | };
2178 |
2179 |
2180 | static
2181 | void quic_handle_event(h2o_tracer_t *tracer, const void *data, int data_len) {
2182 | FILE *out = tracer->out;
2183 |
2184 | const quic_event_t *event = static_cast(data);
2185 |
2186 | if (event->id == 1) { // sched:sched_process_exit
2187 | exit(0);
2188 | }
2189 |
2190 | // output JSON
2191 | fprintf(out, "{");
2192 |
2193 | switch (event->id) {
2194 | case 2: { // quicly:connect
2195 | json_write_pair_n(out, STR_LIT("type"), "connect");
2196 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2197 | json_write_pair_c(out, STR_LIT("conn"), event->connect.master_id);
2198 | json_write_pair_c(out, STR_LIT("time"), event->connect.at);
2199 | json_write_pair_c(out, STR_LIT("version"), event->connect.version);
2200 | break;
2201 | }
2202 | case 3: { // quicly:accept
2203 | json_write_pair_n(out, STR_LIT("type"), "accept");
2204 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2205 | json_write_pair_c(out, STR_LIT("conn"), event->accept.master_id);
2206 | json_write_pair_c(out, STR_LIT("time"), event->accept.at);
2207 | json_write_pair_c(out, STR_LIT("dcid"), event->accept.dcid);
2208 | break;
2209 | }
2210 | case 4: { // quicly:free
2211 | json_write_pair_n(out, STR_LIT("type"), "free");
2212 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2213 | json_write_pair_c(out, STR_LIT("conn"), event->free.master_id);
2214 | json_write_pair_c(out, STR_LIT("time"), event->free.at);
2215 | break;
2216 | }
2217 | case 5: { // quicly:send
2218 | json_write_pair_n(out, STR_LIT("type"), "send");
2219 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2220 | json_write_pair_c(out, STR_LIT("conn"), event->send.master_id);
2221 | json_write_pair_c(out, STR_LIT("time"), event->send.at);
2222 | json_write_pair_c(out, STR_LIT("state"), event->send.state);
2223 | json_write_pair_c(out, STR_LIT("dcid"), event->send.dcid);
2224 | break;
2225 | }
2226 | case 6: { // quicly:receive
2227 | json_write_pair_n(out, STR_LIT("type"), "receive");
2228 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2229 | json_write_pair_c(out, STR_LIT("conn"), event->receive.master_id);
2230 | json_write_pair_c(out, STR_LIT("time"), event->receive.at);
2231 | json_write_pair_c(out, STR_LIT("dcid"), event->receive.dcid);
2232 | json_write_pair_c(out, STR_LIT("first-octet"), event->receive.bytes[0]);
2233 | json_write_pair_c(out, STR_LIT("bytes-len"), event->receive.num_bytes);
2234 | break;
2235 | }
2236 | case 7: { // quicly:version_switch
2237 | json_write_pair_n(out, STR_LIT("type"), "version-switch");
2238 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2239 | json_write_pair_c(out, STR_LIT("conn"), event->version_switch.master_id);
2240 | json_write_pair_c(out, STR_LIT("time"), event->version_switch.at);
2241 | json_write_pair_c(out, STR_LIT("new-version"), event->version_switch.new_version);
2242 | break;
2243 | }
2244 | case 8: { // quicly:idle_timeout
2245 | json_write_pair_n(out, STR_LIT("type"), "idle-timeout");
2246 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2247 | json_write_pair_c(out, STR_LIT("conn"), event->idle_timeout.master_id);
2248 | json_write_pair_c(out, STR_LIT("time"), event->idle_timeout.at);
2249 | break;
2250 | }
2251 | case 9: { // quicly:stateless_reset_receive
2252 | json_write_pair_n(out, STR_LIT("type"), "stateless-reset-receive");
2253 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2254 | json_write_pair_c(out, STR_LIT("conn"), event->stateless_reset_receive.master_id);
2255 | json_write_pair_c(out, STR_LIT("time"), event->stateless_reset_receive.at);
2256 | break;
2257 | }
2258 | case 10: { // quicly:crypto_decrypt
2259 | json_write_pair_n(out, STR_LIT("type"), "crypto-decrypt");
2260 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2261 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_decrypt.master_id);
2262 | json_write_pair_c(out, STR_LIT("time"), event->crypto_decrypt.at);
2263 | json_write_pair_c(out, STR_LIT("pn"), event->crypto_decrypt.pn);
2264 | json_write_pair_c(out, STR_LIT("decrypted-len"), event->crypto_decrypt.decrypted_len);
2265 | break;
2266 | }
2267 | case 11: { // quicly:crypto_handshake
2268 | json_write_pair_n(out, STR_LIT("type"), "crypto-handshake");
2269 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2270 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_handshake.master_id);
2271 | json_write_pair_c(out, STR_LIT("time"), event->crypto_handshake.at);
2272 | json_write_pair_c(out, STR_LIT("ret"), event->crypto_handshake.ret);
2273 | break;
2274 | }
2275 | case 12: { // quicly:crypto_update_secret
2276 | json_write_pair_n(out, STR_LIT("type"), "crypto-update-secret");
2277 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2278 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_update_secret.master_id);
2279 | json_write_pair_c(out, STR_LIT("time"), event->crypto_update_secret.at);
2280 | json_write_pair_c(out, STR_LIT("is-enc"), event->crypto_update_secret.is_enc);
2281 | json_write_pair_c(out, STR_LIT("epoch"), event->crypto_update_secret.epoch);
2282 | json_write_pair_c(out, STR_LIT("label"), event->crypto_update_secret.label);
2283 | break;
2284 | }
2285 | case 13: { // quicly:crypto_send_key_update
2286 | json_write_pair_n(out, STR_LIT("type"), "crypto-send-key-update");
2287 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2288 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_send_key_update.master_id);
2289 | json_write_pair_c(out, STR_LIT("time"), event->crypto_send_key_update.at);
2290 | json_write_pair_c(out, STR_LIT("phase"), event->crypto_send_key_update.phase);
2291 | break;
2292 | }
2293 | case 14: { // quicly:crypto_send_key_update_confirmed
2294 | json_write_pair_n(out, STR_LIT("type"), "crypto-send-key-update-confirmed");
2295 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2296 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_send_key_update_confirmed.master_id);
2297 | json_write_pair_c(out, STR_LIT("time"), event->crypto_send_key_update_confirmed.at);
2298 | json_write_pair_c(out, STR_LIT("next-pn"), event->crypto_send_key_update_confirmed.next_pn);
2299 | break;
2300 | }
2301 | case 15: { // quicly:crypto_receive_key_update
2302 | json_write_pair_n(out, STR_LIT("type"), "crypto-receive-key-update");
2303 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2304 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_receive_key_update.master_id);
2305 | json_write_pair_c(out, STR_LIT("time"), event->crypto_receive_key_update.at);
2306 | json_write_pair_c(out, STR_LIT("phase"), event->crypto_receive_key_update.phase);
2307 | break;
2308 | }
2309 | case 16: { // quicly:crypto_receive_key_update_prepare
2310 | json_write_pair_n(out, STR_LIT("type"), "crypto-receive-key-update-prepare");
2311 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2312 | json_write_pair_c(out, STR_LIT("conn"), event->crypto_receive_key_update_prepare.master_id);
2313 | json_write_pair_c(out, STR_LIT("time"), event->crypto_receive_key_update_prepare.at);
2314 | json_write_pair_c(out, STR_LIT("phase"), event->crypto_receive_key_update_prepare.phase);
2315 | break;
2316 | }
2317 | case 17: { // quicly:packet_prepare
2318 | json_write_pair_n(out, STR_LIT("type"), "packet-prepare");
2319 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2320 | json_write_pair_c(out, STR_LIT("conn"), event->packet_prepare.master_id);
2321 | json_write_pair_c(out, STR_LIT("time"), event->packet_prepare.at);
2322 | json_write_pair_c(out, STR_LIT("first-octet"), event->packet_prepare.first_octet);
2323 | json_write_pair_c(out, STR_LIT("dcid"), event->packet_prepare.dcid);
2324 | break;
2325 | }
2326 | case 18: { // quicly:packet_commit
2327 | json_write_pair_n(out, STR_LIT("type"), "packet-commit");
2328 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2329 | json_write_pair_c(out, STR_LIT("conn"), event->packet_commit.master_id);
2330 | json_write_pair_c(out, STR_LIT("time"), event->packet_commit.at);
2331 | json_write_pair_c(out, STR_LIT("pn"), event->packet_commit.pn);
2332 | json_write_pair_c(out, STR_LIT("len"), event->packet_commit.len);
2333 | json_write_pair_c(out, STR_LIT("ack-only"), event->packet_commit.ack_only);
2334 | break;
2335 | }
2336 | case 19: { // quicly:packet_acked
2337 | json_write_pair_n(out, STR_LIT("type"), "packet-acked");
2338 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2339 | json_write_pair_c(out, STR_LIT("conn"), event->packet_acked.master_id);
2340 | json_write_pair_c(out, STR_LIT("time"), event->packet_acked.at);
2341 | json_write_pair_c(out, STR_LIT("pn"), event->packet_acked.pn);
2342 | json_write_pair_c(out, STR_LIT("newly-acked"), event->packet_acked.newly_acked);
2343 | break;
2344 | }
2345 | case 20: { // quicly:packet_lost
2346 | json_write_pair_n(out, STR_LIT("type"), "packet-lost");
2347 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2348 | json_write_pair_c(out, STR_LIT("conn"), event->packet_lost.master_id);
2349 | json_write_pair_c(out, STR_LIT("time"), event->packet_lost.at);
2350 | json_write_pair_c(out, STR_LIT("pn"), event->packet_lost.pn);
2351 | break;
2352 | }
2353 | case 21: { // quicly:pto
2354 | json_write_pair_n(out, STR_LIT("type"), "pto");
2355 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2356 | json_write_pair_c(out, STR_LIT("conn"), event->pto.master_id);
2357 | json_write_pair_c(out, STR_LIT("time"), event->pto.at);
2358 | json_write_pair_c(out, STR_LIT("inflight"), event->pto.inflight);
2359 | json_write_pair_c(out, STR_LIT("cwnd"), event->pto.cwnd);
2360 | json_write_pair_c(out, STR_LIT("pto-count"), event->pto.pto_count);
2361 | break;
2362 | }
2363 | case 22: { // quicly:cc_ack_received
2364 | json_write_pair_n(out, STR_LIT("type"), "cc-ack-received");
2365 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2366 | json_write_pair_c(out, STR_LIT("conn"), event->cc_ack_received.master_id);
2367 | json_write_pair_c(out, STR_LIT("time"), event->cc_ack_received.at);
2368 | json_write_pair_c(out, STR_LIT("largest-acked"), event->cc_ack_received.largest_acked);
2369 | json_write_pair_c(out, STR_LIT("bytes-acked"), event->cc_ack_received.bytes_acked);
2370 | json_write_pair_c(out, STR_LIT("cwnd"), event->cc_ack_received.cwnd);
2371 | json_write_pair_c(out, STR_LIT("inflight"), event->cc_ack_received.inflight);
2372 | break;
2373 | }
2374 | case 23: { // quicly:cc_congestion
2375 | json_write_pair_n(out, STR_LIT("type"), "cc-congestion");
2376 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2377 | json_write_pair_c(out, STR_LIT("conn"), event->cc_congestion.master_id);
2378 | json_write_pair_c(out, STR_LIT("time"), event->cc_congestion.at);
2379 | json_write_pair_c(out, STR_LIT("max-lost-pn"), event->cc_congestion.max_lost_pn);
2380 | json_write_pair_c(out, STR_LIT("inflight"), event->cc_congestion.inflight);
2381 | json_write_pair_c(out, STR_LIT("cwnd"), event->cc_congestion.cwnd);
2382 | break;
2383 | }
2384 | case 24: { // quicly:transport_close_send
2385 | json_write_pair_n(out, STR_LIT("type"), "transport-close-send");
2386 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2387 | json_write_pair_c(out, STR_LIT("conn"), event->transport_close_send.master_id);
2388 | json_write_pair_c(out, STR_LIT("time"), event->transport_close_send.at);
2389 | json_write_pair_c(out, STR_LIT("error-code"), event->transport_close_send.error_code);
2390 | json_write_pair_c(out, STR_LIT("frame-type"), event->transport_close_send.frame_type);
2391 | json_write_pair_c(out, STR_LIT("reason-phrase"), event->transport_close_send.reason_phrase);
2392 | break;
2393 | }
2394 | case 25: { // quicly:transport_close_receive
2395 | json_write_pair_n(out, STR_LIT("type"), "transport-close-receive");
2396 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2397 | json_write_pair_c(out, STR_LIT("conn"), event->transport_close_receive.master_id);
2398 | json_write_pair_c(out, STR_LIT("time"), event->transport_close_receive.at);
2399 | json_write_pair_c(out, STR_LIT("error-code"), event->transport_close_receive.error_code);
2400 | json_write_pair_c(out, STR_LIT("frame-type"), event->transport_close_receive.frame_type);
2401 | json_write_pair_c(out, STR_LIT("reason-phrase"), event->transport_close_receive.reason_phrase);
2402 | break;
2403 | }
2404 | case 26: { // quicly:application_close_send
2405 | json_write_pair_n(out, STR_LIT("type"), "application-close-send");
2406 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2407 | json_write_pair_c(out, STR_LIT("conn"), event->application_close_send.master_id);
2408 | json_write_pair_c(out, STR_LIT("time"), event->application_close_send.at);
2409 | json_write_pair_c(out, STR_LIT("error-code"), event->application_close_send.error_code);
2410 | json_write_pair_c(out, STR_LIT("reason-phrase"), event->application_close_send.reason_phrase);
2411 | break;
2412 | }
2413 | case 27: { // quicly:application_close_receive
2414 | json_write_pair_n(out, STR_LIT("type"), "application-close-receive");
2415 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2416 | json_write_pair_c(out, STR_LIT("conn"), event->application_close_receive.master_id);
2417 | json_write_pair_c(out, STR_LIT("time"), event->application_close_receive.at);
2418 | json_write_pair_c(out, STR_LIT("error-code"), event->application_close_receive.error_code);
2419 | json_write_pair_c(out, STR_LIT("reason-phrase"), event->application_close_receive.reason_phrase);
2420 | break;
2421 | }
2422 | case 28: { // quicly:stream_send
2423 | json_write_pair_n(out, STR_LIT("type"), "stream-send");
2424 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2425 | json_write_pair_c(out, STR_LIT("conn"), event->stream_send.master_id);
2426 | json_write_pair_c(out, STR_LIT("time"), event->stream_send.at);
2427 | json_write_pair_c(out, STR_LIT("stream-id"), event->stream_send.stream_id);
2428 | json_write_pair_c(out, STR_LIT("off"), event->stream_send.off);
2429 | json_write_pair_c(out, STR_LIT("len"), event->stream_send.len);
2430 | json_write_pair_c(out, STR_LIT("is-fin"), event->stream_send.is_fin);
2431 | break;
2432 | }
2433 | case 29: { // quicly:stream_receive
2434 | json_write_pair_n(out, STR_LIT("type"), "stream-receive");
2435 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2436 | json_write_pair_c(out, STR_LIT("conn"), event->stream_receive.master_id);
2437 | json_write_pair_c(out, STR_LIT("time"), event->stream_receive.at);
2438 | json_write_pair_c(out, STR_LIT("stream-id"), event->stream_receive.stream_id);
2439 | json_write_pair_c(out, STR_LIT("off"), event->stream_receive.off);
2440 | json_write_pair_c(out, STR_LIT("len"), event->stream_receive.len);
2441 | break;
2442 | }
2443 | case 30: { // quicly:stream_acked
2444 | json_write_pair_n(out, STR_LIT("type"), "stream-acked");
2445 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2446 | json_write_pair_c(out, STR_LIT("conn"), event->stream_acked.master_id);
2447 | json_write_pair_c(out, STR_LIT("time"), event->stream_acked.at);
2448 | json_write_pair_c(out, STR_LIT("stream-id"), event->stream_acked.stream_id);
2449 | json_write_pair_c(out, STR_LIT("off"), event->stream_acked.off);
2450 | json_write_pair_c(out, STR_LIT("len"), event->stream_acked.len);
2451 | break;
2452 | }
2453 | case 31: { // quicly:stream_lost
2454 | json_write_pair_n(out, STR_LIT("type"), "stream-lost");
2455 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2456 | json_write_pair_c(out, STR_LIT("conn"), event->stream_lost.master_id);
2457 | json_write_pair_c(out, STR_LIT("time"), event->stream_lost.at);
2458 | json_write_pair_c(out, STR_LIT("stream-id"), event->stream_lost.stream_id);
2459 | json_write_pair_c(out, STR_LIT("off"), event->stream_lost.off);
2460 | json_write_pair_c(out, STR_LIT("len"), event->stream_lost.len);
2461 | break;
2462 | }
2463 | case 32: { // quicly:max_data_send
2464 | json_write_pair_n(out, STR_LIT("type"), "max-data-send");
2465 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2466 | json_write_pair_c(out, STR_LIT("conn"), event->max_data_send.master_id);
2467 | json_write_pair_c(out, STR_LIT("time"), event->max_data_send.at);
2468 | json_write_pair_c(out, STR_LIT("limit"), event->max_data_send.limit);
2469 | break;
2470 | }
2471 | case 33: { // quicly:max_data_receive
2472 | json_write_pair_n(out, STR_LIT("type"), "max-data-receive");
2473 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2474 | json_write_pair_c(out, STR_LIT("conn"), event->max_data_receive.master_id);
2475 | json_write_pair_c(out, STR_LIT("time"), event->max_data_receive.at);
2476 | json_write_pair_c(out, STR_LIT("limit"), event->max_data_receive.limit);
2477 | break;
2478 | }
2479 | case 34: { // quicly:max_streams_send
2480 | json_write_pair_n(out, STR_LIT("type"), "max-streams-send");
2481 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2482 | json_write_pair_c(out, STR_LIT("conn"), event->max_streams_send.master_id);
2483 | json_write_pair_c(out, STR_LIT("time"), event->max_streams_send.at);
2484 | json_write_pair_c(out, STR_LIT("limit"), event->max_streams_send.limit);
2485 | json_write_pair_c(out, STR_LIT("is-unidirectional"), event->max_streams_send.is_unidirectional);
2486 | break;
2487 | }
2488 | case 35: { // quicly:max_streams_receive
2489 | json_write_pair_n(out, STR_LIT("type"), "max-streams-receive");
2490 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2491 | json_write_pair_c(out, STR_LIT("conn"), event->max_streams_receive.master_id);
2492 | json_write_pair_c(out, STR_LIT("time"), event->max_streams_receive.at);
2493 | json_write_pair_c(out, STR_LIT("limit"), event->max_streams_receive.limit);
2494 | json_write_pair_c(out, STR_LIT("is-unidirectional"), event->max_streams_receive.is_unidirectional);
2495 | break;
2496 | }
2497 | case 36: { // quicly:max_stream_data_send
2498 | json_write_pair_n(out, STR_LIT("type"), "max-stream-data-send");
2499 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2500 | json_write_pair_c(out, STR_LIT("conn"), event->max_stream_data_send.master_id);
2501 | json_write_pair_c(out, STR_LIT("time"), event->max_stream_data_send.at);
2502 | json_write_pair_c(out, STR_LIT("stream-id"), event->max_stream_data_send.stream_id);
2503 | json_write_pair_c(out, STR_LIT("limit"), event->max_stream_data_send.limit);
2504 | break;
2505 | }
2506 | case 37: { // quicly:max_stream_data_receive
2507 | json_write_pair_n(out, STR_LIT("type"), "max-stream-data-receive");
2508 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2509 | json_write_pair_c(out, STR_LIT("conn"), event->max_stream_data_receive.master_id);
2510 | json_write_pair_c(out, STR_LIT("time"), event->max_stream_data_receive.at);
2511 | json_write_pair_c(out, STR_LIT("stream-id"), event->max_stream_data_receive.stream_id);
2512 | json_write_pair_c(out, STR_LIT("limit"), event->max_stream_data_receive.limit);
2513 | break;
2514 | }
2515 | case 38: { // quicly:new_token_send
2516 | json_write_pair_n(out, STR_LIT("type"), "new-token-send");
2517 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2518 | json_write_pair_c(out, STR_LIT("conn"), event->new_token_send.master_id);
2519 | json_write_pair_c(out, STR_LIT("time"), event->new_token_send.at);
2520 | json_write_pair_c(out, STR_LIT("token"), event->new_token_send.token, (event->new_token_send.len < STR_LEN ? event->new_token_send.len : STR_LEN));
2521 | json_write_pair_c(out, STR_LIT("len"), event->new_token_send.len);
2522 | json_write_pair_c(out, STR_LIT("generation"), event->new_token_send.generation);
2523 | break;
2524 | }
2525 | case 39: { // quicly:new_token_acked
2526 | json_write_pair_n(out, STR_LIT("type"), "new-token-acked");
2527 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2528 | json_write_pair_c(out, STR_LIT("conn"), event->new_token_acked.master_id);
2529 | json_write_pair_c(out, STR_LIT("time"), event->new_token_acked.at);
2530 | json_write_pair_c(out, STR_LIT("generation"), event->new_token_acked.generation);
2531 | break;
2532 | }
2533 | case 40: { // quicly:new_token_receive
2534 | json_write_pair_n(out, STR_LIT("type"), "new-token-receive");
2535 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2536 | json_write_pair_c(out, STR_LIT("conn"), event->new_token_receive.master_id);
2537 | json_write_pair_c(out, STR_LIT("time"), event->new_token_receive.at);
2538 | json_write_pair_c(out, STR_LIT("token"), event->new_token_receive.token, (event->new_token_receive.len < STR_LEN ? event->new_token_receive.len : STR_LEN));
2539 | json_write_pair_c(out, STR_LIT("len"), event->new_token_receive.len);
2540 | break;
2541 | }
2542 | case 41: { // quicly:handshake_done_send
2543 | json_write_pair_n(out, STR_LIT("type"), "handshake-done-send");
2544 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2545 | json_write_pair_c(out, STR_LIT("conn"), event->handshake_done_send.master_id);
2546 | json_write_pair_c(out, STR_LIT("time"), event->handshake_done_send.at);
2547 | break;
2548 | }
2549 | case 42: { // quicly:handshake_done_receive
2550 | json_write_pair_n(out, STR_LIT("type"), "handshake-done-receive");
2551 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2552 | json_write_pair_c(out, STR_LIT("conn"), event->handshake_done_receive.master_id);
2553 | json_write_pair_c(out, STR_LIT("time"), event->handshake_done_receive.at);
2554 | break;
2555 | }
2556 | case 43: { // quicly:streams_blocked_send
2557 | json_write_pair_n(out, STR_LIT("type"), "streams-blocked-send");
2558 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2559 | json_write_pair_c(out, STR_LIT("conn"), event->streams_blocked_send.master_id);
2560 | json_write_pair_c(out, STR_LIT("time"), event->streams_blocked_send.at);
2561 | json_write_pair_c(out, STR_LIT("limit"), event->streams_blocked_send.limit);
2562 | json_write_pair_c(out, STR_LIT("is-unidirectional"), event->streams_blocked_send.is_unidirectional);
2563 | break;
2564 | }
2565 | case 44: { // quicly:streams_blocked_receive
2566 | json_write_pair_n(out, STR_LIT("type"), "streams-blocked-receive");
2567 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2568 | json_write_pair_c(out, STR_LIT("conn"), event->streams_blocked_receive.master_id);
2569 | json_write_pair_c(out, STR_LIT("time"), event->streams_blocked_receive.at);
2570 | json_write_pair_c(out, STR_LIT("limit"), event->streams_blocked_receive.limit);
2571 | json_write_pair_c(out, STR_LIT("is-unidirectional"), event->streams_blocked_receive.is_unidirectional);
2572 | break;
2573 | }
2574 | case 45: { // quicly:data_blocked_receive
2575 | json_write_pair_n(out, STR_LIT("type"), "data-blocked-receive");
2576 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2577 | json_write_pair_c(out, STR_LIT("conn"), event->data_blocked_receive.master_id);
2578 | json_write_pair_c(out, STR_LIT("time"), event->data_blocked_receive.at);
2579 | json_write_pair_c(out, STR_LIT("off"), event->data_blocked_receive.off);
2580 | break;
2581 | }
2582 | case 46: { // quicly:stream_data_blocked_receive
2583 | json_write_pair_n(out, STR_LIT("type"), "stream-data-blocked-receive");
2584 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2585 | json_write_pair_c(out, STR_LIT("conn"), event->stream_data_blocked_receive.master_id);
2586 | json_write_pair_c(out, STR_LIT("time"), event->stream_data_blocked_receive.at);
2587 | json_write_pair_c(out, STR_LIT("stream-id"), event->stream_data_blocked_receive.stream_id);
2588 | json_write_pair_c(out, STR_LIT("limit"), event->stream_data_blocked_receive.limit);
2589 | break;
2590 | }
2591 | case 47: { // quicly:quictrace_sent
2592 | json_write_pair_n(out, STR_LIT("type"), "quictrace-sent");
2593 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2594 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_sent.master_id);
2595 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_sent.at);
2596 | json_write_pair_c(out, STR_LIT("pn"), event->quictrace_sent.pn);
2597 | json_write_pair_c(out, STR_LIT("len"), event->quictrace_sent.len);
2598 | json_write_pair_c(out, STR_LIT("packet-type"), event->quictrace_sent.packet_type);
2599 | break;
2600 | }
2601 | case 48: { // quicly:quictrace_recv
2602 | json_write_pair_n(out, STR_LIT("type"), "quictrace-recv");
2603 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2604 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_recv.master_id);
2605 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_recv.at);
2606 | json_write_pair_c(out, STR_LIT("pn"), event->quictrace_recv.pn);
2607 | break;
2608 | }
2609 | case 49: { // quicly:quictrace_send_stream
2610 | json_write_pair_n(out, STR_LIT("type"), "quictrace-send-stream");
2611 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2612 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_send_stream.master_id);
2613 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_send_stream.at);
2614 | json_write_pair_c(out, STR_LIT("stream-id"), event->quictrace_send_stream.stream_id);
2615 | json_write_pair_c(out, STR_LIT("off"), event->quictrace_send_stream.off);
2616 | json_write_pair_c(out, STR_LIT("len"), event->quictrace_send_stream.len);
2617 | json_write_pair_c(out, STR_LIT("fin"), event->quictrace_send_stream.fin);
2618 | break;
2619 | }
2620 | case 50: { // quicly:quictrace_recv_stream
2621 | json_write_pair_n(out, STR_LIT("type"), "quictrace-recv-stream");
2622 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2623 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_recv_stream.master_id);
2624 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_recv_stream.at);
2625 | json_write_pair_c(out, STR_LIT("stream-id"), event->quictrace_recv_stream.stream_id);
2626 | json_write_pair_c(out, STR_LIT("off"), event->quictrace_recv_stream.off);
2627 | json_write_pair_c(out, STR_LIT("len"), event->quictrace_recv_stream.len);
2628 | json_write_pair_c(out, STR_LIT("fin"), event->quictrace_recv_stream.fin);
2629 | break;
2630 | }
2631 | case 51: { // quicly:quictrace_recv_ack
2632 | json_write_pair_n(out, STR_LIT("type"), "quictrace-recv-ack");
2633 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2634 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_recv_ack.master_id);
2635 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_recv_ack.at);
2636 | json_write_pair_c(out, STR_LIT("ack-block-begin"), event->quictrace_recv_ack.ack_block_begin);
2637 | json_write_pair_c(out, STR_LIT("ack-block-end"), event->quictrace_recv_ack.ack_block_end);
2638 | break;
2639 | }
2640 | case 52: { // quicly:quictrace_recv_ack_delay
2641 | json_write_pair_n(out, STR_LIT("type"), "quictrace-recv-ack-delay");
2642 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2643 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_recv_ack_delay.master_id);
2644 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_recv_ack_delay.at);
2645 | json_write_pair_c(out, STR_LIT("ack-delay"), event->quictrace_recv_ack_delay.ack_delay);
2646 | break;
2647 | }
2648 | case 53: { // quicly:quictrace_lost
2649 | json_write_pair_n(out, STR_LIT("type"), "quictrace-lost");
2650 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2651 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_lost.master_id);
2652 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_lost.at);
2653 | json_write_pair_c(out, STR_LIT("pn"), event->quictrace_lost.pn);
2654 | break;
2655 | }
2656 | case 54: { // quicly:quictrace_cc_ack
2657 | json_write_pair_n(out, STR_LIT("type"), "quictrace-cc-ack");
2658 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2659 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_cc_ack.master_id);
2660 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_cc_ack.at);
2661 | json_write_pair_c(out, STR_LIT("min-rtt"), event->quictrace_cc_ack.minimum);
2662 | json_write_pair_c(out, STR_LIT("smoothed-rtt"), event->quictrace_cc_ack.smoothed);
2663 | json_write_pair_c(out, STR_LIT("variance-rtt"), event->quictrace_cc_ack.variance);
2664 | json_write_pair_c(out, STR_LIT("latest-rtt"), event->quictrace_cc_ack.latest);
2665 | json_write_pair_c(out, STR_LIT("cwnd"), event->quictrace_cc_ack.cwnd);
2666 | json_write_pair_c(out, STR_LIT("inflight"), event->quictrace_cc_ack.inflight);
2667 | break;
2668 | }
2669 | case 55: { // quicly:quictrace_cc_lost
2670 | json_write_pair_n(out, STR_LIT("type"), "quictrace-cc-lost");
2671 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2672 | json_write_pair_c(out, STR_LIT("conn"), event->quictrace_cc_lost.master_id);
2673 | json_write_pair_c(out, STR_LIT("time"), event->quictrace_cc_lost.at);
2674 | json_write_pair_c(out, STR_LIT("min-rtt"), event->quictrace_cc_lost.minimum);
2675 | json_write_pair_c(out, STR_LIT("smoothed-rtt"), event->quictrace_cc_lost.smoothed);
2676 | json_write_pair_c(out, STR_LIT("variance-rtt"), event->quictrace_cc_lost.variance);
2677 | json_write_pair_c(out, STR_LIT("latest-rtt"), event->quictrace_cc_lost.latest);
2678 | json_write_pair_c(out, STR_LIT("cwnd"), event->quictrace_cc_lost.cwnd);
2679 | json_write_pair_c(out, STR_LIT("inflight"), event->quictrace_cc_lost.inflight);
2680 | break;
2681 | }
2682 | case 60: { // h2o:h3_accept
2683 | json_write_pair_n(out, STR_LIT("type"), "h3-accept");
2684 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2685 | json_write_pair_c(out, STR_LIT("conn-id"), event->h3_accept.conn_id);
2686 | json_write_pair_c(out, STR_LIT("conn"), event->h3_accept.master_id);
2687 | json_write_pair_c(out, STR_LIT("time"), time_milliseconds());
2688 | break;
2689 | }
2690 | case 61: { // h2o:h3_close
2691 | json_write_pair_n(out, STR_LIT("type"), "h3-close");
2692 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2693 | json_write_pair_c(out, STR_LIT("conn-id"), event->h3_close.conn_id);
2694 | json_write_pair_c(out, STR_LIT("conn"), event->h3_close.master_id);
2695 | json_write_pair_c(out, STR_LIT("time"), time_milliseconds());
2696 | break;
2697 | }
2698 | case 70: { // h2o:send_response_header
2699 | json_write_pair_n(out, STR_LIT("type"), "send-response-header");
2700 | json_write_pair_c(out, STR_LIT("seq"), ++seq);
2701 | json_write_pair_c(out, STR_LIT("conn-id"), event->send_response_header.conn_id);
2702 | json_write_pair_c(out, STR_LIT("req-id"), event->send_response_header.req_id);
2703 | json_write_pair_c(out, STR_LIT("name"), event->send_response_header.name);
2704 | json_write_pair_c(out, STR_LIT("name-len"), event->send_response_header.name_len);
2705 | json_write_pair_c(out, STR_LIT("value"), event->send_response_header.value);
2706 | json_write_pair_c(out, STR_LIT("value-len"), event->send_response_header.value_len);
2707 | json_write_pair_c(out, STR_LIT("conn"), event->send_response_header.master_id);
2708 | json_write_pair_c(out, STR_LIT("time"), time_milliseconds());
2709 | break;
2710 | }
2711 |
2712 | default:
2713 | std::abort();
2714 | }
2715 |
2716 | fprintf(out, "}\n");
2717 | }
2718 |
2719 |
2720 | static void quic_handle_lost(h2o_tracer_t *tracer, uint64_t lost) {
2721 | fprintf(tracer->out, "{"
2722 | "\"type\":\"h2olog-event-lost\","
2723 | "\"seq\":%" PRIu64 ","
2724 | "\"time\":%" PRIu64 ","
2725 | "\"lost\":%" PRIu64
2726 | "}\n",
2727 | ++seq, time_milliseconds(), lost);
2728 | }
2729 |
2730 | static const char *quic_bpf_ext() {
2731 | return bpf_text;
2732 | }
2733 |
2734 | void init_quic_tracer(h2o_tracer_t * tracer) {
2735 | tracer->handle_event = quic_handle_event;
2736 | tracer->handle_lost = quic_handle_lost;
2737 | tracer->init_usdt_probes = quic_init_usdt_probes;
2738 | tracer->bpf_text = quic_bpf_ext;
2739 | }
2740 |
2741 |
--------------------------------------------------------------------------------
/h2o-probes.d:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Fastly, Kazuho Oku
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | provider h2o {
24 | probe h1_accept(uint64_t conn_id, struct st_h2o_socket_t *sock, struct st_h2o_conn_t *conn);
25 | probe h1_close(uint64_t conn_id);
26 | probe h2_unknown_frame_type(uint64_t conn_id, uint8_t frame_type);
27 | probe h3_accept(uint64_t conn_id, struct st_h2o_conn_t *conn, struct st_quicly_conn_t *quic);
28 | probe h3_close(uint64_t conn_id);
29 | probe h3_stream_create(uint64_t conn_id, uint64_t req_id);
30 | probe h3_stream_destroy(uint64_t conn_id, uint64_t req_id);
31 | probe h3_stream_set_state(uint64_t conn_id, uint64_t req_id, unsigned state);
32 | probe h3_packet_receive(struct sockaddr *dest, struct sockaddr *src, const void *base, size_t len);
33 | probe h3_packet_forward(struct sockaddr *dest, struct sockaddr *src, size_t num_packets, size_t num_bytes, int fd);
34 |
35 | probe receive_request(uint64_t conn_id, uint64_t req_id, int http_version);
36 | probe receive_request_header(uint64_t conn_id, uint64_t req_id, const char *name, size_t name_len, const char *value,
37 | size_t value_len);
38 | probe send_response(uint64_t conn_id, uint64_t req_id, int status);
39 | probe send_response_header(uint64_t conn_id, uint64_t req_id, const char *name, size_t name_len, const char *value,
40 | size_t value_len);
41 | };
42 |
--------------------------------------------------------------------------------
/h2olog.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka, Goro Fuji
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include "h2olog.h"
27 |
28 | #define VERSION "0.1.0"
29 | #define POLL_TIMEOUT (1000)
30 | #define PERF_BUFFER_PAGE_COUNT 256
31 |
32 | static void usage(void)
33 | {
34 | printf(R"(h2olog (v%s)
35 | Usage: h2olog -p PID
36 | h2olog quic -p PID
37 | h2olog quic -s response_header_name -p PID
38 | Other options:
39 | -h Print this help and exit
40 | -d Print debugging information
41 | -w Path to write the output (default: stdout)
42 | )",
43 | VERSION);
44 | return;
45 | }
46 |
47 | static void make_timestamp(char *buf, size_t buf_len)
48 | {
49 | time_t t = time(NULL);
50 | struct tm tms;
51 | localtime_r(&t, &tms);
52 | const char *iso8601format = "%FT%TZ";
53 | strftime(buf, buf_len, iso8601format, &tms);
54 | }
55 |
56 | static void infof(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
57 |
58 | static void infof(const char *fmt, ...)
59 | {
60 | char buf[1024];
61 | va_list args;
62 | va_start(args, fmt);
63 | vsnprintf(buf, sizeof(buf), fmt, args);
64 | va_end(args);
65 |
66 | char timestamp[128];
67 | make_timestamp(timestamp, sizeof(timestamp));
68 |
69 | fprintf(stderr, "%s %s\n", timestamp, buf);
70 | }
71 |
72 | static void show_event_per_sec(h2o_tracer_t *tracer, time_t *t0)
73 | {
74 | time_t t1 = time(NULL);
75 | int64_t d = t1 - *t0;
76 | if (d > 10) {
77 | uint64_t c = tracer->count / d;
78 | if (c > 0) {
79 | if (tracer->lost_count > 0) {
80 | infof("%20" PRIu64 " events/s (possibly lost %" PRIu64 " events)", c, tracer->lost_count);
81 | tracer->lost_count = 0;
82 | } else {
83 | infof("%20" PRIu64 " events/s", c);
84 | }
85 | tracer->count = 0;
86 | }
87 | *t0 = t1;
88 | }
89 | }
90 |
91 | static void show_process(pid_t pid)
92 | {
93 | char cmdline[256];
94 | char proc_file[256];
95 | snprintf(proc_file, sizeof(proc_file), "/proc/%d/cmdline", pid);
96 | FILE *f = fopen(proc_file, "r");
97 | if (f == nullptr) {
98 | fprintf(stderr, "Error: failed to open %s: %s\n", proc_file, strerror(errno));
99 | exit(EXIT_FAILURE);
100 | }
101 | size_t nread = fread(cmdline, 1, sizeof(cmdline), f);
102 | fclose(f);
103 | if (nread == 0) {
104 | fprintf(stderr, "Error: failed to read from %s: %s\n", proc_file, strerror(errno));
105 | exit(EXIT_FAILURE);
106 | }
107 | nread--; // skip trailing nul
108 | for (size_t i = 0; i < nread; i++) {
109 | if (cmdline[i] == '\0') {
110 | cmdline[i] = ' ';
111 | }
112 | }
113 | infof("Attaching pid=%d (%s)", pid, cmdline);
114 | }
115 |
116 | static std::string join_str(const std::string &sep, const std::vector &strs)
117 | {
118 | std::string s;
119 | for (auto iter = strs.cbegin(); iter != strs.cend(); ++iter) {
120 | if (iter != strs.cbegin()) {
121 | s += sep;
122 | }
123 | s += *iter;
124 | }
125 | return s;
126 | }
127 |
128 | static std::string generate_header_filter_cflag(const std::vector &tokens)
129 | {
130 | std::vector conditions;
131 |
132 | for (auto &token : tokens) {
133 | char buf[256];
134 | snprintf(buf, sizeof(buf), "/* %s */ (slen) == %zu", token.c_str(), token.size());
135 | std::vector exprs = {buf};
136 |
137 | for (size_t i = 0; i < token.size(); ++i) {
138 | snprintf(buf, sizeof(buf), "(s)[%zu] == '%c'", i, token[i]);
139 | exprs.push_back(buf);
140 | }
141 | conditions.push_back("(" + join_str(" && ", exprs) + ")");
142 | }
143 |
144 | std::string cflag("-DCHECK_ALLOWED_RES_HEADER_NAME(s,slen)=(");
145 | cflag += join_str(" || ", conditions);
146 | cflag += ")";
147 | return cflag;
148 | }
149 |
150 | static std::string make_pid_cflag(const char *macro_name, pid_t pid)
151 | {
152 | char buf[256];
153 | snprintf(buf, sizeof(buf), "-D%s=%d", macro_name, pid);
154 | return std::string(buf);
155 | }
156 |
157 | static void event_cb(void *context, void *data, int len)
158 | {
159 | h2o_tracer_t *tracer = (h2o_tracer_t *)context;
160 | tracer->count++;
161 |
162 | tracer->handle_event(tracer, data, len);
163 | }
164 |
165 | static void lost_cb(void *context, uint64_t lost)
166 | {
167 | h2o_tracer_t *tracer = (h2o_tracer_t *)context;
168 | tracer->lost_count += lost;
169 |
170 | tracer->handle_lost(tracer, lost);
171 | }
172 |
173 | int main(int argc, char **argv)
174 | {
175 | h2o_tracer_t tracer = {};
176 | if (argc > 1 && strcmp(argv[1], "quic") == 0) {
177 | init_quic_tracer(&tracer);
178 | --argc;
179 | ++argv;
180 | } else {
181 | init_http_tracer(&tracer);
182 | }
183 |
184 | bool debug = false;
185 | const char *out_file = nullptr;
186 | std::vector event_type_filters;
187 | std::vector response_header_filters;
188 | int c;
189 | pid_t h2o_pid = -1;
190 | while ((c = getopt(argc, argv, "hdp:t:s:w:")) != -1) {
191 | switch (c) {
192 | case 'p':
193 | h2o_pid = atoi(optarg);
194 | break;
195 | case 't':
196 | event_type_filters.push_back(optarg);
197 | break;
198 | case 's':
199 | response_header_filters.push_back(optarg);
200 | break;
201 | case 'w':
202 | out_file = optarg;
203 | break;
204 | case 'd':
205 | debug = true;
206 | break;
207 | case 'h':
208 | usage();
209 | exit(EXIT_SUCCESS);
210 | default:
211 | usage();
212 | exit(EXIT_FAILURE);
213 | }
214 | }
215 |
216 | if (argc > optind) {
217 | fprintf(stderr, "Error: too many aruments\n");
218 | usage();
219 | exit(EXIT_FAILURE);
220 | }
221 |
222 | if (h2o_pid == -1) {
223 | fprintf(stderr, "Error: -p option is missing\n");
224 | usage();
225 | exit(EXIT_FAILURE);
226 | }
227 |
228 | if (geteuid() != 0) {
229 | fprintf(stderr, "Error: root privilege is required\n");
230 | exit(EXIT_FAILURE);
231 | }
232 |
233 | if (out_file != nullptr) {
234 | FILE *out = fopen(out_file, "w");
235 | if (out == nullptr) {
236 | fprintf(stderr, "Error: failed to open %s: %s", out_file, strerror(errno));
237 | exit(EXIT_FAILURE);
238 | }
239 | tracer.out = out;
240 | } else {
241 | tracer.out = stdout;
242 | }
243 |
244 | std::vector cflags({
245 | make_pid_cflag("H2OLOG_H2O_PID", h2o_pid),
246 | });
247 |
248 | if (!response_header_filters.empty()) {
249 | cflags.push_back(generate_header_filter_cflag(response_header_filters));
250 | }
251 |
252 | ebpf::BPF *bpf = new ebpf::BPF();
253 | std::vector probes = tracer.init_usdt_probes(h2o_pid);
254 |
255 | ebpf::StatusTuple ret = bpf->init(tracer.bpf_text(), cflags, probes);
256 | if (ret.code() != 0) {
257 | fprintf(stderr, "Error: init: %s\n", ret.msg().c_str());
258 | return EXIT_FAILURE;
259 | }
260 |
261 | bpf->attach_tracepoint("sched:sched_process_exit", "trace_sched_process_exit");
262 |
263 | for (auto &probe : probes) {
264 | ret = bpf->attach_usdt(probe);
265 | if (ret.code() != 0) {
266 | fprintf(stderr, "Error: attach_usdt: %s\n", ret.msg().c_str());
267 | return EXIT_FAILURE;
268 | }
269 | }
270 |
271 | ret = bpf->open_perf_buffer("events", event_cb, lost_cb, &tracer, PERF_BUFFER_PAGE_COUNT);
272 | if (ret.code() != 0) {
273 | fprintf(stderr, "Error: open_perf_buffer: %s\n", ret.msg().c_str());
274 | return EXIT_FAILURE;
275 | }
276 |
277 | if (debug) {
278 | show_process(h2o_pid);
279 | }
280 |
281 | ebpf::BPFPerfBuffer *perf_buffer = bpf->get_perf_buffer("events");
282 | if (perf_buffer) {
283 | time_t t0 = time(NULL);
284 |
285 | while (true) {
286 | perf_buffer->poll(POLL_TIMEOUT);
287 | fflush(tracer.out);
288 |
289 | if (debug) {
290 | show_event_per_sec(&tracer, &t0);
291 | }
292 | }
293 | }
294 |
295 | fprintf(stderr, "Error: failed to get_perf_buffer()\n");
296 | return EXIT_FAILURE;
297 | }
298 |
--------------------------------------------------------------------------------
/h2olog.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef h2olog_h
24 | #define h2olog_h
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | struct st_h2o_tracer_t;
31 | typedef struct st_h2o_tracer_t h2o_tracer_t;
32 |
33 | struct st_h2o_tracer_t {
34 | /*
35 | * Where to output the results. Defaults to `stdout`.
36 | */
37 | FILE *out;
38 |
39 | /*
40 | * The number of events emitted in `handle_event`.
41 | */
42 | uint64_t count;
43 |
44 | /*
45 | * The number of lost events. It is reset periodically.
46 | */
47 | uint64_t lost_count;
48 |
49 | /*
50 | * Handles an incoming BPF event.
51 | */
52 | void (*handle_event)(h2o_tracer_t *tracer, const void *data, int len);
53 |
54 | /*
55 | * Handles an event data lost.
56 | */
57 | void (*handle_lost)(h2o_tracer_t *tracer, uint64_t lost);
58 |
59 | /*
60 | * Returns a vector of relevant USDT probes.
61 | */
62 | std::vector (*init_usdt_probes)(pid_t h2o_pid);
63 |
64 | /*
65 | * Returns the code to be compiled into BPF bytecode.
66 | */
67 | const char *(*bpf_text)(void);
68 | };
69 |
70 | /*
71 | * Initialize an HTTP tracer.
72 | */
73 | void init_http_tracer(h2o_tracer_t *);
74 |
75 | /*
76 | * Initialize a QUIC tracer.
77 | */
78 | void init_quic_tracer(h2o_tracer_t *);
79 |
80 | #endif
81 |
--------------------------------------------------------------------------------
/http.cc:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #include "h2olog.h"
24 |
25 | const char *HTTP_BPF = R"(
26 | #include
27 |
28 | #define MAX_HDR_LEN 128
29 |
30 | enum {
31 | HTTP_EVENT_RECEIVE_REQ,
32 | HTTP_EVENT_RECEIVE_REQ_HDR,
33 | HTTP_EVENT_SEND_RESP,
34 | HTTP_EVENT_SEND_RESP_HDR,
35 | SCHED_PROCESS_EXIT,
36 | };
37 |
38 | typedef struct st_http_event_t {
39 | uint8_t type;
40 | uint64_t conn_id;
41 | uint64_t req_id;
42 | union {
43 | uint32_t http_version;
44 | uint32_t http_status;
45 | struct {
46 | uint64_t name_len;
47 | uint64_t value_len;
48 | char name[MAX_HDR_LEN];
49 | char value[MAX_HDR_LEN];
50 | } header;
51 | };
52 | } http_event_t;
53 |
54 | BPF_PERF_OUTPUT(events);
55 |
56 | int trace_sched_process_exit(struct tracepoint__sched__sched_process_exit *ctx) {
57 | const struct task_struct *task = (const struct task_struct*)bpf_get_current_task();
58 | pid_t h2o_pid = task->tgid;
59 | pid_t h2o_tid = task->pid;
60 | if (!(h2o_pid == H2OLOG_H2O_PID && h2o_tid == H2OLOG_H2O_PID)) {
61 | return 0;
62 | }
63 | http_event_t ev = { .type = SCHED_PROCESS_EXIT };
64 | events.perf_submit(ctx, &ev, sizeof(ev));
65 | return 0;
66 | }
67 |
68 | int trace_receive_request(struct pt_regs *ctx) {
69 | http_event_t ev = { .type = HTTP_EVENT_RECEIVE_REQ };
70 | bpf_usdt_readarg(1, ctx, &ev.conn_id);
71 | bpf_usdt_readarg(2, ctx, &ev.req_id);
72 | bpf_usdt_readarg(3, ctx, &ev.http_version);
73 | events.perf_submit(ctx, &ev, sizeof(ev));
74 | return 0;
75 | }
76 |
77 | int trace_receive_request_header(struct pt_regs *ctx) {
78 | http_event_t ev = { .type = HTTP_EVENT_RECEIVE_REQ_HDR };
79 | void *pos = NULL;
80 | bpf_usdt_readarg(1, ctx, &ev.conn_id);
81 | bpf_usdt_readarg(2, ctx, &ev.req_id);
82 | bpf_usdt_readarg(3, ctx, &pos);
83 | bpf_usdt_readarg(4, ctx, &ev.header.name_len);
84 | bpf_probe_read(&ev.header.name, sizeof(ev.header.name), pos);
85 | bpf_usdt_readarg(5, ctx, &pos);
86 | bpf_usdt_readarg(6, ctx, &ev.header.value_len);
87 | bpf_probe_read(&ev.header.value, sizeof(ev.header.value), pos);
88 | events.perf_submit(ctx, &ev, sizeof(ev));
89 | return 0;
90 | }
91 |
92 | int trace_send_response(struct pt_regs *ctx) {
93 | http_event_t ev = { .type = HTTP_EVENT_SEND_RESP };
94 | bpf_usdt_readarg(1, ctx, &ev.conn_id);
95 | bpf_usdt_readarg(2, ctx, &ev.req_id);
96 | bpf_usdt_readarg(3, ctx, &ev.http_status);
97 | events.perf_submit(ctx, &ev, sizeof(ev));
98 | return 0;
99 | }
100 |
101 | int trace_send_response_header(struct pt_regs *ctx) {
102 | http_event_t ev = { .type = HTTP_EVENT_SEND_RESP_HDR };
103 | void *pos = NULL;
104 | bpf_usdt_readarg(1, ctx, &ev.conn_id);
105 | bpf_usdt_readarg(2, ctx, &ev.req_id);
106 | bpf_usdt_readarg(3, ctx, &pos);
107 | bpf_usdt_readarg(4, ctx, &ev.header.name_len);
108 | bpf_probe_read(&ev.header.name, sizeof(ev.header.name), pos);
109 | bpf_usdt_readarg(5, ctx, &pos);
110 | bpf_usdt_readarg(6, ctx, &ev.header.value_len);
111 | bpf_probe_read(&ev.header.value, sizeof(ev.header.value), pos);
112 | events.perf_submit(ctx, &ev, sizeof(ev));
113 | return 0;
114 | }
115 | )";
116 |
117 | #define MAX_HDR_LEN 128
118 | #define MIN(x, y) (((x) < (y)) ? (x) : (y))
119 |
120 | enum {
121 | HTTP_EVENT_RECEIVE_REQ,
122 | HTTP_EVENT_RECEIVE_REQ_HDR,
123 | HTTP_EVENT_SEND_RESP,
124 | HTTP_EVENT_SEND_RESP_HDR,
125 | SCHED_PROCESS_EXIT,
126 | };
127 |
128 | typedef struct st_http_event_t {
129 | uint8_t type;
130 | uint64_t conn_id;
131 | uint64_t req_id;
132 | union {
133 | uint32_t http_version;
134 | uint32_t http_status;
135 | struct {
136 | uint64_t name_len;
137 | uint64_t value_len;
138 | char name[MAX_HDR_LEN];
139 | char value[MAX_HDR_LEN];
140 | } header;
141 | };
142 | } http_event_t;
143 |
144 | static void handle_event(h2o_tracer_t *tracer, const void *data, int len)
145 | {
146 | const http_event_t *ev = (const http_event_t *)data;
147 | FILE *out = tracer->out;
148 |
149 | switch (ev->type) {
150 | case HTTP_EVENT_RECEIVE_REQ:
151 | fprintf(out, "%" PRIu64 " %" PRIu64 " RxProtocol HTTP/%" PRIu32 ".%" PRIu32 "\n", ev->conn_id, ev->req_id,
152 | ev->http_version / 256, ev->http_version % 256);
153 | break;
154 | case HTTP_EVENT_SEND_RESP:
155 | fprintf(out, "%" PRIu64 " %" PRIu64 " TxStatus %" PRIu32 "\n", ev->conn_id, ev->req_id, ev->http_status);
156 | break;
157 | case HTTP_EVENT_RECEIVE_REQ_HDR:
158 | case HTTP_EVENT_SEND_RESP_HDR: {
159 | int n_len = MIN(ev->header.name_len, MAX_HDR_LEN);
160 | int v_len = MIN(ev->header.value_len, MAX_HDR_LEN);
161 | const char *label = (ev->type == HTTP_EVENT_RECEIVE_REQ_HDR) ? "RxHeader" : "TxHeader";
162 | fprintf(out, "%" PRIu64 " %" PRIu64 " %s %.*s %.*s\n", ev->conn_id, ev->req_id, label, n_len, ev->header.name, v_len,
163 | ev->header.value);
164 | } break;
165 | case SCHED_PROCESS_EXIT: {
166 | exit(0);
167 | } break;
168 | default:
169 | fprintf(out, "unknown event: %u\n", ev->type);
170 | }
171 | }
172 |
173 | static void handle_lost(h2o_tracer_t *tracer, uint64_t lost)
174 | {
175 | fprintf(stderr, "Possibly lost %" PRIu64 " events\n", lost);
176 | }
177 |
178 | static std::vector init_usdt_probes(pid_t h2o_pid)
179 | {
180 | const std::vector vec{
181 | ebpf::USDT(h2o_pid, "h2o", "receive_request", "trace_receive_request"),
182 | ebpf::USDT(h2o_pid, "h2o", "receive_request_header", "trace_receive_request_header"),
183 | ebpf::USDT(h2o_pid, "h2o", "send_response", "trace_send_response"),
184 | ebpf::USDT(h2o_pid, "h2o", "send_response_header", "trace_send_response_header"),
185 | };
186 | return vec;
187 | }
188 |
189 | static const char *bpf_text(void)
190 | {
191 | return HTTP_BPF;
192 | }
193 |
194 | void init_http_tracer(h2o_tracer_t *tracer)
195 | {
196 | tracer->handle_event = handle_event;
197 | tracer->handle_lost = handle_lost;
198 | tracer->init_usdt_probes = init_usdt_probes;
199 | tracer->bpf_text = bpf_text;
200 | }
201 |
--------------------------------------------------------------------------------
/json.cc:
--------------------------------------------------------------------------------
1 | #include "json.h"
2 | #include
3 | #include
4 |
5 | #define FPUTS_LIT(s, out) fwrite(s, 1, strlen(s), out)
6 |
7 | static bool json_need_escape(char c)
8 | {
9 | return static_cast(c) < 0x20 || c == 0x7f;
10 | }
11 |
12 | static void json_write_str_value(FILE *out, const char *str)
13 | {
14 | fputc('"', out);
15 | while (*str) {
16 | switch (*str) {
17 | case '\"':
18 | FPUTS_LIT("\\\"", out);
19 | break;
20 | case '\\':
21 | FPUTS_LIT("\\\\", out);
22 | break;
23 | case '\b':
24 | FPUTS_LIT("\\b", out);
25 | break;
26 | case '\f':
27 | FPUTS_LIT("\\f", out);
28 | break;
29 | case '\n':
30 | FPUTS_LIT("\\n", out);
31 | break;
32 | case '\r':
33 | FPUTS_LIT("\\r", out);
34 | break;
35 | case '\t':
36 | FPUTS_LIT("\\t", out);
37 | break;
38 | default:
39 | if (!json_need_escape(*str)) {
40 | fputc(*str, out);
41 | } else {
42 | auto u8 = static_cast(*str);
43 | fprintf(out, "\\u%04x", u8);
44 | }
45 | break;
46 | }
47 | str++;
48 | }
49 | fputc('"', out);
50 | }
51 |
52 | static void json_write_name_value(FILE *out, const char *name, size_t name_len)
53 | {
54 | fputc('"', out);
55 | fwrite(name, 1, name_len, out);
56 | fputc('"', out);
57 | fputc(':', out);
58 | }
59 |
60 | void json_write_pair_n(FILE *out, const char *name, size_t name_len, const char *value)
61 | {
62 | json_write_name_value(out, name, name_len);
63 | json_write_str_value(out, value);
64 | }
65 |
66 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, const char *value)
67 | {
68 | fputc(',', out);
69 | json_write_name_value(out, name, name_len);
70 | json_write_str_value(out, value);
71 | }
72 |
73 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, const void *value, size_t len)
74 | {
75 | fputc(',', out);
76 | json_write_name_value(out, name, name_len);
77 | fputc('"', out);
78 | const uint8_t *bin = static_cast(value);
79 | for (size_t i = 0; i < len; i++) {
80 | fputc("0123456789abcdef"[bin[i] >> 4], out);
81 | fputc("0123456789abcdef"[bin[i] & 0xf], out);
82 | }
83 | fputc('"', out);
84 | }
85 |
86 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, int32_t value)
87 | {
88 | json_write_pair_c(out, name, name_len, static_cast(value));
89 | }
90 |
91 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, uint32_t value)
92 | {
93 | json_write_pair_c(out, name, name_len, static_cast(value));
94 | }
95 |
96 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, int64_t value)
97 | {
98 | fputc(',', out);
99 | json_write_name_value(out, name, name_len);
100 | fprintf(out, "%" PRId64, value);
101 | }
102 |
103 | void json_write_pair_c(FILE *out, const char *name, size_t name_len, uint64_t value)
104 | {
105 | fputc(',', out);
106 | json_write_name_value(out, name, name_len);
107 | fprintf(out, "%" PRIu64, value);
108 | }
109 |
--------------------------------------------------------------------------------
/json.h:
--------------------------------------------------------------------------------
1 | #ifndef H2OLOG_JSON_UTILS_H
2 | #define H2OLOG_JSON_UTILS_H
3 |
4 | #include
5 | #include
6 |
7 | // "_n" suffix means "with no heading comma"
8 | // "_c" suffix means "with a heading comma"
9 |
10 | void json_write_pair_n(std::FILE *out, const char *name, size_t name_len, const char *value);
11 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const char *value);
12 |
13 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const void *value, std::size_t len);
14 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const std::int64_t value);
15 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const std::uint64_t value);
16 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const std::int32_t value);
17 | void json_write_pair_c(std::FILE *out, const char *name, size_t name_len, const std::uint32_t value);
18 |
19 | #endif
--------------------------------------------------------------------------------
/make.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | set -xe
3 |
4 | CC=clang CXX=clang++ cmake -H. -Bbuild
5 | make -Cbuild VERBOSE=1
6 |
--------------------------------------------------------------------------------
/misc/autopep8:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | SCRIPT_DIR="$PWD/$(dirname $0)"
4 |
5 | export PYTHONPATH="$SCRIPT_DIR/.pip3/lib/python3.5/site-packages"
6 | export PATH="$SCRIPT_DIR/.pip3/bin:$PATH"
7 |
8 | if ! autopep8 --version > /dev/null 2>/dev/null
9 | then
10 | echo "autopep8 is not found. Please install it by the following command:"
11 | echo "sudo pip3 install pep8 autopep8"
12 | exit 1
13 | fi
14 |
15 | exec autopep8 "$@"
16 |
--------------------------------------------------------------------------------
/misc/gen-quic-bpf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | #
3 | # Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka, Goro Fuji
4 | #
5 | # Permission is hereby granted, free of charge, to any person obtaining a copy
6 | # of this software and associated documentation files (the "Software"), to
7 | # deal in the Software without restriction, including without limitation the
8 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 | # sell copies of the Software, and to permit persons to whom the Software is
10 | # furnished to do so, subject to the following conditions:
11 | #
12 | # The above copyright notice and this permission notice shall be included in
13 | # all copies or substantial portions of the Software.
14 | #
15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 | # IN THE SOFTWARE.
22 |
23 | # usage: gen-quic-bpf.py d_files_dir output_file
24 |
25 | import re
26 | import sys
27 | from collections import OrderedDict
28 | from pathlib import Path
29 | from pprint import pprint
30 |
31 | block_fields = {
32 | "quicly:crypto_decrypt": set(["decrypted"]),
33 | "quicly:crypto_update_secret": set(["secret"]),
34 | "quicly:crypto_send_key_update": set(["secret"]),
35 | "quicly:crypto_receive_key_update": set(["secret"]),
36 | "quicly:crypto_receive_key_update_prepare": set(["secret"]),
37 |
38 | "h2o:h3_accept": set(["conn"]), # `h2o_conn_t *conn`
39 | }
40 |
41 | quicly_block_probes = set([
42 | "quicly:debug_message",
43 | ])
44 |
45 | h2o_allow_probes = set([
46 | "h2o:h3_accept",
47 | "h2o:h3_close",
48 | "h2o:send_response_header",
49 | ])
50 |
51 | # convert field names for compatibility with:
52 | # https://github.com/h2o/quicly/blob/master/quictrace-adapter.py
53 | rename_map = {
54 | # common fields
55 | "at": "time",
56 | "master_id": "conn",
57 |
58 | # changed in the latest quicly master branch
59 | "num_bytes": "bytes_len",
60 |
61 | # quicly_rtt_t
62 | "minimum": "min-rtt",
63 | "smoothed": "smoothed-rtt",
64 | "variance": "variance-rtt",
65 | "latest": "latest-rtt",
66 | }
67 |
68 | data_types_h = Path(Path(__file__).parent.parent, "quic.h")
69 |
70 | re_flags = re.X | re.M | re.S
71 | whitespace = r'(?:/\*.*?\*/|\s+)'
72 | probe_decl = r'(?:\bprobe\s+(?:[a-zA-Z0-9_]+)\s*\([^\)]*\)\s*;)'
73 | d_decl = r'(?:\bprovider\s*(?P[a-zA-Z0-9_]+)\s*\{(?P(?:%s|%s)*)\})' % (
74 | probe_decl, whitespace)
75 |
76 |
77 | def parse_c_struct(path):
78 | content = path.read_text()
79 |
80 | st_map = OrderedDict()
81 | for (st_name, st_content) in re.findall(r'struct\s+([a-zA-Z0-9_]+)\s*\{([^}]*)\}', content, flags=re_flags):
82 | st = st_map[st_name] = OrderedDict()
83 | for (ctype, name, is_array) in re.findall(r'(\w+[^;]*[\w\*])\s+([a-zA-Z0-9_]+)(\[\d+\])?;', st_content, flags=re_flags):
84 | if "dummy" in name:
85 | continue
86 | st[name] = ctype + is_array
87 | return st_map
88 |
89 |
90 | def parse_d(context: dict, path: Path, allow_probes: set = None, block_probes: set = None):
91 | content = path.read_text()
92 |
93 | matched = re.search(d_decl, content, flags=re_flags)
94 | provider = matched.group('provider')
95 |
96 | st_map = context["st_map"]
97 | probe_metadata = context["probe_metadata"]
98 |
99 | id = context["id"]
100 |
101 | for (name, args) in re.findall(r'\bprobe\s+([a-zA-Z0-9_]+)\(([^\)]+)\);', matched.group('probes'), flags=re_flags):
102 | arg_list = re.split(r'\s*,\s*', args, flags=re_flags)
103 | id += 1
104 |
105 | fully_specified_probe_name = "%s:%s" % (provider, name)
106 | if block_probes and fully_specified_probe_name in block_probes:
107 | continue
108 | if allow_probes and fully_specified_probe_name not in allow_probes:
109 | continue
110 |
111 | metadata = {
112 | "id": id,
113 | "provider": provider,
114 | "name": name,
115 | "fully_specified_probe_name": fully_specified_probe_name,
116 | }
117 | probe_metadata[name] = metadata
118 | args = metadata['args'] = list(map(
119 | lambda arg: re.match(
120 | r'(?P\w[^;]*[^;\s])\s*\b(?P[a-zA-Z0-9_]+)', arg, flags=re_flags).groupdict(),
121 | arg_list))
122 |
123 | flat_args_map = metadata['flat_args_map'] = OrderedDict()
124 |
125 | for arg in args:
126 | arg_name = arg['name']
127 | arg_type = arg['type']
128 |
129 | if is_ptr_type(arg_type) and not is_str_type(arg_type):
130 | for st_key, st_valtype in st_map[strip_typename(arg_type)].items():
131 | flat_args_map[st_key] = st_valtype
132 | else:
133 | flat_args_map[arg_name] = arg_type
134 |
135 | context["id"] = id
136 |
137 |
138 | def strip_typename(t):
139 | return t.replace("*", "").replace("struct", "").replace("const", "").replace("strict", "").strip()
140 |
141 |
142 | def is_str_type(t):
143 | return re.search(r'\b(?:char|u?int8_t|void)\s*\*', t)
144 |
145 |
146 | def is_ptr_type(t):
147 | return "*" in t
148 |
149 |
150 | def is_bin_type(t):
151 | return re.search(r'\b(?:u?int8_t|void)\s*\*', t)
152 |
153 |
154 | def build_tracer_name(metadata):
155 | return "trace_%s__%s" % (metadata['provider'], metadata['name'])
156 |
157 |
158 | def build_tracer(context, metadata):
159 | st_map = context["st_map"]
160 | fully_specified_probe_name = metadata["fully_specified_probe_name"]
161 |
162 | c = r"""// %s
163 | int %s(struct pt_regs *ctx) {
164 | void *buf = NULL;
165 | struct quic_event_t event = { .id = %d };
166 |
167 | """ % (fully_specified_probe_name, build_tracer_name(metadata), metadata['id'])
168 | block_field_set = block_fields.get(fully_specified_probe_name, set())
169 | probe_name = metadata["name"]
170 |
171 | args = metadata['args']
172 | for i in range(len(args)):
173 | arg = args[i]
174 | arg_name = arg['name']
175 | arg_type = arg['type']
176 |
177 | if arg_name in block_field_set:
178 | c += " // %s %s (ignored)\n" % (arg_type, arg_name)
179 | continue
180 | else:
181 | c += " // %s %s\n" % (arg_type, arg_name)
182 |
183 | if is_str_type(arg_type):
184 | c += " bpf_usdt_readarg(%d, ctx, &buf);\n" % (i+1)
185 | # Use `sizeof(buf)` instead of a length variable, because older kernels
186 | # do not accept a variable for `bpf_probe_read()`'s length parameter.
187 | event_t_name = "%s.%s" % (probe_name, arg_name)
188 | c += " bpf_probe_read(&event.%s, sizeof(event.%s), buf);\n" % (
189 | event_t_name, event_t_name)
190 | elif is_ptr_type(arg_type):
191 | c += " %s %s = {};\n" % (arg_type.replace("*", ""), arg_name)
192 | c += " bpf_usdt_readarg(%d, ctx, &buf);\n" % (i+1)
193 | c += " bpf_probe_read(&%s, sizeof(%s), buf);\n" % (arg_name, arg_name)
194 | for st_key, st_valtype in st_map[strip_typename(arg_type)].items():
195 | event_t_name = "%s.%s" % (probe_name, st_key)
196 | c += " event.%s = %s.%s; /* %s */\n" % (
197 | event_t_name, arg_name, st_key, st_valtype)
198 | else:
199 | event_t_name = "%s.%s" % (probe_name, arg_name)
200 | c += " bpf_usdt_readarg(%d, ctx, &event.%s);\n" % (i +
201 | 1, event_t_name)
202 |
203 | if fully_specified_probe_name == "h2o:h3_accept":
204 | c += r"""
205 | h2o_to_quicly_conn.update(&event.h3_accept.conn_id, &event.h3_accept.master_id);
206 | """
207 | elif fully_specified_probe_name == "h2o:h3_close":
208 | c += r"""
209 | const uint32_t *master_conn_id_ptr = h2o_to_quicly_conn.lookup(&event.h3_close.conn_id);
210 | if (master_conn_id_ptr != NULL) {
211 | event.h3_close.master_id = *master_conn_id_ptr;
212 | } else {
213 | bpf_trace_printk("h2o's conn_id=%lu is not associated to master_conn_id\n", event.h3_close.conn_id);
214 | }
215 | h2o_to_quicly_conn.delete(&event.h3_close.conn_id);
216 | """
217 | elif metadata["provider"] == "h2o":
218 | c += r"""
219 | const uint32_t *master_conn_id_ptr = h2o_to_quicly_conn.lookup(&event.%s.conn_id);
220 | if (master_conn_id_ptr == NULL)
221 | return 0;
222 | event.%s.master_id = *master_conn_id_ptr;
223 | """ % (probe_name, probe_name)
224 | if fully_specified_probe_name == "h2o:send_response_header":
225 | # handle -s option
226 | c += r"""
227 | #ifdef CHECK_ALLOWED_RES_HEADER_NAME
228 | if (!CHECK_ALLOWED_RES_HEADER_NAME(event.send_response_header.name, event.send_response_header.name_len))
229 | return 0;
230 | #endif
231 | """
232 |
233 | c += r"""
234 | if (events.perf_submit(ctx, &event, sizeof(event)) != 0)
235 | bpf_trace_printk("failed to perf_submit\n");
236 |
237 | return 0;
238 | }
239 | """
240 | return c
241 |
242 |
243 | def prepare_context(d_files_dir):
244 | st_map = parse_c_struct(data_types_h)
245 | context = {
246 | "id": 1, # 1 is used for sched:sched_process_exit
247 | "probe_metadata": OrderedDict(),
248 | "st_map": st_map,
249 | }
250 | parse_d(context, Path(d_files_dir, "quicly-probes.d"),
251 | block_probes=quicly_block_probes)
252 | parse_d(context, Path(d_files_dir, "h2o-probes.d"),
253 | allow_probes=h2o_allow_probes)
254 |
255 | return context
256 |
257 |
258 | def generate_cplusplus(context, output_file):
259 |
260 | probe_metadata = context["probe_metadata"]
261 |
262 | event_t_decl = r"""
263 | struct quic_event_t {
264 | uint8_t id;
265 |
266 | union {
267 | """
268 |
269 | for name, metadata in probe_metadata.items():
270 | fully_specified_probe_name = metadata["fully_specified_probe_name"]
271 | block_field_set = block_fields.get(fully_specified_probe_name, None)
272 |
273 | event_t_decl += " struct { // %s\n" % fully_specified_probe_name
274 | for field_name, field_type in metadata["flat_args_map"].items():
275 | if block_field_set and field_name in block_field_set:
276 | continue
277 |
278 | if fully_specified_probe_name == "quicly:receive" and field_name == "bytes":
279 | f = "uint8_t %s[1]" % field_name # for first-octet
280 | elif is_bin_type(field_type):
281 | f = "uint8_t %s[STR_LEN]" % field_name
282 | elif is_str_type(field_type):
283 | f = "char %s[STR_LEN]" % field_name
284 | else:
285 | f = "%s %s" % (field_type, field_name)
286 |
287 | event_t_decl += " %s;\n" % f
288 | if metadata["provider"] == "h2o" and name != "h3_accept":
289 | event_t_decl += " uint32_t master_id;\n"
290 | event_t_decl += " } %s;\n" % name
291 |
292 | event_t_decl += r"""
293 | };
294 | };
295 | """
296 |
297 | bpf = r"""
298 | #include
299 |
300 | #define STR_LEN 64
301 | %s
302 | %s
303 | BPF_PERF_OUTPUT(events);
304 |
305 | // HTTP/3 tracing
306 | BPF_HASH(h2o_to_quicly_conn, u64, u32);
307 |
308 | // tracepoint sched:sched_process_exit
309 | int trace_sched_process_exit(struct tracepoint__sched__sched_process_exit *ctx) {
310 | const struct task_struct *task = (const struct task_struct*)bpf_get_current_task();
311 | pid_t h2o_pid = task->tgid;
312 | pid_t h2o_tid = task->pid;
313 | if (!(h2o_pid == H2OLOG_H2O_PID && h2o_tid == H2OLOG_H2O_PID)) {
314 | return 0;
315 | }
316 | struct quic_event_t ev = { .id = 1 };
317 | events.perf_submit(ctx, &ev, sizeof(ev));
318 | return 0;
319 | }
320 |
321 | """ % (data_types_h.read_text(), event_t_decl)
322 |
323 | usdt_def = """
324 | static
325 | std::vector quic_init_usdt_probes(pid_t pid) {
326 | const std::vector probes = {
327 | """
328 |
329 | for metadata in probe_metadata.values():
330 | bpf += build_tracer(context, metadata)
331 | usdt_def += """ ebpf::USDT(pid, "%s", "%s", "%s"),\n""" % (
332 | metadata['provider'], metadata['name'], build_tracer_name(metadata))
333 |
334 | usdt_def += """
335 | };
336 | return probes;
337 | }
338 | """
339 |
340 | handle_event_func = r"""
341 | static
342 | void quic_handle_event(h2o_tracer_t *tracer, const void *data, int data_len) {
343 | FILE *out = tracer->out;
344 |
345 | const quic_event_t *event = static_cast(data);
346 |
347 | if (event->id == 1) { // sched:sched_process_exit
348 | exit(0);
349 | }
350 |
351 | // output JSON
352 | fprintf(out, "{");
353 |
354 | switch (event->id) {
355 | """
356 |
357 | for probe_name in probe_metadata:
358 | metadata = probe_metadata[probe_name]
359 | fully_specified_probe_name = metadata["fully_specified_probe_name"]
360 |
361 | block_field_set = block_fields.get(fully_specified_probe_name, None)
362 | flat_args_map = metadata["flat_args_map"]
363 |
364 | handle_event_func += " case %s: { // %s\n" % (
365 | metadata['id'], fully_specified_probe_name)
366 | handle_event_func += ' json_write_pair_n(out, STR_LIT("type"), "%s");\n' % probe_name.replace("_", "-")
367 | handle_event_func += ' json_write_pair_c(out, STR_LIT("seq"), ++seq);\n'
368 |
369 | for field_name, field_type in flat_args_map.items():
370 | if block_field_set and field_name in block_field_set:
371 | continue
372 | json_field_name = rename_map.get(field_name, field_name).replace("_", "-")
373 | event_t_name = "%s.%s" % (probe_name, field_name)
374 | if fully_specified_probe_name == "quicly:receive" and field_name == "bytes":
375 | handle_event_func += ' json_write_pair_c(out, STR_LIT("first-octet"), event->receive.bytes[0]);\n'
376 | elif not is_bin_type(field_type):
377 | handle_event_func += ' json_write_pair_c(out, STR_LIT("%s"), event->%s);\n' % (
378 | json_field_name, event_t_name)
379 | else: # bin type (it should have the correspinding length arg)
380 | len_names = set([field_name + "_len", "len", "num_" + field_name])
381 |
382 | for n in flat_args_map:
383 | if n in len_names:
384 | len_event_t_name = "%s.%s" % (probe_name, n)
385 |
386 | # A string might be truncated in STRLEN
387 | handle_event_func += ' json_write_pair_c(out, STR_LIT("%s"), event->%s, (event->%s < STR_LEN ? event->%s : STR_LEN));\n' % (
388 | json_field_name, event_t_name, len_event_t_name, len_event_t_name)
389 |
390 | if metadata["provider"] == "h2o":
391 | if probe_name != "h3_accept":
392 | handle_event_func += ' json_write_pair_c(out, STR_LIT("conn"), event->%s.master_id);\n' % (
393 | probe_name)
394 | handle_event_func += ' json_write_pair_c(out, STR_LIT("time"), time_milliseconds());\n'
395 |
396 | handle_event_func += " break;\n"
397 | handle_event_func += " }\n"
398 |
399 | handle_event_func += r"""
400 | default:
401 | std::abort();
402 | }
403 |
404 | fprintf(out, "}\n");
405 | """
406 | handle_event_func += "}\n"
407 |
408 | Path(output_file).write_text(r"""// Generated code. Do not edit it here!
409 |
410 | #include
411 | #include
412 | #include
413 | #include
414 | #include
415 | #include "h2olog.h"
416 | #include "quic.h"
417 | #include "json.h"
418 |
419 | #define STR_LEN 64
420 | #define STR_LIT(s) s, strlen(s)
421 |
422 | uint64_t seq = 0;
423 |
424 | // BPF modules written in C
425 | const char *bpf_text = R"(
426 | %s
427 | )";
428 |
429 | static uint64_t time_milliseconds()
430 | {
431 | struct timeval tv;
432 | gettimeofday(&tv, NULL);
433 | return (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
434 | }
435 |
436 | %s
437 | %s
438 | %s
439 |
440 | static void quic_handle_lost(h2o_tracer_t *tracer, uint64_t lost) {
441 | fprintf(tracer->out, "{"
442 | "\"type\":\"h2olog-event-lost\","
443 | "\"seq\":%%" PRIu64 ","
444 | "\"time\":%%" PRIu64 ","
445 | "\"lost\":%%" PRIu64
446 | "}\n",
447 | ++seq, time_milliseconds(), lost);
448 | }
449 |
450 | static const char *quic_bpf_ext() {
451 | return bpf_text;
452 | }
453 |
454 | void init_quic_tracer(h2o_tracer_t * tracer) {
455 | tracer->handle_event = quic_handle_event;
456 | tracer->handle_lost = quic_handle_lost;
457 | tracer->init_usdt_probes = quic_init_usdt_probes;
458 | tracer->bpf_text = quic_bpf_ext;
459 | }
460 |
461 | """ % (bpf, usdt_def, event_t_decl, handle_event_func))
462 |
463 |
464 | def main():
465 | try:
466 | (_, d_files_dir, output_file) = sys.argv
467 | except:
468 | print("usage: %s d_files_dir output_file" % sys.argv[0])
469 | sys.exit(1)
470 |
471 | context = prepare_context(d_files_dir)
472 | generate_cplusplus(context, output_file)
473 |
474 |
475 | if __name__ == "__main__":
476 | main()
477 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.autopep8]
2 | max_line_length = 200
3 | indent_size = 2
4 |
--------------------------------------------------------------------------------
/quic.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019-2020 Fastly, Inc., Toru Maesaka, Goro Fuji
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef H2OLOG_QUIC_H
24 | #define H2OLOG_QUIC_H
25 |
26 | /*
27 | * These structs mirror H2O's internal structs. As the name suggests, dummy
28 | * fields are paddings that are ignored.
29 | */
30 | struct st_quicly_stream_t {
31 | uint64_t dummy;
32 | int64_t stream_id;
33 | };
34 |
35 | struct st_quicly_conn_t {
36 | uint32_t dummy[4];
37 | uint32_t master_id;
38 | };
39 |
40 | struct quicly_rtt_t {
41 | uint32_t minimum;
42 | uint32_t smoothed;
43 | uint32_t variance;
44 | uint32_t latest;
45 | };
46 |
47 | struct st_quicly_address_token_plaintext_t {
48 | int dummy;
49 | };
50 |
51 | struct st_h2o_conn_t {
52 | int dummy;
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/quicly-probes.d:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Fastly, Kazuho Oku
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to
6 | * deal in the Software without restriction, including without limitation the
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 | * sell copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | /**
24 | * Providers of quicly. Name of the arguments are important - they are used as the names of JSON fields when the dtrace script is
25 | * generated.
26 | */
27 | provider quicly {
28 | probe connect(struct st_quicly_conn_t *conn, int64_t at, uint32_t version);
29 | probe accept(struct st_quicly_conn_t *conn, int64_t at, const char *dcid,
30 | struct st_quicly_address_token_plaintext_t *address_token);
31 | probe free(struct st_quicly_conn_t *conn, int64_t at);
32 | probe send(struct st_quicly_conn_t *conn, int64_t at, int state, const char *dcid);
33 | probe receive(struct st_quicly_conn_t *conn, int64_t at, const char *dcid, const void *bytes, size_t num_bytes);
34 | probe version_switch(struct st_quicly_conn_t *conn, int64_t at, uint32_t new_version);
35 | probe idle_timeout(struct st_quicly_conn_t *conn, int64_t at);
36 | probe stateless_reset_receive(struct st_quicly_conn_t *conn, int64_t at);
37 |
38 | probe crypto_decrypt(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn, const void *decrypted, size_t decrypted_len);
39 | probe crypto_handshake(struct st_quicly_conn_t *conn, int64_t at, int ret);
40 | probe crypto_update_secret(struct st_quicly_conn_t *conn, int64_t at, int is_enc, uint8_t epoch, const char *label, const char *secret);
41 | probe crypto_send_key_update(struct st_quicly_conn_t *conn, int64_t at, uint64_t phase, const char *secret);
42 | probe crypto_send_key_update_confirmed(struct st_quicly_conn_t *conn, int64_t at, uint64_t next_pn);
43 | probe crypto_receive_key_update(struct st_quicly_conn_t *conn, int64_t at, uint64_t phase, const char *secret);
44 | probe crypto_receive_key_update_prepare(struct st_quicly_conn_t *conn, int64_t at, uint64_t phase, const char *secret);
45 |
46 | probe packet_prepare(struct st_quicly_conn_t *conn, int64_t at, uint8_t first_octet, const char *dcid);
47 | probe packet_commit(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn, size_t len, int ack_only);
48 | probe packet_acked(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn, int newly_acked);
49 | probe packet_lost(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn);
50 |
51 | probe pto(struct st_quicly_conn_t *conn, int64_t at, size_t inflight, uint32_t cwnd, int8_t pto_count);
52 | probe cc_ack_received(struct st_quicly_conn_t *conn, int64_t at, uint64_t largest_acked, size_t bytes_acked, uint32_t cwnd,
53 | size_t inflight);
54 | probe cc_congestion(struct st_quicly_conn_t *conn, int64_t at, uint64_t max_lost_pn, size_t inflight, uint32_t cwnd);
55 |
56 | probe transport_close_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t error_code, uint64_t frame_type,
57 | const char *reason_phrase);
58 | probe transport_close_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t error_code, uint64_t frame_type,
59 | const char *reason_phrase);
60 | probe application_close_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t error_code, const char *reason_phrase);
61 | probe application_close_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t error_code, const char *reason_phrase);
62 |
63 | probe stream_send(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stream_t *stream, uint64_t off, size_t len,
64 | int is_fin);
65 | probe stream_receive(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stream_t *stream, uint64_t off, size_t len);
66 | probe stream_acked(struct st_quicly_conn_t *conn, int64_t at, int64_t stream_id, uint64_t off, size_t len);
67 | probe stream_lost(struct st_quicly_conn_t *conn, int64_t at, int64_t stream_id, uint64_t off, size_t len);
68 |
69 | probe max_data_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit);
70 | probe max_data_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit);
71 |
72 | probe max_streams_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit, int is_unidirectional);
73 | probe max_streams_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit, int is_unidirectional);
74 |
75 | probe max_stream_data_send(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stream_t *stream, uint64_t limit);
76 | probe max_stream_data_receive(struct st_quicly_conn_t *conn, int64_t at, int64_t stream_id, uint64_t limit);
77 |
78 | probe new_token_send(struct st_quicly_conn_t *conn, int64_t at, uint8_t *token, size_t len, uint64_t generation);
79 | probe new_token_acked(struct st_quicly_conn_t *conn, int64_t at, uint64_t generation);
80 | probe new_token_receive(struct st_quicly_conn_t *conn, int64_t at, uint8_t *token, size_t len);
81 |
82 | probe handshake_done_send(struct st_quicly_conn_t *conn, int64_t at);
83 | probe handshake_done_receive(struct st_quicly_conn_t *conn, int64_t at);
84 |
85 | probe streams_blocked_send(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit, int is_unidirectional);
86 | probe streams_blocked_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t limit, int is_unidirectional);
87 |
88 | probe data_blocked_receive(struct st_quicly_conn_t *conn, int64_t at, uint64_t off);
89 |
90 | probe stream_data_blocked_receive(struct st_quicly_conn_t *conn, int64_t at, int64_t stream_id, uint64_t limit);
91 |
92 | probe quictrace_sent(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn, size_t len, uint8_t packet_type);
93 | probe quictrace_recv(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn);
94 | probe quictrace_send_stream(struct st_quicly_conn_t *conn, int64_t at, struct st_quicly_stream_t *stream, uint64_t off,
95 | size_t len, int fin);
96 | probe quictrace_recv_stream(struct st_quicly_conn_t *conn, int64_t at, int64_t stream_id, uint64_t off, size_t len, int fin);
97 | probe quictrace_recv_ack(struct st_quicly_conn_t *conn, int64_t at, uint64_t ack_block_begin, uint64_t ack_block_end);
98 | probe quictrace_recv_ack_delay(struct st_quicly_conn_t *conn, int64_t at, int64_t ack_delay);
99 | probe quictrace_lost(struct st_quicly_conn_t *conn, int64_t at, uint64_t pn);
100 | probe quictrace_cc_ack(struct st_quicly_conn_t *conn, int64_t at, struct quicly_rtt_t *rtt, uint32_t cwnd, size_t inflight);
101 | probe quictrace_cc_lost(struct st_quicly_conn_t *conn, int64_t at, struct quicly_rtt_t *rtt, uint32_t cwnd, size_t inflight);
102 |
103 | probe debug_message(struct st_quicly_conn_t *conn, const char *function, int line, const char *message);
104 | };
105 |
--------------------------------------------------------------------------------