Skip to content

Commit 408cf4f

Browse files
quic: fix scheduling misses, svc_schedule validates conn
reset next_timeout in svc_schedule increase retx timeout to 1250M ticks rm unnecessary unacked_sz reset WARN if svc_timer_cnt != active_conn_cnt test_quic_conformance: update for service heap
1 parent 20f74a7 commit 408cf4f

File tree

6 files changed

+61
-15
lines changed

6 files changed

+61
-15
lines changed

src/waltz/quic/fd_quic.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,7 +2020,6 @@ fd_quic_lazy_ack_pkt( fd_quic_t * quic,
20202020
( ( pkt->enc_level == fd_quic_enc_level_initial_id ) |
20212021
( pkt->enc_level == fd_quic_enc_level_handshake_id ) );
20222022
if( ack_sz_threshold_hit | force_instant_ack ) {
2023-
conn->unacked_sz = 0UL;
20242023
fd_quic_svc_prep_schedule( conn, state->now );
20252024
} else {
20262025
fd_quic_svc_prep_schedule( conn, state->now + quic->config.ack_delay );
@@ -2252,6 +2251,8 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
22522251
break;
22532252
}
22542253

2254+
fd_quic_svc_schedule( state->svc_timers, conn );
2255+
22552256
if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
22562257
FD_DEBUG( FD_LOG_DEBUG(( "Rejected packet (type=%d)", long_packet_type )); )
22572258
return FD_QUIC_PARSE_FAIL;
@@ -2268,6 +2269,9 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
22682269
ulong dst_conn_id = fd_ulong_load_8( cur_ptr+1 );
22692270
conn = fd_quic_conn_query( state->conn_map, dst_conn_id );
22702271
rc = fd_quic_handle_v1_one_rtt( quic, conn, pkt, cur_ptr, cur_sz );
2272+
2273+
fd_quic_svc_schedule( state->svc_timers, conn );
2274+
22712275
if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
22722276
return FD_QUIC_PARSE_FAIL;
22732277
}
@@ -2283,6 +2287,7 @@ fd_quic_process_quic_packet_v1( fd_quic_t * quic,
22832287
int ack_type = fd_quic_lazy_ack_pkt( quic, conn, pkt );
22842288
quic->metrics.ack_tx[ ack_type ]++;
22852289

2290+
/* fd_quic_lazy_ack_pkt may have prepped schedule */
22862291
fd_quic_svc_schedule( state->svc_timers, conn );
22872292

22882293
if( pkt->rtt_ack_time ) {
@@ -2462,6 +2467,11 @@ fd_quic_process_packet( fd_quic_t * quic,
24622467
}
24632468

24642469
rc = fd_quic_process_quic_packet_v1( quic, &pkt, cur_ptr, cur_sz );
2470+
if( FD_UNLIKELY( fd_quic_svc_cnt_events( state->svc_timers ) != quic->metrics.conn_active_cnt ) ) {
2471+
FD_LOG_WARNING(( "only %lu out of %lu connections are in timer",
2472+
fd_quic_svc_cnt_events( state->svc_timers ),
2473+
quic->metrics.conn_active_cnt ));
2474+
}
24652475

24662476
/* 0UL means no progress, so fail */
24672477
if( FD_UNLIKELY( ( rc == FD_QUIC_PARSE_FAIL ) |
@@ -2491,6 +2501,11 @@ fd_quic_process_packet( fd_quic_t * quic,
24912501
/* short header packet
24922502
only one_rtt packets currently have short headers */
24932503
fd_quic_process_quic_packet_v1( quic, &pkt, cur_ptr, cur_sz );
2504+
if( FD_UNLIKELY( fd_quic_svc_cnt_events( state->svc_timers ) != quic->metrics.conn_active_cnt ) ) {
2505+
FD_LOG_WARNING(( "only %lu out of %lu connections are in timer",
2506+
fd_quic_svc_cnt_events( state->svc_timers ),
2507+
quic->metrics.conn_active_cnt ));
2508+
}
24942509
}
24952510

24962511
/* main receive-side entry point */
@@ -2924,6 +2939,11 @@ fd_quic_service( fd_quic_t * quic ) {
29242939
long now_ticks = fd_tickcount();
29252940

29262941
fd_quic_svc_timers_t * timers = state->svc_timers;
2942+
if( FD_UNLIKELY( fd_quic_svc_cnt_events( timers ) != quic->metrics.conn_active_cnt ) ) {
2943+
FD_LOG_WARNING(( "only %lu out of %lu connections are in timer",
2944+
fd_quic_svc_cnt_events( timers ),
2945+
quic->metrics.conn_active_cnt ));
2946+
}
29272947
fd_quic_svc_event_t next = fd_quic_svc_timers_next( timers, now, 1 /* pop */);
29282948
if( FD_UNLIKELY( next.conn == NULL ) ) {
29292949
return 0;
@@ -3573,7 +3593,8 @@ fd_quic_conn_tx( fd_quic_t * quic,
35733593
ulong now = fd_quic_get_state( quic )->now;
35743594

35753595
/* initialize expiry and tx_time */
3576-
fd_quic_pkt_meta_t pkt_meta_tmpl[1] = {{.expiry = now+500000000UL, .tx_time = now}};
3596+
ulong const retx_timeout = 1250UL*1000000UL; /* 1250M ticks ~ 500 ms?*/
3597+
fd_quic_pkt_meta_t pkt_meta_tmpl[1] = {{.expiry = now+retx_timeout, .tx_time = now}};
35773598
// pkt_meta_tmpl->expiry = fd_quic_calc_expiry( conn, now );
35783599
//ulong margin = (ulong)(conn->rtt->smoothed_rtt) + (ulong)(3 * conn->rtt->var_rtt);
35793600
//if( margin < pkt_meta->expiry ) {
@@ -3852,7 +3873,6 @@ fd_quic_conn_tx( fd_quic_t * quic,
38523873
void
38533874
fd_quic_conn_service( fd_quic_t * quic, fd_quic_conn_t * conn, ulong now ) {
38543875
(void)now;
3855-
conn->svc_meta.next_timeout = ULONG_MAX;
38563876

38573877
/* Send new rtt measurement probe? */
38583878
if( FD_UNLIKELY(now > conn->last_ack + (ulong)conn->rtt_period_ticks) ) {
@@ -3951,6 +3971,7 @@ fd_quic_conn_service( fd_quic_t * quic, fd_quic_conn_t * conn, ulong now ) {
39513971
case FD_QUIC_CONN_STATE_INVALID:
39523972
/* fall thru */
39533973
default:
3974+
FD_LOG_ERR(( "invalid conn state %u", conn->state ));
39543975
return;
39553976
}
39563977

@@ -3976,12 +3997,6 @@ fd_quic_conn_free( fd_quic_t * quic,
39763997

39773998
fd_quic_state_t * state = fd_quic_get_state( quic );
39783999

3979-
/* no need to remove this connection from the events queue
3980-
free is called from two places:
3981-
fini - service will never be called again. All events are destroyed
3982-
service - removes event before calling free. Event only allowed to be
3983-
enqueued once */
3984-
39854000
/* remove all stream ids from map, and free stream */
39864001

39874002
/* remove used streams */
@@ -4038,12 +4053,12 @@ fd_quic_conn_free( fd_quic_t * quic,
40384053
}
40394054
conn->tls_hs = NULL;
40404055

4056+
/* remove from service queue */
40414057
fd_quic_svc_cancel( state->svc_timers, conn );
40424058

40434059
/* put connection back in free list */
40444060
conn->free_conn_next = state->free_conn_list;
40454061
state->free_conn_list = conn->conn_idx;
4046-
fd_quic_set_conn_state( conn, FD_QUIC_CONN_STATE_INVALID );
40474062

40484063
quic->metrics.conn_active_cnt--;
40494064

@@ -4070,7 +4085,6 @@ fd_quic_connect( fd_quic_t * quic,
40704085
}
40714086
}
40724087

4073-
40744088
fd_rng_t * rng = state->_rng;
40754089

40764090
/* create conn ids for us and them

src/waltz/quic/fd_quic_svc_q.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,19 @@ fd_quic_svc_cancel( fd_quic_svc_timers_t * timers,
7878
void
7979
fd_quic_svc_schedule( fd_quic_svc_timers_t * timers,
8080
fd_quic_conn_t * conn ) {
81+
82+
/* if conn null or invalid, do not schedule */
83+
if( FD_UNLIKELY( !conn || conn->state == FD_QUIC_CONN_STATE_INVALID ) ) {
84+
/* cleaner/safer to check in here for now. If function call overhead
85+
becomes a constraint, move check to caller */
86+
return;
87+
}
88+
8189
ulong idx = conn->svc_meta.idx;
8290
ulong expiry = conn->svc_meta.next_timeout;
8391

92+
conn->svc_meta.next_timeout = ULONG_MAX; /* reset next_timeout */
93+
8494
if( FD_UNLIKELY( idx != FD_QUIC_SVC_IDX_INVAL ) ) {
8595
/* find current expiry */
8696
fd_quic_svc_event_t * event = timers + idx;
@@ -95,6 +105,7 @@ fd_quic_svc_schedule( fd_quic_svc_timers_t * timers,
95105
conn->svc_meta.idx = FD_QUIC_SVC_IDX_INVAL;
96106
}
97107
}
108+
/* TODO: potential perf improvement combining remove and insert(?) */
98109

99110
/* insert new element */
100111
fd_quic_svc_event_t e = {
@@ -161,3 +172,8 @@ fd_quic_svc_get_event( fd_quic_svc_timers_t * timers,
161172
if( idx == FD_QUIC_SVC_IDX_INVAL ) return NULL;
162173
return timers + idx;
163174
}
175+
176+
ulong
177+
fd_quic_svc_cnt_events( fd_quic_svc_timers_t * timers ) {
178+
return fd_quic_svc_queue_prq_cnt( timers );
179+
}

src/waltz/quic/fd_quic_svc_q.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ fd_quic_svc_timers_init_conn( fd_quic_conn_t * conn );
5656

5757
/* fd_quic_svc_schedule schedules a connection timer.
5858
Uses conn->svc_meta.next_timeout as the expiry time.
59-
If already scheduled, keeps the earlier time. */
59+
If already scheduled, keeps the earlier time. Resets
60+
next_timeout to ULONG_MAX. */
6061
void
6162
fd_quic_svc_schedule( fd_quic_svc_timers_t * timers,
6263
fd_quic_conn_t * conn );
@@ -90,4 +91,10 @@ fd_quic_svc_event_t*
9091
fd_quic_svc_get_event( fd_quic_svc_timers_t * timers,
9192
fd_quic_conn_t * conn );
9293

94+
95+
/* fd_quic_svc_cnt_events returns the number of conns with active timers
96+
Primarily used for testing/validation. */
97+
ulong
98+
fd_quic_svc_cnt_events( fd_quic_svc_timers_t * timers );
99+
93100
#endif /* HEADER_fd_src_waltz_quic_fd_quic_svc_q_h */

src/waltz/quic/tests/fd_quic_sandbox.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ fd_quic_sandbox_new_conn_established( fd_quic_sandbox_t * sandbox,
315315
conn->srx->rx_max_data_ackd = 0UL;
316316
conn->tx_initial_max_stream_data_uni = 0UL;
317317

318+
fd_quic_state_t * state = fd_quic_get_state( quic );
319+
fd_quic_svc_schedule( state->svc_timers, conn );
320+
318321
/* TODO set a realistic packet number */
319322

320323
return conn;

src/waltz/quic/tests/test_quic_conformance.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,7 @@ test_quic_pktmeta_pktnum_skip( fd_quic_sandbox_t * sandbox,
637637

638638
fd_quic_sandbox_init( sandbox, FD_QUIC_ROLE_SERVER );
639639
fd_quic_t * quic = sandbox->quic;
640+
fd_quic_state_t * state = fd_quic_get_state( quic );
640641
fd_quic_conn_t * conn = fd_quic_sandbox_new_conn_established( sandbox, rng );
641642
fd_quic_metrics_t * metrics = &conn->quic->metrics;
642643
fd_quic_pkt_meta_tracker_t * tracker = &conn->pkt_meta_tracker;
@@ -649,7 +650,8 @@ test_quic_pktmeta_pktnum_skip( fd_quic_sandbox_t * sandbox,
649650
conn->flags = ( conn->flags & ~FD_QUIC_CONN_FLAGS_PING_SENT ) | FD_QUIC_CONN_FLAGS_PING;
650651
conn->upd_pkt_number = FD_QUIC_PKT_NUM_PENDING;
651652
sandbox->wallclock += (ulong)10e6;
652-
fd_quic_svc_schedule1( conn, FD_QUIC_SVC_INSTANT );
653+
conn->svc_meta.next_timeout = sandbox->wallclock;
654+
fd_quic_svc_schedule( state->svc_timers, conn );
653655
fd_quic_service( quic );
654656
FD_TEST( conn->pkt_number[2] == next_pkt_number + 1UL );
655657
next_pkt_number++;
@@ -679,7 +681,8 @@ test_quic_pktmeta_pktnum_skip( fd_quic_sandbox_t * sandbox,
679681
conn->flags = ( conn->flags & ~FD_QUIC_CONN_FLAGS_PING_SENT ) | FD_QUIC_CONN_FLAGS_PING;
680682
conn->upd_pkt_number = FD_QUIC_PKT_NUM_PENDING;
681683
sandbox->wallclock += (ulong)10e6;
682-
fd_quic_svc_schedule1( conn, FD_QUIC_SVC_INSTANT );
684+
conn->svc_meta.next_timeout = sandbox->wallclock;
685+
fd_quic_svc_schedule( state->svc_timers, conn );
683686
fd_quic_service( quic );
684687
FD_TEST( conn->pkt_number[2] == next_pkt_number );
685688
FD_TEST( *metrics_alloc_fail_cnt > alloc_fail_cnt );
@@ -718,7 +721,8 @@ test_quic_pktmeta_pktnum_skip( fd_quic_sandbox_t * sandbox,
718721
conn->flags = ( conn->flags & ~FD_QUIC_CONN_FLAGS_PING_SENT ) | FD_QUIC_CONN_FLAGS_PING;
719722
conn->upd_pkt_number = FD_QUIC_PKT_NUM_PENDING;
720723
sandbox->wallclock += (ulong)10e6;
721-
fd_quic_svc_schedule1( conn, FD_QUIC_SVC_INSTANT );
724+
conn->svc_meta.next_timeout = sandbox->wallclock;
725+
fd_quic_svc_schedule( state->svc_timers, conn );
722726
fd_quic_service( quic );
723727
FD_TEST( conn->pkt_number[2] == next_pkt_number + 1UL );
724728
next_pkt_number++;

src/waltz/quic/tests/test_quic_svc_q.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ test_multiple_connections( fd_quic_svc_timers_t * timers,
105105
fd_quic_conn_t * conns[conn_cnt]; /* array of conn ptrs */
106106
for( uint i=0; i<conn_cnt; i++ ) {
107107
conns[i] = (fd_quic_conn_t *)(conn_base + i * conn_sz);
108+
conns[i]->state = FD_QUIC_CONN_STATE_ACTIVE;
108109
}
109110

110111
ulong now = 1000UL;
@@ -192,6 +193,7 @@ main( int argc, char ** argv ) {
192193

193194
{
194195
fd_quic_conn_t * conn = (fd_quic_conn_t *)create_mock_conns( &limits , 1);
196+
conn->state = FD_QUIC_CONN_STATE_ACTIVE;
195197
test_svc_schedule( timers, conn );
196198
test_svc_cancel( timers, conn );
197199
free( conn );

0 commit comments

Comments
 (0)