Line data Source code
1 : /* fd_quic_trace_rx_tile.c does passive decryption of incoming QUIC
2 : packets.
3 :
4 : It mocks the setup procedure and run loop of a real fd_quic_tile. */
5 :
6 : #include "fd_quic_trace.h"
7 :
8 : #include "../../../../waltz/quic/fd_quic_private.h"
9 : #include "../../../../waltz/quic/templ/fd_quic_parse_util.h"
10 : #include "../../../../waltz/quic/fd_quic_proto.c"
11 : #include "../../../../util/net/fd_eth.h"
12 : #include "../../../../util/net/fd_ip4.h"
13 : #include "../../../../util/net/fd_udp.h"
14 :
15 : static int
16 : before_frag( fd_quic_trace_ctx_t * ctx,
17 : ulong in_idx FD_FN_UNUSED,
18 : ulong seq FD_FN_UNUSED,
19 0 : ulong sig ) {
20 : /* Skip non-QUIC packets, based on the tile we target */
21 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
22 0 : int send = ctx->trace_send;
23 :
24 0 : switch( proto ) {
25 0 : case DST_PROTO_OUTGOING:
26 0 : return 0;
27 0 : case DST_PROTO_TPU_QUIC:
28 0 : return send;
29 0 : case DST_PROTO_SEND:
30 0 : return !send;
31 0 : default:
32 0 : return 1;
33 0 : }
34 :
35 0 : return 0;
36 0 : }
37 :
38 : static void
39 : during_frag( fd_quic_trace_ctx_t * ctx,
40 : ulong in_idx FD_PARAM_UNUSED,
41 : ulong seq FD_PARAM_UNUSED,
42 : ulong sig,
43 : ulong chunk,
44 : ulong sz,
45 0 : ulong ctl ) {
46 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
47 0 : if( (proto==DST_PROTO_TPU_QUIC) | (proto==DST_PROTO_SEND) ) {
48 0 : fd_memcpy( ctx->buffer, fd_net_rx_translate_frag( &ctx->net_in_bounds[0], chunk, ctl, sz ), sz );
49 0 : } else if( proto == DST_PROTO_OUTGOING ) {
50 0 : ulong p = ctx->net_out_base + (chunk<<FD_CHUNK_LG_SZ);
51 0 : fd_memcpy( ctx->buffer, (void*)p, sz );
52 0 : }
53 0 : }
54 :
55 : static int
56 : bounds_check_conn( fd_quic_t const * quic,
57 0 : fd_quic_conn_t const * conn ) {
58 0 : long conn_off = (long)((ulong)conn-(ulong)quic);
59 0 : return conn_off >= (long)quic->layout.conns_off && conn_off < (long)quic->layout.conn_map_off;
60 0 : }
61 :
62 : static ulong
63 : fd_quic_trace_initial( fd_quic_trace_ctx_t * ctx,
64 : uchar * data,
65 : ulong data_sz,
66 : uint ip4_saddr,
67 : ushort udp_sport,
68 : uint ip4_daddr,
69 : ushort udp_dport,
70 0 : uint key_idx ) {
71 0 : fd_quic_t * quic = ctx->quic;
72 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
73 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
74 :
75 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return FD_QUIC_PARSE_FAIL;
76 :
77 0 : fd_quic_initial_t initial[1] = {0};
78 0 : ulong rc = fd_quic_decode_initial( initial, data, data_sz );
79 0 : if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
80 0 : FD_LOG_DEBUG(( "fd_quic_decode_initial failed" ));
81 0 : return FD_QUIC_PARSE_FAIL;
82 0 : }
83 0 : ulong len = (ulong)( initial->pkt_num_pnoff + initial->len );
84 0 : if( FD_UNLIKELY( len > data_sz ) ) {
85 0 : FD_LOG_DEBUG(( "Bogus initial packet length" ));
86 0 : return FD_QUIC_PARSE_FAIL;
87 0 : }
88 0 : if( FD_UNLIKELY( initial->dst_conn_id_len > 20 ) ) {
89 0 : FD_LOG_DEBUG(( "Bogus destination connection id length: %u", (uint)initial->dst_conn_id_len ));
90 0 : }
91 :
92 0 : uint conn_idx = ~0u;
93 0 : fd_quic_crypto_keys_t _keys[1];
94 0 : fd_quic_crypto_keys_t const * keys = NULL;
95 0 : if( initial->dst_conn_id_len == FD_QUIC_CONN_ID_SZ ) {
96 0 : ulong conn_id = key_idx == 0 ? fd_ulong_load_8( initial->dst_conn_id )
97 0 : : fd_ulong_load_8( initial->src_conn_id );
98 0 : if( conn_id==0 ) return FD_QUIC_PARSE_FAIL;
99 :
100 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, conn_id, NULL );
101 0 : if( conn_entry && conn_entry->conn ) {
102 0 : fd_quic_conn_t * conn = translate_ptr( conn_entry->conn );
103 0 : if( FD_LIKELY( bounds_check_conn( quic, conn ) ) ) {
104 0 : conn_idx = conn->conn_idx;
105 0 : keys = &conn->keys[fd_quic_enc_level_initial_id][key_idx];
106 :
107 0 : # define EMPTY ((uchar[16]){0})
108 : /* assume this is a new connection, since this is an Initial packet */
109 0 : if( keys && memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) != 0 ) {
110 : /* load the appropriate cid into peer_conn_id */
111 0 : ulong peer_conn_id = key_idx == 0 ? fd_ulong_load_8( initial->src_conn_id )
112 0 : : fd_ulong_load_8( initial->dst_conn_id );
113 :
114 : /* insert into peer_cid map */
115 0 : peer_conn_id_map_t * entry = peer_conn_id_map_insert( fd_quic_trace_peer_map, peer_conn_id );
116 :
117 : /* NULL entry either implies already exists, or full */
118 0 : if( entry ) {
119 0 : entry->conn_idx = conn->conn_idx;
120 0 : }
121 0 : }
122 0 : } else {
123 0 : FD_LOG_WARNING(( "conn out of bounds in fd_quic_trace_initial for conn id %lu with key idx %u", conn_id, key_idx ));
124 0 : }
125 0 : } else {
126 0 : FD_LOG_DEBUG(( "Failed to find conn for conn id %lu with key idx %u", conn_id, key_idx ));
127 0 : }
128 0 : }
129 :
130 0 : if( !keys || memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) == 0 ) {
131 0 : int is_client = ctx->trace_send;
132 0 : int is_egress = (int)key_idx;
133 :
134 : /* (server,egress) and (client,ingress) don't have the client's orig DCID avail */
135 0 : if( is_client==is_egress ) {
136 0 : fd_quic_crypto_secrets_t secrets[1];
137 0 : fd_quic_gen_initial_secrets(
138 0 : secrets,
139 0 : initial->dst_conn_id, initial->dst_conn_id_len,
140 0 : !is_client );
141 :
142 : /* Derive decryption key */
143 0 : fd_quic_gen_keys( _keys, secrets->secret[fd_quic_enc_level_initial_id][key_idx] );
144 0 : keys = _keys;
145 0 : }
146 0 : }
147 :
148 0 : if( !keys ) return FD_QUIC_PARSE_FAIL;
149 :
150 0 : ulong pktnum_off = initial->pkt_num_pnoff;
151 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
152 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
153 :
154 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
155 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+pktnum_off, pktnum_sz );
156 0 : ulong pktnum = pktnum_comp; /* don't bother decompressing since initial pktnum is usually low */
157 :
158 0 : ulong body_sz = initial->len; /* length of packet number, frames, and auth tag */
159 0 : ulong tot_sz = pktnum_off + body_sz;
160 :
161 0 : if( tot_sz > data_sz ) return FD_QUIC_PARSE_FAIL;
162 :
163 0 : int crypt_err = fd_quic_crypto_decrypt( data, tot_sz, pktnum_off, pktnum, keys );
164 0 : if( crypt_err!=FD_QUIC_SUCCESS ) {
165 0 : return FD_QUIC_PARSE_FAIL;
166 0 : }
167 :
168 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
169 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
170 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return FD_QUIC_PARSE_FAIL;
171 :
172 0 : if( ctx->dump ) {
173 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
174 0 : .ip4_saddr = ip4_saddr,
175 0 : .udp_sport = udp_sport,
176 0 : .ip4_daddr = ip4_daddr,
177 0 : .udp_dport = udp_dport,
178 0 : .flow = key_idx,
179 0 : .conn_idx = conn_idx };
180 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
181 0 : state->now,
182 0 : data,
183 0 : tot_sz );
184 0 : fflush( stdout );
185 0 : } else {
186 0 : uchar conn_id_truncated[24] = {0};
187 0 : fd_memcpy( conn_id_truncated, initial->dst_conn_id, initial->dst_conn_id_len );
188 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
189 0 : .conn_id = fd_ulong_load_8( &initial->dst_conn_id_len ),
190 0 : .pkt_num = pktnum,
191 0 : .src_ip = ip4_saddr,
192 0 : .src_port = udp_sport,
193 0 : .pkt_type = FD_QUIC_PKT_TYPE_INITIAL
194 0 : };
195 :
196 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, tot_sz-wrap_sz );
197 0 : }
198 :
199 0 : return tot_sz;
200 0 : }
201 :
202 : static ulong
203 : fd_quic_trace_handshake( fd_quic_trace_ctx_t * ctx,
204 : uchar * data,
205 : ulong data_sz,
206 : uint ip4_saddr,
207 : ushort udp_sport,
208 : uint ip4_daddr,
209 : ushort udp_dport,
210 0 : uint key_idx ) {
211 0 : fd_quic_t * quic = ctx->quic;
212 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
213 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
214 :
215 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return FD_QUIC_PARSE_FAIL;
216 :
217 0 : fd_quic_handshake_t handshake[1] = {0};
218 0 : ulong rc = fd_quic_decode_handshake( handshake, data, data_sz );
219 0 : if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
220 0 : FD_LOG_DEBUG(( "fd_quic_decode_handshake failed" ));
221 0 : return FD_QUIC_PARSE_FAIL;
222 0 : }
223 0 : ulong len = (ulong)( handshake->pkt_num_pnoff + handshake->len );
224 0 : if( FD_UNLIKELY( len > data_sz ) ) {
225 0 : FD_LOG_DEBUG(( "Bogus handshake packet length" ));
226 0 : return FD_QUIC_PARSE_FAIL;
227 0 : }
228 :
229 : /* need conn_idx */
230 0 : uint conn_idx = ~0u;
231 :
232 : /* keeping this logic similar to the equivalent in fd_quic_trace_initial */
233 : /* for future merging */
234 0 : fd_quic_crypto_keys_t const * keys = NULL;
235 0 : if( handshake->dst_conn_id_len == FD_QUIC_CONN_ID_SZ ) {
236 0 : ulong conn_id = key_idx == 0 ? fd_ulong_load_8( handshake->dst_conn_id )
237 0 : : fd_ulong_load_8( handshake->src_conn_id );
238 0 : if( conn_id==0 ) return FD_QUIC_PARSE_FAIL;
239 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, conn_id, NULL );
240 0 : if( conn_entry && conn_entry->conn ) {
241 0 : fd_quic_conn_t * conn = translate_ptr( conn_entry->conn );
242 0 : if( FD_LIKELY( bounds_check_conn( quic, conn ) ) ) {
243 0 : keys = &conn->keys[fd_quic_enc_level_handshake_id][key_idx];
244 0 : conn_idx = conn->conn_idx;
245 0 : }
246 0 : }
247 0 : }
248 0 : if( !keys || memcmp( keys->pkt_key, EMPTY, sizeof( keys->pkt_key ) ) == 0 ) {
249 0 : return FD_QUIC_PARSE_FAIL;
250 0 : }
251 :
252 0 : ulong pktnum_off = handshake->pkt_num_pnoff;
253 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
254 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
255 :
256 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
257 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+pktnum_off, pktnum_sz );
258 0 : ulong pktnum = pktnum_comp; /* TODO decompress */
259 :
260 0 : ulong body_sz = handshake->len; /* length of packet number, frames, and auth tag */
261 0 : ulong tot_sz = pktnum_off + body_sz;
262 :
263 0 : if( tot_sz > data_sz ) return FD_QUIC_PARSE_FAIL;
264 :
265 0 : int crypt_err = fd_quic_crypto_decrypt( data, data_sz, pktnum_off, pktnum, keys );
266 0 : if( crypt_err!=FD_QUIC_SUCCESS ) return FD_QUIC_PARSE_FAIL;
267 :
268 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
269 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
270 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return FD_QUIC_PARSE_FAIL;
271 :
272 0 : if( ctx->dump ) {
273 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
274 0 : .ip4_saddr = ip4_saddr,
275 0 : .udp_sport = udp_sport,
276 0 : .ip4_daddr = ip4_daddr,
277 0 : .udp_dport = udp_dport,
278 0 : .flow = key_idx,
279 0 : .conn_idx = conn_idx };
280 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
281 0 : state->now,
282 0 : data,
283 0 : data_sz );
284 0 : fflush( stdout );
285 0 : } else {
286 0 : uchar conn_id_truncated[8] = {0};
287 0 : fd_memcpy( conn_id_truncated, handshake->dst_conn_id, 8 );
288 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
289 0 : .conn_id = fd_ulong_load_8( conn_id_truncated ),
290 0 : .pkt_num = pktnum,
291 0 : .src_ip = ip4_saddr,
292 0 : .src_port = udp_sport,
293 0 : .pkt_type = FD_QUIC_PKT_TYPE_HANDSHAKE
294 0 : };
295 :
296 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
297 0 : }
298 :
299 0 : return FD_QUIC_PARSE_FAIL;
300 0 : }
301 :
302 : static void
303 : fd_quic_trace_1rtt( fd_quic_trace_ctx_t * ctx,
304 : uchar * data,
305 : ulong data_sz,
306 : uint ip4_saddr,
307 : ushort udp_sport,
308 : uint ip4_daddr,
309 : ushort udp_dport,
310 0 : uint key_idx ) {
311 0 : fd_quic_t * quic = ctx->quic;
312 0 : fd_quic_state_t * state = fd_quic_get_state( quic );
313 0 : fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );
314 :
315 0 : if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return;
316 :
317 0 : fd_quic_conn_t const * conn = NULL;
318 0 : ulong dst_conn_id = 0UL;
319 :
320 : /* key_idx 0 is ingress, key_idx 1 is egress */
321 0 : if( key_idx == 0 ) {
322 : /* Look up conn */
323 0 : dst_conn_id = fd_ulong_load_8( data+1 );
324 0 : fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, dst_conn_id, NULL );
325 :
326 0 : if( conn_entry && dst_conn_id && conn_entry->conn ) {
327 0 : conn = translate_ptr( conn_entry->conn );
328 0 : if( FD_UNLIKELY( !bounds_check_conn( quic, conn ) ) ) return;
329 0 : }
330 0 : } else {
331 :
332 : /* we use the first 8 bytes of the peer conn_id for the key
333 : since we don't actually know the length */
334 :
335 0 : ulong peer_conn_id = fd_ulong_load_8( data+1 );
336 :
337 : /* look up connection id in peer conn_id map */
338 0 : uint conn_idx = 0;
339 0 : peer_conn_id_map_t * peer_entry = peer_conn_id_map_query( fd_quic_trace_peer_map, peer_conn_id, NULL );
340 :
341 0 : if( FD_LIKELY( peer_entry ) ) {
342 0 : conn_idx = peer_entry->conn_idx;
343 0 : } else {
344 : /* report packet with unavailable connection */
345 0 : char time_str[FD_LOG_WALLCLOCK_CSTR_BUF_SZ];
346 0 : printf( "{ "
347 0 : "\"type\": \"packet\", "
348 0 : "\"flow\": \"%s\", "
349 0 : "\"trace_time\": \"%s\", "
350 0 : "\"src_ip_addr\": \"" FD_IP4_ADDR_FMT "\", "
351 0 : "\"src_udp_port\": \"%u\", "
352 0 : "\"dst_ip_addr\": \"" FD_IP4_ADDR_FMT "\", "
353 0 : "\"dst_udp_port\": \"%u\", "
354 0 : "\"hdr_type\": \"1-rtt\", "
355 0 : "\"err\": \"no-trace-connection\", "
356 0 : "\"dst_conn_id\": \"%lx\" "
357 0 : "}, ] }\n",
358 0 : key_idx == 0 ? "ingress" : "egress",
359 0 : fd_log_wallclock_cstr( fd_log_wallclock(), time_str ),
360 0 : FD_IP4_ADDR_FMT_ARGS( ip4_saddr ),
361 0 : (uint)udp_sport,
362 0 : FD_IP4_ADDR_FMT_ARGS( ip4_daddr ),
363 0 : (uint)udp_dport,
364 0 : peer_conn_id
365 0 : );
366 0 : return;
367 0 : }
368 :
369 0 : conn = fd_quic_trace_conn_at_idx( quic, conn_idx );
370 0 : }
371 :
372 0 : if( !conn ) return;
373 :
374 0 : fd_quic_crypto_keys_t const * keys = &conn->keys[ fd_quic_enc_level_appdata_id ][ key_idx ];
375 :
376 0 : ulong pktnum_off = 9UL;
377 0 : int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
378 0 : if( hdr_err!=FD_QUIC_SUCCESS ) return;
379 :
380 0 : ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
381 0 : ulong pktnum_comp = fd_quic_pktnum_decode( data+9UL, pktnum_sz );
382 0 : ulong pktnum = fd_quic_reconstruct_pkt_num( pktnum_comp, pktnum_sz, conn->exp_pkt_number[2] );
383 0 : int crypt_err = fd_quic_crypto_decrypt( data, data_sz, pktnum_off, pktnum, keys );
384 0 : if( crypt_err!=FD_QUIC_SUCCESS ) return;
385 :
386 0 : ulong hdr_sz = pktnum_off + pktnum_sz;
387 0 : ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
388 0 : if( FD_UNLIKELY( data_sz<wrap_sz ) ) return;
389 :
390 0 : if( ctx->dump ) {
391 0 : fd_quic_pretty_print_t quic_pkt_ctx = {
392 0 : .ip4_saddr = ip4_saddr,
393 0 : .udp_sport = udp_sport,
394 0 : .ip4_daddr = ip4_daddr,
395 0 : .udp_dport = udp_dport,
396 0 : .flow = key_idx,
397 0 : .conn_idx = conn->conn_idx };
398 0 : fd_quic_pretty_print_quic_pkt( &quic_pkt_ctx,
399 0 : state->now,
400 0 : data,
401 0 : data_sz );
402 0 : fflush( stdout );
403 0 : } else if( key_idx == 0 ) {
404 0 : fd_quic_trace_frame_ctx_t frame_ctx = {
405 0 : .conn_id = dst_conn_id,
406 0 : .pkt_num = pktnum,
407 0 : .src_ip = ip4_saddr,
408 0 : .src_port = udp_sport,
409 0 : .pkt_type = FD_QUIC_PKT_TYPE_ONE_RTT
410 0 : };
411 :
412 0 : fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
413 0 : }
414 0 : }
415 :
416 : static int
417 0 : is_valid_quic_long_hdr( uchar* data ) {
418 0 : if( data[0]>>6 != 0x3 ) return 0;
419 0 : uint version = fd_uint_bswap( FD_LOAD( uint, data + 1 ) );
420 0 : if( version != 1 ) return 0;
421 :
422 0 : return 1;
423 0 : }
424 :
425 : static void
426 : fd_quic_trace_pkt( fd_quic_trace_ctx_t * ctx,
427 : uchar * data,
428 : ulong data_sz,
429 : uint ip4_saddr,
430 : ushort udp_sport,
431 : uint ip4_daddr,
432 : ushort udp_dport,
433 0 : uint key_idx ) {
434 :
435 0 : uchar * cur_ptr = data;
436 0 : uchar * end_ptr = data + data_sz;
437 0 : while( cur_ptr < end_ptr ) {
438 0 : int is_long = fd_quic_h0_hdr_form( cur_ptr[0] );
439 0 : ulong sz = 0;
440 0 : if( is_long ) {
441 0 : if( !is_valid_quic_long_hdr( cur_ptr ) ) {
442 0 : FD_LOG_NOTICE(( "Invalid quic long hdr with key_idx %u (maybe udp)", key_idx ));
443 0 : return;
444 0 : };
445 0 : switch( fd_quic_h0_long_packet_type( cur_ptr[0] ) ) {
446 0 : case FD_QUIC_PKT_TYPE_INITIAL:
447 0 : sz = fd_quic_trace_initial( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
448 0 : break;
449 0 : case FD_QUIC_PKT_TYPE_HANDSHAKE:
450 0 : sz = fd_quic_trace_handshake( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
451 0 : break;
452 0 : case FD_QUIC_PKT_TYPE_RETRY:
453 : /* TODO fd_quic_trace_retry */
454 0 : FD_LOG_NOTICE(( "%s retry packet of data_sz %lu, src: " FD_IP4_ADDR_FMT ":%u, dst: " FD_IP4_ADDR_FMT ":%u", key_idx==0 ? "Received" : "Sent", (ulong)( end_ptr - cur_ptr ), FD_IP4_ADDR_FMT_ARGS( ip4_saddr ), udp_sport, FD_IP4_ADDR_FMT_ARGS( ip4_daddr ), udp_dport ));
455 0 : return;
456 0 : default:
457 0 : FD_LOG_NOTICE(( "Unknown long packet type with key_idx %u, data_sz %lu, src: " FD_IP4_ADDR_FMT ":%u, dst: " FD_IP4_ADDR_FMT ":%u", key_idx, (ulong)( end_ptr - cur_ptr ), FD_IP4_ADDR_FMT_ARGS( ip4_saddr ), udp_sport, FD_IP4_ADDR_FMT_ARGS( ip4_daddr ), udp_dport ));
458 0 : return;
459 0 : }
460 :
461 : /* TODO TX should support FD_QUIC_PKT_TYPE_RETRY */
462 : /* FD_QUIC_PKT_TYPE_RETRY as the server, we shouldn't be receiving RETRY packets */
463 : /* FD_QUIC_PKT_TYPE_ZERO_RTT we don't support 0-RTT packets */
464 0 : } else {
465 0 : fd_quic_trace_1rtt( ctx, cur_ptr, (ulong)( end_ptr - cur_ptr ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
466 : /* one-rtt packets are last in the datagram */
467 0 : break;
468 0 : }
469 :
470 0 : if( sz == 0 || sz == FD_QUIC_PARSE_FAIL ) break;
471 :
472 0 : cur_ptr += sz;
473 0 : }
474 0 : }
475 :
476 : static void
477 : after_frag( fd_quic_trace_ctx_t * ctx,
478 : ulong in_idx FD_PARAM_UNUSED,
479 : ulong seq FD_PARAM_UNUSED,
480 : ulong sig,
481 : ulong sz,
482 : ulong tsorig FD_PARAM_UNUSED,
483 : ulong tspub FD_PARAM_UNUSED,
484 0 : fd_stem_context_t * stem FD_PARAM_UNUSED ) {
485 0 : ulong proto = fd_disco_netmux_sig_proto( sig );
486 0 : uint key_idx = proto==DST_PROTO_OUTGOING ? 1 : 0;
487 :
488 0 : if( sz < FD_QUIC_SHORTEST_PKT ) return;
489 0 : if( sz > sizeof(ctx->buffer) ) return;
490 :
491 0 : uchar * cur = ctx->buffer;
492 0 : uchar * end = cur+sz;
493 :
494 0 : fd_eth_hdr_t const * eth_hdr = fd_type_pun_const( cur );
495 0 : cur += sizeof(fd_eth_hdr_t);
496 0 : if( FD_UNLIKELY( cur>end ) ) return;
497 0 : if( FD_UNLIKELY( fd_ushort_bswap( eth_hdr->net_type )!=FD_ETH_HDR_TYPE_IP ) ) return;
498 :
499 0 : fd_ip4_hdr_t const * ip4_hdr = fd_type_pun_const( cur );
500 0 : if( FD_UNLIKELY( cur+sizeof(fd_ip4_hdr_t) > end ) ) return;
501 0 : cur += FD_IP4_GET_LEN( *ip4_hdr );
502 0 : if( FD_UNLIKELY( cur>end ) ) return;
503 0 : if( FD_UNLIKELY( ip4_hdr->protocol!=FD_IP4_HDR_PROTOCOL_UDP ) ) return;
504 :
505 0 : fd_udp_hdr_t const * udp_hdr = fd_type_pun_const( cur );
506 0 : if( FD_UNLIKELY( cur+sizeof(fd_udp_hdr_t) > end ) ) return;
507 0 : cur += sizeof(fd_udp_hdr_t);
508 0 : if( FD_UNLIKELY( cur>end ) ) return;
509 :
510 0 : uint ip4_saddr = fd_uint_load_4( ip4_hdr->saddr_c );
511 0 : ushort udp_sport = fd_ushort_bswap( udp_hdr->net_sport );
512 0 : uint ip4_daddr = fd_uint_load_4( ip4_hdr->daddr_c );
513 0 : ushort udp_dport = fd_ushort_bswap( udp_hdr->net_dport );
514 0 : fd_quic_trace_pkt( ctx, cur, (ulong)( end-cur ), ip4_saddr, udp_sport, ip4_daddr, udp_dport, key_idx );
515 0 : }
516 :
517 :
518 : #define STEM_BURST (1UL)
519 :
520 : #define STEM_CALLBACK_CONTEXT_TYPE fd_quic_trace_ctx_t
521 : #define STEM_CALLBACK_CONTEXT_ALIGN alignof(fd_quic_trace_ctx_t)
522 :
523 0 : #define STEM_CALLBACK_BEFORE_FRAG before_frag
524 0 : #define STEM_CALLBACK_DURING_FRAG during_frag
525 0 : #define STEM_CALLBACK_AFTER_FRAG after_frag
526 :
527 : #include "../../../../disco/stem/fd_stem.c"
528 :
529 : void
530 : fd_quic_trace_rx_tile( fd_quic_trace_ctx_t * trace_ctx,
531 : fd_frag_meta_t const * rx_mcache,
532 0 : fd_frag_meta_t const * tx_mcache ) {
533 :
534 0 : uchar fseq_mem[ FD_FSEQ_FOOTPRINT*2 ] __attribute__((aligned(FD_FSEQ_ALIGN)));
535 0 : ulong * fseq_tbl[2] = {0};
536 0 : for( uint j = 0; j < 2; ++j ){
537 0 : ulong * fseq = fd_fseq_join( fd_fseq_new( fseq_mem + j * FD_FSEQ_FOOTPRINT, 0UL ) );
538 0 : fseq_tbl[j] = fseq;
539 0 : }
540 :
541 0 : fd_rng_t rng[1];
542 0 : FD_TEST( fd_rng_join( fd_rng_new( rng, (uint)fd_tickcount(), 0UL ) ) );
543 :
544 0 : uchar scratch[ sizeof(fd_stem_tile_in_t)+128 ] __attribute__((aligned(FD_STEM_SCRATCH_ALIGN)));
545 :
546 0 : fd_frag_meta_t const * in_mcache_tbl[2] = { rx_mcache, tx_mcache };
547 :
548 0 : stem_run1( /* in_cnt */ 2UL,
549 0 : /* in_mcache */ in_mcache_tbl,
550 0 : /* in_fseq */ fseq_tbl,
551 0 : /* out_cnt */ 0UL,
552 0 : /* out_mcache */ NULL,
553 0 : /* cons_cnt */ 0UL,
554 0 : /* cons_out */ NULL,
555 0 : /* cons_fseq */ NULL,
556 0 : /* stem_burst */ 1UL,
557 0 : /* stem_lazy */ 0L,
558 0 : /* rng */ rng,
559 0 : /* scratch */ scratch,
560 0 : /* ctx */ trace_ctx );
561 :
562 0 : for( int j = 0; j < 2; ++j ){
563 0 : fd_fseq_delete( fd_fseq_leave( fseq_tbl[j] ) );
564 0 : }
565 0 : }
|