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 387 0.0 %
Date: 2025-09-16 04:29:32 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,
      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 : }

Generated by: LCOV version 1.14