Skip to content

Commit

Permalink
quic - pretty print quic trace
Browse files Browse the repository at this point in the history
  • Loading branch information
nbridge-jump committed Jan 6, 2025
1 parent 4316031 commit 0414e81
Show file tree
Hide file tree
Showing 12 changed files with 921 additions and 42 deletions.
1 change: 1 addition & 0 deletions src/app/fdctl/fdctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ typedef union {

struct {
int event;
int dump; /* whether the user requested --dump */
} quic_trace;
} args_t;

Expand Down
8 changes: 7 additions & 1 deletion src/app/fddev/quic_trace/fd_quic_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ extern void const * fd_quic_trace_log_base;

extern ulong ** fd_quic_trace_target_fseq;

struct fd_quic_trace_ctx {
int dump; /* whether the user requested --dump */
};

typedef struct fd_quic_trace_ctx fd_quic_trace_ctx_t;

struct fd_quic_trace_frame_ctx {
ulong conn_id;
uint src_ip;
Expand All @@ -36,7 +42,7 @@ fd_quic_trace_frames( fd_quic_trace_frame_ctx_t * context,
ulong data_sz );

void
fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache );
fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache, int dump );

void
fd_quic_trace_log_tile( fd_frag_meta_t const * in_mcache );
Expand Down
4 changes: 3 additions & 1 deletion src/app/fddev/quic_trace/fd_quic_trace_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ quic_trace_cmd_args( int * pargc,
} else {
FD_LOG_ERR(( "Unsupported QUIC event type \"%s\"", event ));
}

args->quic_trace.dump = fd_env_strip_cmdline_contains( pargc, pargv, "--dump" );
}

