Skip to content

Commit 73722fa

Browse files
committed
quic: remove layer 3/4 logic
- Remove ephemeral source port selection - Allow QUIC clients to pass arbitrary src IP and port - Allow initiaing a conn with an 'unknown' src IP (Chosen by layer 3)
1 parent ae37185 commit 73722fa

30 files changed

+77
-175
lines changed

contrib/quic/agave_compat/src/main.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,6 @@ unsafe fn fdquic_to_agave() {
357357

358358
let quic = fd_quic_new_anonymous_small(wksp, FD_QUIC_ROLE_CLIENT as i32, &mut rng);
359359
assert!(!quic.is_null(), "Failed to create fd_quic_t");
360-
(*quic).config.net.ephem_udp_port.lo = client_port;
361-
(*quic).config.net.ephem_udp_port.hi = client_port;
362360

363361
fd_quic_set_aio_net_tx(quic, fd_udpsock_get_tx(udpsock));
364362
fd_udpsock_set_rx(udpsock, fd_quic_get_aio_net_rx(quic));
@@ -369,7 +367,7 @@ unsafe fn fdquic_to_agave() {
369367
"Connecting from 127.0.0.1:{} to 127.0.0.1:{}",
370368
client_port, listen_port
371369
);
372-
let conn = fd_quic_connect(quic, 0x0100007f, listen_port);
370+
let conn = fd_quic_connect(quic, 0x0100007f, listen_port, 0x0100007f, client_port);
373371
assert!(!conn.is_null());
374372
let conn_start = Instant::now();
375373
loop {

contrib/quic/go_compat/main.go

+1-6
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ func clientTest(fdQuic *C.fd_quic_t) {
130130
defer cancel()
131131

132132
C.fd_quic_config_anonymous(fdQuic, C.FD_QUIC_ROLE_CLIENT)
133-
fdQuic.config.net.ip_addr = 0x0100007f
134-
fdQuic.config.net.ephem_udp_port.lo = 8000
135-
fdQuic.config.net.ephem_udp_port.hi = 8001
136133
C.fd_quic_init(fdQuic)
137134

138135
netFdToGo := make(chan []byte, 128)
@@ -225,7 +222,7 @@ func clientTest(fdQuic *C.fd_quic_t) {
225222
return true
226223
}
227224

228-
quicConn := C.fd_quic_connect(fdQuic, 0x0100007f, C.ushort(addrGo.Port))
225+
quicConn := C.fd_quic_connect(fdQuic, 0x0100007f, C.ushort(addrGo.Port), 0x0100007f, C.ushort(addrFd.Port))
229226
if quicConn == nil {
230227
log.Fatal("fd_quic_connect failed")
231228
}
@@ -269,8 +266,6 @@ func serverTest(fdQuic *C.fd_quic_t) {
269266

270267
C.fd_quic_config_anonymous(fdQuic, C.FD_QUIC_ROLE_SERVER)
271268
fdQuic.config.retry = 1
272-
fdQuic.config.net.ip_addr = 0x0100007f
273-
fdQuic.config.net.listen_udp_port = 8000
274269
C.fd_quic_init(fdQuic)
275270

276271
netFdToGo := make(chan []byte, 128)

src/app/fdctl/run/topos/fd_firedancer.c

-1
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,6 @@ fd_topo_initialize( config_t * config ) {
566566
tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
567567
tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
568568
tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
569-
tile->quic.ip_addr = config->tiles.net.ip_addr;
570569
tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
571570
tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
572571
tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;

src/app/fdctl/run/topos/fd_frankendancer.c

-1
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,6 @@ fd_topo_initialize( config_t * config ) {
361361
tile->quic.out_depth = config->tiles.verify.receive_buffer_size;
362362
tile->quic.max_concurrent_connections = config->tiles.quic.max_concurrent_connections;
363363
tile->quic.max_concurrent_handshakes = config->tiles.quic.max_concurrent_handshakes;
364-
tile->quic.ip_addr = config->tiles.net.ip_addr;
365364
tile->quic.quic_transaction_listen_port = config->tiles.quic.quic_transaction_listen_port;
366365
tile->quic.idle_timeout_millis = config->tiles.quic.idle_timeout_millis;
367366
tile->quic.ack_delay_millis = config->tiles.quic.ack_delay_millis;

src/app/fddev/quic_trace/fd_quic_trace_log_tile.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ after_frag( void * _ctx FD_FN_UNUSED,
3434
fd_quic_log_error_t const * error = fd_type_pun_const( ctx->buffer );
3535
printf( "event=conn_close_quic conn_id=%016lx src_ip=%08x enc=%d pktnum=%8lu close_code=0x%lx loc=%.*s(%u)\n",
3636
error->hdr.conn_id,
37-
fd_uint_bswap( FD_LOAD( uint, error->hdr.ip4_saddr ) ),
37+
fd_uint_bswap( error->hdr.ip4_saddr ),
3838
error->hdr.enc_level,
3939
error->hdr.pkt_num,
4040
error->code[0],

src/app/fddev/tiles/fd_benchs.c

+1-8
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,6 @@ populate_quic_config( fd_quic_config_t * config ) {
248248
config->role = FD_QUIC_ROLE_CLIENT;
249249
config->retry = 0;
250250
config->initial_rx_max_stream_data = 0; /* we don't expect the server to initiate streams */
251-
252-
config->net.ephem_udp_port.lo = 12000;
253-
config->net.ephem_udp_port.hi = 12100;
254-
255251
config->net.dscp = 0;
256252
}
257253

@@ -310,7 +306,7 @@ during_frag( fd_benchs_ctx_t * ctx,
310306
uint dest_ip = 0;
311307
ushort dest_port = fd_ushort_bswap( ctx->quic_port );
312308

313-
ctx->quic_conn = fd_quic_connect( ctx->quic, dest_ip, dest_port );
309+
ctx->quic_conn = fd_quic_connect( ctx->quic, dest_ip, dest_port, 0U, 12000 );
314310

315311
/* failed? try later */
316312
if( FD_UNLIKELY( !ctx->quic_conn ) ) {
@@ -502,11 +498,8 @@ unprivileged_init( fd_topo_t * topo,
502498

503499
if( FD_UNLIKELY( !quic_tx_aio ) ) FD_LOG_ERR(( "fd_aio_join failed" ));
504500

505-
uint quic_ip_addr = 0; /* TODO fetch the quic destination ip addr */
506501
ulong quic_idle_timeout_millis = 10000; /* idle timeout in milliseconds */
507502
quic->config.role = FD_QUIC_ROLE_CLIENT;
508-
quic->config.net.ip_addr = quic_ip_addr;
509-
quic->config.net.listen_udp_port = 42424; /* should be unused */
510503
quic->config.idle_timeout = quic_idle_timeout_millis * 1000000UL;
511504
quic->config.initial_rx_max_stream_data = 0;
512505
quic->config.retry = 0; /* unused on clients */

src/app/fddev/txn.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ send_quic_transactions( fd_quic_t * quic,
8888
quic->cb.conn_hs_complete = cb_conn_hs_complete;
8989
quic->cb.stream_notify = cb_stream_notify;
9090

91-
fd_quic_conn_t * conn = fd_quic_connect( quic, dst_ip, dst_port );
91+
fd_quic_conn_t * conn = fd_quic_connect( quic, dst_ip, dst_port, 0U, 0 );
9292
while ( FD_LIKELY( !( g_conn_hs_complete || g_conn_final ) ) ) {
9393
fd_quic_service( quic );
9494
fd_quic_udpsock_service( udpsock );
@@ -180,9 +180,6 @@ txn_cmd_fn( args_t * args,
180180

181181
fd_quic_config_t * client_cfg = &quic->config;
182182
client_cfg->role = FD_QUIC_ROLE_CLIENT;
183-
client_cfg->net.ip_addr = udpsock->listen_ip;
184-
client_cfg->net.ephem_udp_port.lo = (ushort)udpsock->listen_port;
185-
client_cfg->net.ephem_udp_port.hi = (ushort)(udpsock->listen_port + 1);
186183
client_cfg->idle_timeout = 200UL * 1000UL * 1000UL; /* 5000 millis */
187184
client_cfg->initial_rx_max_stream_data = 0; /* doesn't receive */
188185

src/disco/quic/fd_quic_tile.c

-5
Original file line numberDiff line numberDiff line change
@@ -517,13 +517,8 @@ unprivileged_init( fd_topo_t * topo,
517517
if( FD_UNLIKELY( tile->quic.ack_delay_millis >= tile->quic.idle_timeout_millis ) ) {
518518
FD_LOG_ERR(( "Invalid `ack_delay_millis`: must be lower than `idle_timeout_millis`" ));
519519
}
520-
if( FD_UNLIKELY( !tile->quic.ip_addr ) ) {
521-
FD_LOG_ERR(( "QUIC IP address not set" ));
522-
}
523520

524521
quic->config.role = FD_QUIC_ROLE_SERVER;
525-
quic->config.net.ip_addr = tile->quic.ip_addr;
526-
quic->config.net.listen_udp_port = tile->quic.quic_transaction_listen_port;
527522
quic->config.idle_timeout = tile->quic.idle_timeout_millis * (ulong)1e6;
528523
quic->config.ack_delay = tile->quic.ack_delay_millis * (ulong)1e6;
529524
quic->config.initial_rx_max_stream_data = FD_TXN_MTU;

src/disco/topo/fd_topo.h

-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,6 @@ typedef struct {
165165
uint reasm_cnt;
166166
ulong max_concurrent_connections;
167167
ulong max_concurrent_handshakes;
168-
uint ip_addr;
169168
ushort quic_transaction_listen_port;
170169
ulong idle_timeout_millis;
171170
uint ack_delay_millis;

src/waltz/quic/fd_quic.c

+38-62
Original file line numberDiff line numberDiff line change
@@ -273,9 +273,6 @@ fd_quic_config_from_env( int * pargc,
273273
cfg->idle_timeout = idle_timeout_ms * (ulong)1e6;
274274
cfg->initial_rx_max_stream_data = initial_rx_max_stream_data;
275275

276-
cfg->net.ephem_udp_port.lo = 10000;
277-
cfg->net.ephem_udp_port.hi = 11000;
278-
279276
return cfg;
280277
}
281278

@@ -397,15 +394,7 @@ fd_quic_init( fd_quic_t * quic ) {
397394

398395
switch( config->role ) {
399396
case FD_QUIC_ROLE_SERVER:
400-
if( FD_UNLIKELY( !config->net.listen_udp_port ) ) { FD_LOG_WARNING(( "no cfg.net.listen_udp_port" )); return NULL; }
401-
break;
402397
case FD_QUIC_ROLE_CLIENT:
403-
if( FD_UNLIKELY( !config->net.ephem_udp_port.lo
404-
|| !config->net.ephem_udp_port.hi
405-
|| config->net.ephem_udp_port.lo > config->net.ephem_udp_port.hi ) ) {
406-
FD_LOG_WARNING(( "invalid cfg.net.ephem_udp_port" ));
407-
return NULL;
408-
}
409398
break;
410399
default:
411400
FD_LOG_WARNING(( "invalid cfg.role" ));
@@ -588,9 +577,6 @@ fd_quic_init( fd_quic_t * quic ) {
588577
FD_QUIC_TRANSPORT_PARAM_SET( tp, max_ack_delay, max_ack_delay_ms_u );
589578
/* */tp->disable_active_migration_present = 1;
590579

591-
/* Initialize next ephemeral udp port */
592-
state->next_ephem_udp_port = config->net.ephem_udp_port.lo;
593-
594580
return quic;
595581
}
596582

@@ -815,11 +801,11 @@ fd_quic_log_full_hdr( fd_quic_conn_t const * conn,
815801
fd_quic_log_hdr_t hdr = {
816802
.conn_id = conn->our_conn_id,
817803
.pkt_num = pkt->pkt_number,
804+
.ip4_saddr = pkt->ip4->saddr,
818805
.udp_sport = pkt->udp->net_sport,
819806
.enc_level = (uchar)pkt->enc_level,
820807
.flags = 0
821808
};
822-
memcpy( hdr.ip4_saddr, pkt->ip4->saddr_c, 4 );
823809
return hdr;
824810
}
825811

@@ -1364,9 +1350,7 @@ fd_quic_send_retry( fd_quic_t * quic,
13641350
fd_quic_pkt_t * pkt,
13651351
fd_quic_conn_id_t const * odcid,
13661352
fd_quic_conn_id_t const * scid,
1367-
ulong new_conn_id,
1368-
uint dst_ip_addr,
1369-
ushort dst_udp_port ) {
1353+
ulong new_conn_id ) {
13701354

13711355
fd_quic_state_t * state = fd_quic_get_state( quic );
13721356

@@ -1385,9 +1369,10 @@ fd_quic_send_retry( fd_quic_t * quic,
13851369
retry_pkt,
13861370
// encode buffer
13871371
&pkt->ip4->net_id,
1388-
dst_ip_addr,
1389-
quic->config.net.listen_udp_port,
1390-
dst_udp_port ) == FD_QUIC_FAILED ) ) {
1372+
pkt->ip4->saddr,
1373+
pkt->udp->net_sport,
1374+
pkt->ip4->daddr,
1375+
pkt->udp->net_dport ) == FD_QUIC_FAILED ) ) {
13911376
return FD_QUIC_PARSE_FAIL;
13921377
}
13931378
return 0UL;
@@ -1487,11 +1472,6 @@ fd_quic_handle_v1_initial( fd_quic_t * quic,
14871472
fd_memcpy( peer_conn_id.conn_id, initial->src_conn_id, FD_QUIC_MAX_CONN_ID_SZ );
14881473
peer_conn_id.sz = initial->src_conn_id_len;
14891474

1490-
/* Save peer's network endpoint */
1491-
1492-
ushort dst_udp_port = pkt->udp->net_sport;
1493-
uint dst_ip_addr = FD_LOAD( uint, pkt->ip4->saddr_c );
1494-
14951475
/* Prepare QUIC-TLS transport params object (sent as a TLS extension).
14961476
Take template from state and mutate certain params in-place.
14971477
@@ -1531,8 +1511,7 @@ fd_quic_handle_v1_initial( fd_quic_t * quic,
15311511
ulong new_conn_id_u64 = fd_rng_ulong( state->_rng );
15321512
if( FD_UNLIKELY( fd_quic_send_retry(
15331513
quic, pkt,
1534-
&odcid, peer_scid, new_conn_id_u64,
1535-
dst_ip_addr, dst_udp_port ) ) ) {
1514+
&odcid, peer_scid, new_conn_id_u64 ) ) ) {
15361515
return FD_QUIC_FAILED;
15371516
}
15381517
return (initial->pkt_num_pnoff + initial->len);
@@ -1614,8 +1593,10 @@ fd_quic_handle_v1_initial( fd_quic_t * quic,
16141593
conn = fd_quic_conn_create( quic,
16151594
scid,
16161595
&peer_conn_id,
1617-
dst_ip_addr,
1618-
dst_udp_port,
1596+
pkt->ip4->saddr,
1597+
pkt->udp->net_sport,
1598+
pkt->ip4->daddr,
1599+
pkt->udp->net_dport,
16191600
1 /* server */ );
16201601

16211602
if( FD_UNLIKELY( !conn ) ) { /* no free connections */
@@ -1715,6 +1696,12 @@ fd_quic_handle_v1_initial( fd_quic_t * quic,
17151696
return FD_QUIC_PARSE_FAIL;
17161697
}
17171698

1699+
if( FD_UNLIKELY( !conn->host.ip_addr ) ) {
1700+
/* Lock src IP address in place (previously chosen by layer-4 based
1701+
on the route table) */
1702+
conn->host.ip_addr = pkt->ip4->daddr;
1703+
}
1704+
17181705
/* check if reply conn id needs to change */
17191706
if( FD_UNLIKELY( !( conn->server | conn->established ) ) ) {
17201707
/* switch to the source connection id for future replies */
@@ -2996,8 +2983,9 @@ fd_quic_tx_buffered_raw(
29962983
uchar * tx_buf,
29972984
ushort * ipv4_id,
29982985
uint dst_ipv4_addr,
2999-
ushort src_udp_port,
3000-
ushort dst_udp_port
2986+
ushort dst_udp_port,
2987+
uint src_ipv4_addr,
2988+
ushort src_udp_port
30012989
) {
30022990

30032991
/* TODO leave space at front of tx_buf for header
@@ -3029,19 +3017,14 @@ fd_quic_tx_buffered_raw(
30293017
pkt.ip4->ttl = 64; /* TODO make configurable */
30303018
pkt.ip4->protocol = FD_IP4_HDR_PROTOCOL_UDP;
30313019
pkt.ip4->check = 0;
3020+
pkt.ip4->saddr = src_ipv4_addr;
3021+
pkt.ip4->daddr = dst_ipv4_addr;
30323022
pkt.udp->net_sport = src_udp_port;
30333023
pkt.udp->net_dport = dst_udp_port;
30343024
pkt.udp->net_len = (ushort)( 8 + payload_sz );
30353025
pkt.udp->check = 0x0000;
30363026
*ipv4_id = (ushort)( *ipv4_id + 1 );
30373027

3038-
/* TODO saddr could be zero -- should use the kernel routing table to
3039-
determine an appropriate source address */
3040-
3041-
/* copy to avoid alignment issues */
3042-
memcpy( &pkt.ip4->saddr_c, &config->net.ip_addr, 4 );
3043-
memcpy( &pkt.ip4->daddr_c, &dst_ipv4_addr, 4 );
3044-
30453028
ulong rc = fd_quic_encode_ip4( cur_ptr, cur_sz, pkt.ip4 );
30463029
if( FD_UNLIKELY( rc == FD_QUIC_PARSE_FAIL ) ) {
30473030
FD_LOG_ERR(( "fd_quic_encode_ip4 failed with buffer overrun" ));
@@ -3106,8 +3089,9 @@ fd_quic_tx_buffered( fd_quic_t * quic,
31063089
conn->tx_buf_conn,
31073090
&conn->ipv4_id,
31083091
endpoint->ip_addr,
3109-
conn->host.udp_port,
3110-
endpoint->udp_port );
3092+
endpoint->udp_port,
3093+
conn->host.ip_addr,
3094+
conn->host.udp_port);
31113095
}
31123096

31133097
static ulong
@@ -4095,7 +4079,9 @@ fd_quic_conn_free( fd_quic_t * quic,
40954079
fd_quic_conn_t *
40964080
fd_quic_connect( fd_quic_t * quic,
40974081
uint dst_ip_addr,
4098-
ushort dst_udp_port ) {
4082+
ushort dst_udp_port,
4083+
uint src_ip_addr,
4084+
ushort src_udp_port ) {
40994085

41004086
fd_quic_state_t * state = fd_quic_get_state( quic );
41014087

@@ -4120,25 +4106,15 @@ fd_quic_connect( fd_quic_t * quic,
41204106
&peer_conn_id,
41214107
dst_ip_addr,
41224108
dst_udp_port,
4109+
src_ip_addr,
4110+
src_udp_port,
41234111
0 /* client */ );
41244112

41254113
if( FD_UNLIKELY( !conn ) ) {
41264114
FD_DEBUG( FD_LOG_DEBUG(( "fd_quic_conn_create failed" )) );
41274115
return NULL;
41284116
}
41294117

4130-
/* choose a port from ephemeral range */
4131-
fd_quic_config_t * config = &quic->config;
4132-
ushort ephem_lo = config->net.ephem_udp_port.lo;
4133-
ushort ephem_hi = config->net.ephem_udp_port.hi;
4134-
ushort next_ephem = state->next_ephem_udp_port;
4135-
ushort src_port = next_ephem;
4136-
next_ephem++;
4137-
next_ephem = fd_ushort_if( next_ephem >= ephem_hi, ephem_lo, next_ephem );
4138-
state->next_ephem_udp_port = next_ephem;
4139-
4140-
conn->host.udp_port = src_port;
4141-
41424118
/* Prepare QUIC-TLS transport params object (sent as a TLS extension).
41434119
Take template from state and mutate certain params in-place.
41444120
@@ -4201,8 +4177,10 @@ fd_quic_conn_t *
42014177
fd_quic_conn_create( fd_quic_t * quic,
42024178
ulong our_conn_id,
42034179
fd_quic_conn_id_t const * peer_conn_id,
4204-
uint dst_ip_addr,
4205-
ushort dst_udp_port,
4180+
uint peer_ip_addr,
4181+
ushort peer_udp_port,
4182+
uint self_ip_addr,
4183+
ushort self_udp_port,
42064184
int server ) {
42074185

42084186
fd_quic_config_t * config = &quic->config;
@@ -4253,10 +4231,8 @@ fd_quic_conn_create( fd_quic_t * quic,
42534231
conn->svc_time = LONG_MAX;
42544232
conn->our_conn_id = 0;
42554233
conn->host = (fd_quic_net_endpoint_t){
4256-
.ip_addr = config->net.ip_addr,
4257-
.udp_port = fd_ushort_if( server,
4258-
config->net.listen_udp_port,
4259-
state->next_ephem_udp_port )
4234+
.ip_addr = self_ip_addr, /* may be 0, if outgoing */
4235+
.udp_port = self_udp_port,
42604236
};
42614237
memset( &conn->peer[0], 0, sizeof( conn->peer ) );
42624238
conn->conn_gen++;
@@ -4335,8 +4311,8 @@ fd_quic_conn_create( fd_quic_t * quic,
43354311

43364312
/* peer connection id */
43374313
conn->peer_cids[0] = *peer_conn_id;
4338-
conn->peer[0].ip_addr = dst_ip_addr;
4339-
conn->peer[0].udp_port = dst_udp_port;
4314+
conn->peer[0].ip_addr = peer_ip_addr;
4315+
conn->peer[0].udp_port = peer_udp_port;
43404316

43414317
fd_quic_ack_gen_init( conn->ack_gen );
43424318
conn->unacked_sz = 0UL;

0 commit comments

Comments
 (0)