Skip to content

Commit 0d335ff

Browse files
quic: timeout state fixes
1 parent d8468f9 commit 0d335ff

File tree

3 files changed

+69
-19
lines changed

3 files changed

+69
-19
lines changed

src/waltz/quic/fd_quic.c

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,30 @@ fd_quic_log_full_hdr( fd_quic_conn_t const * conn,
834834
return hdr;
835835
}
836836

837+
static inline void
838+
fd_quic_set_conn_state( fd_quic_conn_t * conn,
839+
uint new_state ) {
840+
841+
uint old_state = conn->state;
842+
843+
FD_COMPILER_MFENCE();
844+
845+
int was_timed_out = !!(old_state == FD_QUIC_CONN_STATE_TIMED_OUT);
846+
int freeing = was_timed_out & !!(new_state == FD_QUIC_CONN_STATE_INVALID);
847+
int reviving = was_timed_out & !freeing & !(new_state == FD_QUIC_CONN_STATE_TIMED_OUT);
848+
849+
fd_quic_metrics_t * metrics = &conn->quic->metrics;
850+
metrics->conn_timeout_freed_cnt += (ulong)freeing;
851+
metrics->conn_timeout_revived_cnt += (ulong)reviving;
852+
853+
metrics->conn_state_cnt[ old_state ]--;
854+
metrics->conn_state_cnt[ new_state ]++;
855+
856+
conn->state = new_state;
857+
858+
FD_COMPILER_MFENCE();
859+
}
860+
837861
/* fd_quic_conn_error sets the connection state to aborted. This does
838862
not destroy the connection object. Rather, it will eventually cause
839863
the connection to be freed during a later fd_quic_service call.
@@ -2277,6 +2301,11 @@ fd_quic_handle_v1_one_rtt( fd_quic_t * quic,
22772301
/* update expected packet number */
22782302
conn->exp_pkt_number[2] = fd_ulong_max( conn->exp_pkt_number[2], pkt_number+1UL );
22792303

2304+
/* Revive conn if it was timed out */
2305+
if( FD_UNLIKELY( conn->state == FD_QUIC_CONN_STATE_TIMED_OUT ) ) {
2306+
fd_quic_set_conn_state( conn, FD_QUIC_CONN_STATE_ACTIVE );
2307+
}
2308+
22802309
return tot_sz;
22812310
}
22822311

@@ -2381,13 +2410,6 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
23812410
return FD_QUIC_PARSE_FAIL;
23822411
}
23832412

2384-
/* If connection is timed out, revive it if packet successfully handled. */
2385-
if( FD_UNLIKELY( conn && conn->state == FD_QUIC_CONN_STATE_TIMED_OUT ) ) {
2386-
quic->metrics.conn_timeout_revived_cnt++;
2387-
fd_quic_set_conn_state( conn, FD_QUIC_CONN_STATE_ACTIVE );
2388-
fd_quic_svc_schedule( state, conn, FD_QUIC_SVC_WAIT );
2389-
}
2390-
23912413
cur_ptr += rc;
23922414