void
Expand Down Expand Up @@ -130,7 +132,7 @@ quic_trace_cmd_fn( args_t * args,
FD_LOG_NOTICE(( "quic-trace starting ..." ));
switch( args->quic_trace.event ) {
case EVENT_STREAM:
fd_quic_trace_rx_tile( net_quic->mcache );
fd_quic_trace_rx_tile( net_quic->mcache, args->quic_trace.dump );
break;
case EVENT_ERROR:
fd_quic_trace_log_tile( log_rx->mcache );
Expand Down
151 changes: 132 additions & 19 deletions src/app/fddev/quic_trace/fd_quic_trace_rx_tile.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ static int
bounds_check_conn( fd_quic_t * quic,
fd_quic_conn_t * conn ) {
long conn_off = (long)((ulong)conn-(ulong)quic);
return conn_off >= (long)quic->layout.conn_map_off && conn_off < (long)quic->layout.hs_pool_off;
return conn_off >= (long)quic->layout.conns_off && conn_off < (long)quic->layout.conn_map_off;
}

static void
fd_quic_trace_initial( void * _ctx FD_FN_UNUSED,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
fd_quic_trace_initial( fd_quic_trace_ctx_t * trace_ctx,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
fd_quic_ctx_t * ctx = &fd_quic_trace_ctx;
fd_quic_t * quic = ctx->quic;
fd_quic_state_t * state = fd_quic_get_state( quic );
Expand Down Expand Up @@ -135,15 +135,107 @@ fd_quic_trace_initial( void * _ctx FD_FN_UNUSED,
.src_port = udp_sport,
.pkt_type = FD_QUIC_PKT_TYPE_INITIAL
};
fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );

if( trace_ctx->dump ) {
fd_quic_pretty_print_quic_pkt( &state->quic_pretty_print,
state->now,
data,
data_sz,
"ingress",
ip4_saddr,
udp_sport );
} else {
fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
}
}

static void
fd_quic_trace_1rtt( void * _ctx FD_FN_UNUSED,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
fd_quic_trace_handshake( fd_quic_trace_ctx_t * trace_ctx,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
fd_quic_ctx_t * ctx = &fd_quic_trace_ctx;
fd_quic_t * quic = ctx->quic;
fd_quic_state_t * state = fd_quic_get_state( quic );
fd_quic_conn_map_t * conn_map = translate_ptr( state->conn_map );

if( FD_UNLIKELY( data_sz < FD_QUIC_SHORTEST_PKT ) ) return;

fd_quic_handshake_t handshake[1] = {0};
ulong rc = fd_quic_decode_handshake( handshake, data, data_sz );
if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
FD_LOG_DEBUG(( "fd_quic_decode_handshake failed" ));
return;
}
ulong len = (ulong)( handshake->pkt_num_pnoff + handshake->len );
if( FD_UNLIKELY( len > data_sz ) ) {
FD_LOG_DEBUG(( "Bogus handshake packet length" ));
return;
}

/* keeping this logic similar to the equivalent in fd_quic_trace_initial */
/* for future merging */
fd_quic_crypto_keys_t const * keys = NULL;
if( handshake->dst_conn_id_len == FD_QUIC_CONN_ID_SZ ) {
ulong dst_conn_id = fd_ulong_load_8( handshake->dst_conn_id );
if( dst_conn_id==0 ) return;
fd_quic_conn_map_t * conn_entry = fd_quic_conn_map_query( conn_map, dst_conn_id, NULL );
if( conn_entry ) {
fd_quic_conn_t * conn = translate_ptr( conn_entry->conn );
if( FD_LIKELY( bounds_check_conn( quic, conn ) ) ) {
keys = translate_ptr( &conn->keys[0][0] );
}
}
}
if( !keys ) {
return;
}

ulong pktnum_off = handshake->pkt_num_pnoff;
int hdr_err = fd_quic_crypto_decrypt_hdr( data, data_sz, pktnum_off, keys );
if( hdr_err!=FD_QUIC_SUCCESS ) return;

ulong pktnum_sz = fd_quic_h0_pkt_num_len( data[0] )+1u;
ulong pktnum_comp = fd_quic_pktnum_decode( data+9UL, pktnum_sz );
ulong pktnum = pktnum_comp; /* TODO decompress */

int crypt_err = fd_quic_crypto_decrypt( data, data_sz, pktnum_off, pktnum, keys );
if( crypt_err!=FD_QUIC_SUCCESS ) return;

ulong hdr_sz = pktnum_off + pktnum_sz;
ulong wrap_sz = hdr_sz + FD_QUIC_CRYPTO_TAG_SZ;
if( FD_UNLIKELY( data_sz<wrap_sz ) ) return;

uchar conn_id_truncated[16] = {0};
fd_memcpy( conn_id_truncated, handshake->dst_conn_id, handshake->dst_conn_id_len );
fd_quic_trace_frame_ctx_t frame_ctx = {
.conn_id = fd_ulong_load_8( conn_id_truncated ),
.pkt_num = pktnum,
.src_ip = ip4_saddr,
.src_port = udp_sport,
.pkt_type = FD_QUIC_PKT_TYPE_INITIAL
};

if( trace_ctx->dump ) {
fd_quic_pretty_print_quic_pkt( &state->quic_pretty_print,
state->now,
data,
data_sz,
"ingress",
ip4_saddr,
udp_sport );
} else {
fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
}
}

static void
fd_quic_trace_1rtt( fd_quic_trace_ctx_t * trace_ctx,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
fd_quic_ctx_t * ctx = &fd_quic_trace_ctx;
fd_quic_t * quic = ctx->quic;
fd_quic_state_t * state = fd_quic_get_state( quic );
Expand Down Expand Up @@ -181,23 +273,42 @@ fd_quic_trace_1rtt( void * _ctx FD_FN_UNUSED,
.src_port = udp_sport,
.pkt_type = FD_QUIC_PKT_TYPE_ONE_RTT
};
fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );

if( trace_ctx->dump ) {
fd_quic_pretty_print_quic_pkt( &state->quic_pretty_print,
state->now,
data,
data_sz,
"ingress",
ip4_saddr,
udp_sport );
} else {
fd_quic_trace_frames( &frame_ctx, data+hdr_sz, data_sz-wrap_sz );
}

(void)ip4_saddr; (void)conn;
}

static void
fd_quic_trace_pkt( fd_quic_ctx_t * ctx,
fd_quic_trace_pkt( void * ctx,
uchar * data,
ulong data_sz,
uint ip4_saddr,
ushort udp_sport ) {
/* FIXME: for now, only handle 1-RTT */
int is_long = fd_quic_h0_hdr_form( data[0] );
if( !is_long ) {
if( is_long ) {
switch( fd_quic_h0_long_packet_type( data[0] ) ) {
case FD_QUIC_PKT_TYPE_INITIAL:
fd_quic_trace_initial( ctx, data, data_sz, ip4_saddr, udp_sport );
break;
case FD_QUIC_PKT_TYPE_HANDSHAKE:
fd_quic_trace_handshake( ctx, data, data_sz, ip4_saddr, udp_sport );
break;
}

/* FD_QUIC_PKT_TYPE_RETRY as the server, we shouldn't be receiving RETRY packets */
/* FD_QUIC_PKT_TYPE_ZERO_RTT we don't support 0-RTT packets */
} else {
fd_quic_trace_1rtt( ctx, data, data_sz, ip4_saddr, udp_sport );
}
Expand Down Expand Up @@ -240,20 +351,20 @@ after_frag( void * _ctx FD_FN_UNUSED,

uint ip4_saddr = fd_uint_load_4( ip4_hdr->saddr_c );
ushort udp_sport = fd_ushort_bswap( udp_hdr->net_sport );
fd_quic_trace_pkt( ctx, cur, (ulong)( end-cur ), ip4_saddr, udp_sport );
fd_quic_trace_pkt( _ctx, cur, (ulong)( end-cur ), ip4_saddr, udp_sport );
}


#define STEM_BURST (1UL)
#define STEM_CALLBACK_CONTEXT_TYPE void
#define STEM_CALLBACK_CONTEXT_TYPE fd_quic_trace_ctx_t
#define STEM_CALLBACK_CONTEXT_ALIGN 1
#define STEM_CALLBACK_BEFORE_FRAG before_frag
#define STEM_CALLBACK_DURING_FRAG during_frag
#define STEM_CALLBACK_AFTER_FRAG after_frag
#include "../../../disco/stem/fd_stem.c"

void
fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache ) {
fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache, int dump ) {
fd_frag_meta_t const * in_mcache_tbl[1] = { in_mcache };

uchar fseq_mem[ FD_FSEQ_FOOTPRINT ] __attribute__((aligned(FD_FSEQ_ALIGN)));
Expand All @@ -265,6 +376,8 @@ fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache ) {

uchar scratch[ sizeof(fd_stem_tile_in_t)+128 ] __attribute__((aligned(FD_STEM_SCRATCH_ALIGN)));

fd_quic_trace_ctx_t ctx[1] = {{ .dump = dump }};

stem_run1( /* in_cnt */ 1UL,
/* in_mcache */ in_mcache_tbl,
/* in_fseq */ fseq_tbl,
Expand All @@ -277,7 +390,7 @@ fd_quic_trace_rx_tile( fd_frag_meta_t const * in_mcache ) {
/* stem_lazy */ 0L,
/* rng */ rng,
/* scratch */ scratch,
/* ctx */ NULL );
/* ctx */ ctx );

fd_fseq_delete( fd_fseq_leave( fseq ) );
}
2 changes: 2 additions & 0 deletions src/waltz/quic/fd_quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "templ/fd_quic_frames_templ.h"
#include "templ/fd_quic_undefs.h"

#include "fd_quic_pretty_print.c"

#include "crypto/fd_quic_crypto_suites.h"
#include "templ/fd_quic_transport_params.h"
#include "templ/fd_quic_parse_util.h"
Expand Down
21 changes: 21 additions & 0 deletions src/waltz/quic/fd_quic_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,24 @@ void *
fd_quic_conn_get_context( fd_quic_conn_t * conn ) {
return conn->context;
}

char const *
fd_quic_conn_reason_name( uint reason ) {
/* define mapping from reason code to name as a c-string */
static char const * fd_quic_conn_reason_names[] = {
# define COMMA ,
# define _(NAME,CODE,DESC) \
[CODE] = #NAME
FD_QUIC_REASON_CODES(_,COMMA)
# undef _
# undef COMMA
};

# define ELEMENTS ( sizeof(fd_quic_conn_reason_names) / sizeof(fd_quic_conn_reason_names[0]) )

if( FD_UNLIKELY( reason >= ELEMENTS ) ) return "N/A";

char const * name = fd_quic_conn_reason_names[reason];

return name ? name : "N/A";
}
52 changes: 31 additions & 21 deletions src/waltz/quic/fd_quic_conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,40 @@
#define FD_QUIC_CONN_STATE_CLOSE_PENDING 6 /* connection is closing */
#define FD_QUIC_CONN_STATE_DEAD 7 /* connection about to be freed */

#define FD_QUIC_REASON_CODES(X,SEP) \
X(NO_ERROR , 0x00 , "No error" ) SEP \
X(INTERNAL_ERROR , 0x01 , "Implementation error" ) SEP \
X(CONNECTION_REFUSED , 0x02 , "Server refuses a connection" ) SEP \
X(FLOW_CONTROL_ERROR , 0x03 , "Flow control error" ) SEP \
X(STREAM_LIMIT_ERROR , 0x04 , "Too many streams opened" ) SEP \
X(STREAM_STATE_ERROR , 0x05 , "Frame received in invalid stream state" ) SEP \
X(FINAL_SIZE_ERROR , 0x06 , "Change to final size" ) SEP \
X(FRAME_ENCODING_ERROR , 0x07 , "Frame encoding error" ) SEP \
X(TRANSPORT_PARAMETER_ERROR , 0x08 , "Error in transport parameters" ) SEP \
X(CONNECTION_ID_LIMIT_ERROR , 0x09 , "Too many connection IDs received" ) SEP \
X(PROTOCOL_VIOLATION , 0x0a , "Generic protocol violation" ) SEP \
X(INVALID_TOKEN , 0x0b , "Invalid Token received" ) SEP \
X(APPLICATION_ERROR , 0x0c , "Application error" ) SEP \
X(CRYPTO_BUFFER_EXCEEDED , 0x0d , "CRYPTO data buffer overflowed" ) SEP \
X(KEY_UPDATE_ERROR , 0x0e , "Invalid packet protection update" ) SEP \
X(AEAD_LIMIT_REACHED , 0x0f , "Excessive use of packet protection keys" ) SEP \
X(NO_VIABLE_PATH , 0x10 , "No viable network path exists" ) SEP \
X(CRYPTO_BASE , 0x100 , "0x0100-0x01ff CRYPTO_ERROR TLS alert code" ) SEP \
X(HANDSHAKE_FAILURE , 0x128 , "Handshake failed" )

enum {
FD_QUIC_CONN_REASON_NO_ERROR = 0x00, /* No error */
FD_QUIC_CONN_REASON_INTERNAL_ERROR = 0x01, /* Implementation error */
FD_QUIC_CONN_REASON_CONNECTION_REFUSED = 0x02, /* Server refuses a connection */
FD_QUIC_CONN_REASON_FLOW_CONTROL_ERROR = 0x03, /* Flow control error */
FD_QUIC_CONN_REASON_STREAM_LIMIT_ERROR = 0x04, /* Too many streams opened */
FD_QUIC_CONN_REASON_STREAM_STATE_ERROR = 0x05, /* Frame received in invalid stream state */
FD_QUIC_CONN_REASON_FINAL_SIZE_ERROR = 0x06, /* Change to final size */
FD_QUIC_CONN_REASON_FRAME_ENCODING_ERROR = 0x07, /* Frame encoding error */
FD_QUIC_CONN_REASON_TRANSPORT_PARAMETER_ERROR = 0x08, /* Error in transport parameters */
FD_QUIC_CONN_REASON_CONNECTION_ID_LIMIT_ERROR = 0x09, /* Too many connection IDs received */
FD_QUIC_CONN_REASON_PROTOCOL_VIOLATION = 0x0a, /* Generic protocol violation */
FD_QUIC_CONN_REASON_INVALID_TOKEN = 0x0b, /* Invalid Token received */
FD_QUIC_CONN_REASON_APPLICATION_ERROR = 0x0c, /* Application error */
FD_QUIC_CONN_REASON_CRYPTO_BUFFER_EXCEEDED = 0x0d, /* CRYPTO data buffer overflowed */
FD_QUIC_CONN_REASON_KEY_UPDATE_ERROR = 0x0e, /* Invalid packet protection update */
FD_QUIC_CONN_REASON_AEAD_LIMIT_REACHED = 0x0f, /* Excessive use of packet protection keys */
FD_QUIC_CONN_REASON_NO_VIABLE_PATH = 0x10, /* No viable network path exists */
FD_QUIC_CONN_REASON_CRYPTO_BASE = 0x100, /* 0x0100-0x01ff CRYPTO_ERROR TLS alert code*/
/* QUIC permits the use of a generic code in place of a specific error code [...]
such as handshake_failure (0x0128 in QUIC). */
FD_QUIC_CONN_REASON_HANDSHAKE_FAILURE = 0x128 /* Handshake failed. */
# define COMMA ,
# define _(NAME,CODE,DESC) \
FD_QUIC_CONN_REASON_##NAME = CODE
FD_QUIC_REASON_CODES(_,COMMA)
# undef _
# undef COMMA
};

char const *
fd_quic_conn_reason_name( uint reason );


struct fd_quic_conn_stream_rx {
ulong rx_hi_stream_id; /* highest RX stream ID sent by peer + 4 */
ulong rx_sup_stream_id; /* highest allowed RX stream ID + 4 */
Expand Down
Loading

0 comments on commit 0414e81

Please sign in to comment.