LCOV - code coverage report
Current view: top level - app/shared_dev/commands/quic_trace - fd_quic_trace_rx_tile.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 377 0.0 %
Date: 2025-07-01 05:00:49 Functions: 0 9 0.0 %

          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 : }

Generated by: LCOV version 1.14