23932415
/* if we get here we parsed all the frames, so ack the packet */
@@ -2868,6 +2890,7 @@ fd_quic_tls_cb_handshake_complete( fd_quic_tls_hs_t * hs,
28682890
return;
28692891

28702892
case FD_QUIC_CONN_STATE_HANDSHAKE:
2893+
case FD_QUIC_CONN_STATE_TIMED_OUT:
28712894
if( FD_UNLIKELY( !conn->transport_params_set ) ) { /* unreachable */
28722895
FD_LOG_WARNING(( "Handshake marked as completed but transport params are not set. This is a bug!" ));
28732896
fd_quic_conn_error( conn, FD_QUIC_CONN_REASON_INTERNAL_ERROR, __LINE__ );
@@ -4151,7 +4174,6 @@ fd_quic_free_timed_out( fd_quic_t * quic ) {
41514174
fd_quic_conn_t * conn = fd_quic_conn_at_idx( state, queue->head );
41524175
fd_quic_svc_pop_head( state, queue, conn );
41534176

4154-
quic->metrics.conn_timeout_freed_cnt++;
41554177
fd_quic_conn_free( quic, conn );
41564178
}
41574179

src/waltz/quic/fd_quic_conn.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -234,17 +234,6 @@ struct fd_quic_conn {
234234
ulong used_pkt_meta;
235235
};
236236

237-
inline static void
238-
fd_quic_set_conn_state( fd_quic_conn_t * conn,
239-
uint state ) {
240-
FD_COMPILER_MFENCE();
241-
uint old_state = conn->state;
242-
conn->quic->metrics.conn_state_cnt[ old_state ]--;
243-
conn->quic->metrics.conn_state_cnt[ state ]++;
244-
conn->state = state;
245-
FD_COMPILER_MFENCE();
246-
}
247-
248237
FD_PROTOTYPES_BEGIN
249238

250239
FD_FN_CONST static inline ulong

src/waltz/quic/tests/test_quic_keep_alive.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,44 @@ test_quic_revive( fd_quic_t * client_quic, fd_quic_t * server_quic ) {
151151
fd_quic_stream_send( stream, "hello", 5, 1 );
152152
fd_quic_service( client_quic ); /* Send it, aio will receive on server */
153153
FD_TEST( server_conn->state == FD_QUIC_CONN_STATE_ACTIVE );
154+
FD_TEST( server_conn->svc_type == FD_QUIC_SVC_INSTANT || server_conn->svc_type == FD_QUIC_SVC_ACK_TX );
155+
FD_TEST( server_quic->metrics.conn_timeout_revived_cnt == 1 );
156+
}
157+
158+
static void
159+
test_hs_with_timeout( fd_quic_t * client_quic, fd_quic_t * server_quic ) {
160+
161+
fd_memset( &server_quic->metrics, 0, sizeof(fd_quic_metrics_t) );
162+
fd_memset( &client_quic->metrics, 0, sizeof(fd_quic_metrics_t) );
163+
164+
FD_TEST( fd_quic_init( server_quic ) );
165+
FD_TEST( fd_quic_init( client_quic ) );
166+
fd_quic_svc_validate( server_quic );
167+
fd_quic_svc_validate( client_quic );
168+
169+
fd_quic_conn_t * client_conn = fd_quic_connect( client_quic, 0U, 0, 0U, 0 );
170+
FD_TEST( client_conn );
171+
172+
fd_quic_service( client_quic ); /* client initial */
173+
fd_quic_service( server_quic ); /* server initial, hs */
174+
175+
/* trigger a timeout */
176+
now += server_quic->config.idle_timeout;
177+
fd_quic_service( server_quic );
178+
179+
FD_TEST( server_conn->state == FD_QUIC_CONN_STATE_TIMED_OUT );
180+
FD_TEST( server_conn->svc_time == LONG_MAX );
181+
FD_TEST( fd_quic_get_state( server_quic )->svc_queue[ FD_QUIC_SVC_TIMEOUT ].head == server_conn->conn_idx );
182+
FD_TEST( server_conn->svc_next == UINT_MAX );
183+
FD_TEST( server_conn->svc_prev == UINT_MAX );
184+
FD_TEST( server_quic->metrics.conn_timeout_cnt == 1 );
185+
186+
client_conn->last_activity = now; /* to not trigger self timeout */
187+
fd_quic_service( client_quic ); /* client send, trigger revival on server */
188+
189+
FD_TEST( server_conn->state == FD_QUIC_CONN_STATE_HANDSHAKE_COMPLETE );
190+
FD_TEST( server_conn->svc_type == FD_QUIC_SVC_INSTANT );
191+
FD_TEST( server_quic->metrics.conn_timeout_revived_cnt == 1 );
154192
}
155193

156194
static void
@@ -210,6 +248,7 @@ test_quic_timeout_store( fd_quic_t * client_quic, fd_quic_t * server_quic ) {
210248
client_quic->config.keep_timed_out = 1;
211249
server_quic->config.keep_timed_out = 1;
212250
test_quic_revive( client_quic, server_quic );
251+
test_hs_with_timeout( client_quic, server_quic );
213252
test_quic_free_timed_out( client_quic, server_quic );
214253
client_quic->config.keep_timed_out = 0;
215254
server_quic->config.keep_timed_out = 0;

0 commit comments

Comments
 (0)