├── .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 | --------------------------------------------------------------------------------