@@ -575,6 +575,7 @@ pub struct Config {
575575 grease : bool ,
576576
577577 cc_algorithm : CongestionControlAlgorithm ,
578+ enable_bbr_app_limited_fix : bool ,
578579 custom_bbr_params : Option < BbrParams > ,
579580 initial_congestion_window_packets : usize ,
580581 enable_relaxed_loss_threshold : bool ,
@@ -653,6 +654,7 @@ impl Config {
653654 application_protos : Vec :: new ( ) ,
654655 grease : true ,
655656 cc_algorithm : CongestionControlAlgorithm :: CUBIC ,
657+ enable_bbr_app_limited_fix : false ,
656658 custom_bbr_params : None ,
657659 initial_congestion_window_packets :
658660 DEFAULT_INITIAL_CONGESTION_WINDOW_PACKETS ,
@@ -1067,6 +1069,15 @@ impl Config {
10671069 self . cc_algorithm = algo;
10681070 }
10691071
1072+ /// Enable a rework of how the BBR congestion control implementation
1073+ /// computes app-limited. This config parameter will be removed after we
1074+ /// build confidence on the new implementation or decide to roll it back.
1075+ ///
1076+ /// Defaults to `false`.
1077+ pub fn set_enable_bbr_app_limited_fix ( & mut self , value : bool ) {
1078+ self . enable_bbr_app_limited_fix = value;
1079+ }
1080+
10701081 /// Sets custom BBR settings.
10711082 ///
10721083 /// This API is experimental and will be removed in the future.
@@ -2233,6 +2244,32 @@ impl<F: BufFactory> Connection<F> {
22332244 Ok ( ( ) )
22342245 }
22352246
2247+ /// Enable a rework of how the BBR congestion control implementation
2248+ /// computes app-limited. This config parameter will be removed after we
2249+ /// build confidence on the new implementation or decide to roll it back.
2250+ ///
2251+ /// Currently this only applies if cc_algorithm is
2252+ /// `CongestionControlAlgorithm::Bbr2Gcongestion`.
2253+ ///
2254+ /// This function can only be called inside one of BoringSSL's handshake
2255+ /// callbacks, before any packet has been sent. Calling this function any
2256+ /// other time will have no effect.
2257+ ///
2258+ /// See [`Config::set_enable_bbr_app_limited_fix()`].
2259+ ///
2260+ /// [`Config::set_enable_bbr_app_limited_fix()`]: struct.Config.html#method.set_enable_bbr_app_limited_fix
2261+ #[ cfg( feature = "boringssl-boring-crate" ) ]
2262+ #[ cfg_attr( docsrs, doc( cfg( feature = "boringssl-boring-crate" ) ) ) ]
2263+ pub fn set_enable_bbr_app_limited_fix_in_handshake (
2264+ ssl : & mut boring:: ssl:: SslRef , value : bool ,
2265+ ) -> Result < ( ) > {
2266+ let ex_data = tls:: ExData :: from_ssl_ref ( ssl) . ok_or ( Error :: TlsFail ) ?;
2267+
2268+ ex_data. recovery_config . enable_bbr_app_limited_fix = value;
2269+
2270+ Ok ( ( ) )
2271+ }
2272+
22362273 /// Sets the congestion control algorithm used by string.
22372274 ///
22382275 /// This function can only be called inside one of BoringSSL's handshake
@@ -2494,6 +2531,51 @@ impl<F: BufFactory> Connection<F> {
24942531 Ok ( ( ) )
24952532 }
24962533
2534+ /// Returns true if at least 1 stream has headers or body data to write.
2535+ pub fn has_flushable_stream ( & self ) -> bool {
2536+ self . streams . has_flushable ( )
2537+ }
2538+
2539+ /// Signal the start of an iteration of the event loop that will
2540+ /// receive packets and then attempt to send packets.
2541+ ///
2542+ /// This hook is used to implement the "Detecting application-limited
2543+ /// phases" logic described in the BBR RFC draft which is described at:
2544+ /// https://www.ietf.org/archive/id/draft-ietf-ccwg-bbr-04.html#name-detecting-application-limit
2545+ ///
2546+ /// This function must be invoked at the beginning of each iteration of the
2547+ /// connection work loop, before receiving packets from the network and
2548+ /// processing ACKs/timeouts.
2549+ ///
2550+ /// The expected work loop order is:
2551+ /// 1. Call work_loop_round_start with the value of has_flushable_stream
2552+ /// from the end of the previous loop, before polling for additional
2553+ /// application data.
2554+ /// 2. Process timeouts by calling conn.on_timeout().
2555+ /// 3. Call conn.recv() to process received packets which contain ACKs and
2556+ /// stream data.
2557+ /// 4. Call conn.send_on_path() to generate new packets and send them.
2558+ /// 5. Save the value of conn.has_flushable_stream() for the next iteration.
2559+ /// 6. Poll for additional data from upstream or wait for the next send
2560+ /// timeout.
2561+ ///
2562+ /// In cases where the new packet generate + send loop yields early due to
2563+ /// an interation limit or the sendmsg on the socket returning EAGAIN, we
2564+ /// should expect had_flushable_stream_before_poll to remain true since the
2565+ /// connection wasn't able to send all the available data despite not
2566+ /// consuming the full congestion window. The call to
2567+ /// bbr_check_if_app_limited() will not mark the connection app-limited
2568+ /// at the last-sent-packet-number because had_flushable_stream_before_poll
2569+ /// is true; this is correct and expected behavior.
2570+ pub fn work_loop_round_start (
2571+ & mut self , had_flushable_stream_before_poll : bool , now : & Instant ,
2572+ ) {
2573+ for ( _, path) in self . paths . iter_mut ( ) {
2574+ path. recovery
2575+ . bbr_check_if_app_limited ( had_flushable_stream_before_poll, now) ;
2576+ }
2577+ }
2578+
24972579 /// Processes QUIC packets received from the peer.
24982580 ///
24992581 /// On success the number of bytes processed from the input buffer is
0 commit comments