@@ -457,6 +457,9 @@ const MAX_SEND_UDP_PAYLOAD_SIZE: usize = 1200;
457
457
// The default length of DATAGRAM queues.
458
458
const DEFAULT_MAX_DGRAM_QUEUE_LEN: usize = 0;
459
459
460
+ // The default length of PATH_CHALLENGE receive queue.
461
+ const DEFAULT_MAX_PATH_CHALLENGE_RX_QUEUE_LEN: usize = 3;
462
+
460
463
// The DATAGRAM standard recommends either none or 65536 as maximum DATAGRAM
461
464
// frames size. We enforce the recommendation for forward compatibility.
462
465
const MAX_DGRAM_FRAME_SIZE: u64 = 65536;
@@ -718,6 +721,8 @@ pub struct Config {
718
721
dgram_recv_max_queue_len: usize,
719
722
dgram_send_max_queue_len: usize,
720
723
724
+ path_challenge_recv_max_queue_len: usize,
725
+
721
726
max_send_udp_payload_size: usize,
722
727
723
728
max_connection_window: u64,
@@ -780,6 +785,9 @@ impl Config {
780
785
dgram_recv_max_queue_len: DEFAULT_MAX_DGRAM_QUEUE_LEN,
781
786
dgram_send_max_queue_len: DEFAULT_MAX_DGRAM_QUEUE_LEN,
782
787
788
+ path_challenge_recv_max_queue_len:
789
+ DEFAULT_MAX_PATH_CHALLENGE_RX_QUEUE_LEN,
790
+
783
791
max_send_udp_payload_size: MAX_SEND_UDP_PAYLOAD_SIZE,
784
792
785
793
max_connection_window: MAX_CONNECTION_WINDOW,
@@ -1194,6 +1202,16 @@ impl Config {
1194
1202
self.dgram_send_max_queue_len = send_queue_len;
1195
1203
}
1196
1204
1205
+ /// Configures the max number of queued received PATH_CHALLENGE frames.
1206
+ ///
1207
+ /// When an endpoint receives a PATH_CHALLENGE frame and the queue is full,
1208
+ /// the frame is discarded.
1209
+ ///
1210
+ /// The default is 3.
1211
+ pub fn set_path_challenge_recv_max_queue_len(&mut self, queue_len: usize) {
1212
+ self.path_challenge_recv_max_queue_len = queue_len;
1213
+ }
1214
+
1197
1215
/// Sets the maximum size of the connection window.
1198
1216
///
1199
1217
/// The default value is MAX_CONNECTION_WINDOW (24MBytes).
@@ -1268,6 +1286,12 @@ pub struct Connection {
1268
1286
/// The path manager.
1269
1287
paths: path::PathMap,
1270
1288
1289
+ /// PATH_CHALLENGE receive queue max length.
1290
+ path_challenge_recv_max_queue_len: usize,
1291
+
1292
+ /// Total number of received PATH_CHALLENGE frames.
1293
+ path_challenge_rx_count: u64,
1294
+
1271
1295
/// List of supported application protocols.
1272
1296
application_protos: Vec<Vec<u8>>,
1273
1297
@@ -1720,7 +1744,13 @@ impl Connection {
1720
1744
1721
1745
let recovery_config = recovery::RecoveryConfig::from_config(config);
1722
1746
1723
- let mut path = path::Path::new(local, peer, &recovery_config, true);
1747
+ let mut path = path::Path::new(
1748
+ local,
1749
+ peer,
1750
+ &recovery_config,
1751
+ config.path_challenge_recv_max_queue_len,
1752
+ true,
1753
+ );
1724
1754
// If we did stateless retry assume the peer's address is verified.
1725
1755
path.verified_peer_address = odcid.is_some();
1726
1756
// Assume clients validate the server's address implicitly.
@@ -1766,6 +1796,9 @@ impl Connection {
1766
1796
recovery_config,
1767
1797
1768
1798
paths,
1799
+ path_challenge_recv_max_queue_len: config
1800
+ .path_challenge_recv_max_queue_len,
1801
+ path_challenge_rx_count: 0,
1769
1802
1770
1803
application_protos: config.application_protos.clone(),
1771
1804
@@ -6284,6 +6317,7 @@ impl Connection {
6284
6317
stopped_stream_count_local: self.stopped_stream_local_count,
6285
6318
reset_stream_count_remote: self.reset_stream_remote_count,
6286
6319
stopped_stream_count_remote: self.stopped_stream_remote_count,
6320
+ path_challenge_rx_count: self.path_challenge_rx_count,
6287
6321
}
6288
6322
}
6289
6323
@@ -7009,6 +7043,8 @@ impl Connection {
7009
7043
},
7010
7044
7011
7045
frame::Frame::PathChallenge { data } => {
7046
+ self.path_challenge_rx_count += 1;
7047
+
7012
7048
self.paths
7013
7049
.get_mut(recv_path_id)?
7014
7050
.on_challenge_received(data);
@@ -7301,8 +7337,13 @@ impl Connection {
7301
7337
}
7302
7338
7303
7339
// This is a new path using an unassigned CID; create it!
7304
- let mut path =
7305
- path::Path::new(info.to, info.from, &self.recovery_config, false);
7340
+ let mut path = path::Path::new(
7341
+ info.to,
7342
+ info.from,
7343
+ &self.recovery_config,
7344
+ self.path_challenge_recv_max_queue_len,
7345
+ false,
7346
+ );
7306
7347
7307
7348
path.max_send_bytes = buf_len * MAX_AMPLIFICATION_FACTOR;
7308
7349
path.active_scid_seq = Some(in_scid_seq);
@@ -7424,8 +7465,13 @@ impl Connection {
7424
7465
.ok_or(Error::OutOfIdentifiers)?
7425
7466
};
7426
7467
7427
- let mut path =
7428
- path::Path::new(local_addr, peer_addr, &self.recovery_config, false);
7468
+ let mut path = path::Path::new(
7469
+ local_addr,
7470
+ peer_addr,
7471
+ &self.recovery_config,
7472
+ self.path_challenge_recv_max_queue_len,
7473
+ false,
7474
+ );
7429
7475
path.active_dcid_seq = Some(dcid_seq);
7430
7476
7431
7477
let pid = self
@@ -7532,6 +7578,9 @@ pub struct Stats {
7532
7578
7533
7579
/// The number of streams stopped by remote.
7534
7580
pub stopped_stream_count_remote: u64,
7581
+
7582
+ /// The total number of PATH_CHALLENGE frames that were received.
7583
+ pub path_challenge_rx_count: u64,
7535
7584
}
7536
7585
7537
7586
impl std::fmt::Debug for Stats {
@@ -15300,6 +15349,9 @@ mod tests {
15300
15349
};
15301
15350
assert_eq!(pipe.server.recv(&mut buf[..sent], ri), Ok(sent));
15302
15351
15352
+ let stats = pipe.server.stats();
15353
+ assert_eq!(stats.path_challenge_rx_count, 1);
15354
+
15303
15355
// A non-existing 4-tuple raises an InvalidState.
15304
15356
let client_addr_3 = "127.0.0.1:9012".parse().unwrap();
15305
15357
let server_addr_2 = "127.0.0.1:9876".parse().unwrap();
@@ -15341,6 +15393,9 @@ mod tests {
15341
15393
};
15342
15394
assert_eq!(pipe.server.recv(&mut buf[..sent], ri), Ok(sent));
15343
15395
15396
+ let stats = pipe.server.stats();
15397
+ assert_eq!(stats.path_challenge_rx_count, 2);
15398
+
15344
15399
// STREAM frame on active path.
15345
15400
let (sent, si) = pipe
15346
15401
.client
@@ -15355,6 +15410,9 @@ mod tests {
15355
15410
};
15356
15411
assert_eq!(pipe.server.recv(&mut buf[..sent], ri), Ok(sent));
15357
15412
15413
+ let stats = pipe.server.stats();
15414
+ assert_eq!(stats.path_challenge_rx_count, 2);
15415
+
15358
15416
// PATH_CHALLENGE
15359
15417
let (sent, si) = pipe
15360
15418
.client
@@ -15370,6 +15428,9 @@ mod tests {
15370
15428
};
15371
15429
assert_eq!(pipe.server.recv(&mut buf[..sent], ri), Ok(sent));
15372
15430
15431
+ let stats = pipe.server.stats();
15432
+ assert_eq!(stats.path_challenge_rx_count, 3);
15433
+
15373
15434
// STREAM frame on active path.
15374
15435
let (sent, si) = pipe
15375
15436
.client
@@ -15419,6 +15480,9 @@ mod tests {
15419
15480
v2.sort();
15420
15481
15421
15482
assert_eq!(v1, v2);
15483
+
15484
+ let stats = pipe.server.stats();
15485
+ assert_eq!(stats.path_challenge_rx_count, 3);
15422
15486
}
15423
15487
15424
15488
#[test]
0 commit comments