Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

quic - pretty print quic trace #3836

Merged
merged 1 commit into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
ripatel-fd marked this conversation as resolved.
Show resolved Hide resolved

#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
Loading