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