@@ -49,6 +49,12 @@ pub const QUIC_MAX_STAKED_CONCURRENT_STREAMS: usize = 512;
4949
5050pub const QUIC_TOTAL_STAKED_CONCURRENT_STREAMS : usize = 100_000 ;
5151
52+ /// RTT after which we start BDP scaling
53+ const REFERENCE_RTT_MS : u64 = 50 ;
54+
55+ /// Above this RTT we stop scaling for BDP
56+ const MAX_RTT_MS : u64 = 350 ;
57+
5258#[ derive( Clone ) ]
5359pub struct SwQosConfig {
5460 pub max_streams_per_ms : u64 ,
@@ -140,8 +146,12 @@ impl SwQos {
140146 }
141147}
142148
143- fn compute_max_allowed_uni_streams ( peer_type : ConnectionPeerType , total_stake : u64 ) -> usize {
144- match peer_type {
149+ fn compute_max_allowed_uni_streams (
150+ rtt_millis : u64 ,
151+ peer_type : ConnectionPeerType ,
152+ total_stake : u64 ,
153+ ) -> usize {
154+ let streams = match peer_type {
145155 ConnectionPeerType :: Staked ( peer_stake) => {
146156 // No checked math for f64 type. So let's explicitly check for 0 here
147157 if total_stake == 0 || peer_stake > total_stake {
@@ -164,7 +174,10 @@ fn compute_max_allowed_uni_streams(peer_type: ConnectionPeerType, total_stake: u
164174 }
165175 }
166176 ConnectionPeerType :: Unstaked => QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS ,
167- }
177+ } ;
178+ // scale amount of streams based on RTT if RTT is larger than REFERENCE_RTT_MS
179+ // multiply first then divide to avoid rounding errors.
180+ ( streams * rtt_millis. clamp ( REFERENCE_RTT_MS , MAX_RTT_MS ) as usize ) / REFERENCE_RTT_MS as usize
168181}
169182
170183impl SwQos {
@@ -182,7 +195,10 @@ impl SwQos {
182195 ) ,
183196 ConnectionHandlerError ,
184197 > {
198+ // get current RTT and limit it to MAX_RTT_MS
199+ let rtt_millis = connection. rtt ( ) . as_millis ( ) as u64 ;
185200 if let Ok ( max_uni_streams) = VarInt :: from_u64 ( compute_max_allowed_uni_streams (
201+ rtt_millis,
186202 conn_context. peer_type ( ) ,
187203 conn_context. total_stake ,
188204 ) as u64 )
@@ -528,27 +544,48 @@ pub mod test {
528544 #[ test]
529545 fn test_max_allowed_uni_streams ( ) {
530546 assert_eq ! (
531- compute_max_allowed_uni_streams( ConnectionPeerType :: Unstaked , 0 ) ,
547+ compute_max_allowed_uni_streams( REFERENCE_RTT_MS , ConnectionPeerType :: Unstaked , 0 ) ,
532548 QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS
533549 ) ;
534550 assert_eq ! (
535- compute_max_allowed_uni_streams( ConnectionPeerType :: Staked ( 10 ) , 0 ) ,
551+ compute_max_allowed_uni_streams( REFERENCE_RTT_MS , ConnectionPeerType :: Staked ( 10 ) , 0 ) ,
536552 QUIC_MIN_STAKED_CONCURRENT_STREAMS
537553 ) ;
538554 let delta =
539555 ( QUIC_TOTAL_STAKED_CONCURRENT_STREAMS - QUIC_MIN_STAKED_CONCURRENT_STREAMS ) as f64 ;
540556 assert_eq ! (
541- compute_max_allowed_uni_streams( ConnectionPeerType :: Staked ( 1000 ) , 10000 ) ,
557+ compute_max_allowed_uni_streams(
558+ REFERENCE_RTT_MS ,
559+ ConnectionPeerType :: Staked ( 1000 ) ,
560+ 10000
561+ ) ,
542562 QUIC_MAX_STAKED_CONCURRENT_STREAMS ,
543563 ) ;
544564 assert_eq ! (
545- compute_max_allowed_uni_streams( ConnectionPeerType :: Staked ( 100 ) , 10000 ) ,
565+ compute_max_allowed_uni_streams(
566+ REFERENCE_RTT_MS ,
567+ ConnectionPeerType :: Staked ( 100 ) ,
568+ 10000
569+ ) ,
546570 ( ( delta / ( 100_f64 ) ) as usize + QUIC_MIN_STAKED_CONCURRENT_STREAMS )
547571 . min( QUIC_MAX_STAKED_CONCURRENT_STREAMS )
548572 ) ;
549573 assert_eq ! (
550- compute_max_allowed_uni_streams( ConnectionPeerType :: Unstaked , 10000 ) ,
574+ compute_max_allowed_uni_streams(
575+ REFERENCE_RTT_MS / 2 ,
576+ ConnectionPeerType :: Unstaked ,
577+ 10000
578+ ) ,
551579 QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS
552580 ) ;
581+ assert_eq ! (
582+ compute_max_allowed_uni_streams(
583+ REFERENCE_RTT_MS + REFERENCE_RTT_MS / 2 ,
584+ ConnectionPeerType :: Unstaked ,
585+ 10000
586+ ) ,
587+ QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS + QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS / 2 ,
588+ "Amount of streams should scale with RTT"
589+ ) ;
553590 }
554591}
0 commit comments