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

Generated by: LCOV version 1.14