mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-17 23:57:59 +01:00

This is a reland of 8ac9bb4d52
Original change's description:
> Added BBR network controller.
>
> BBR is a congestion control method that is initially developed for TCP.
> This CL adds an implementation of BBR ported from QUIC for use with
> WebRTC. An upcoming CL enables it via a field trial.
>
> Bug: webrtc:8415
> Change-Id: Ie4261d2e43bafa15aa928a7cadcfec256107cdbc
> Reviewed-on: https://webrtc-review.googlesource.com/39788
> Commit-Queue: Sebastian Jansson <srte@webrtc.org>
> Reviewed-by: Philip Eliasson <philipel@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#22647}
Bug: webrtc:8415
Change-Id: I090e4116d1f470acbd64af31520654e1bd8dfcda
Reviewed-on: https://webrtc-review.googlesource.com/65200
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#22766}
148 lines
6 KiB
C++
148 lines
6 KiB
C++
/*
|
|
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
#include "modules/congestion_controller/bbr/bbr_factory.h"
|
|
#include "modules/congestion_controller/bbr/bbr_network_controller.h"
|
|
#include "modules/congestion_controller/network_control/test/mock_network_control.h"
|
|
#include "modules/congestion_controller/network_control/test/network_control_tester.h"
|
|
#include "test/gtest.h"
|
|
|
|
using testing::Field;
|
|
using testing::Matcher;
|
|
using testing::AllOf;
|
|
using testing::Ge;
|
|
using testing::Le;
|
|
using testing::NiceMock;
|
|
using testing::Property;
|
|
using testing::StrictMock;
|
|
using testing::_;
|
|
|
|
namespace webrtc {
|
|
namespace bbr {
|
|
namespace test {
|
|
namespace {
|
|
|
|
const DataRate kInitialBitrate = DataRate::kbps(60);
|
|
const Timestamp kDefaultStartTime = Timestamp::ms(10000000);
|
|
|
|
constexpr double kDataRateMargin = 0.3;
|
|
constexpr double kMinDataRateFactor = 1 - kDataRateMargin;
|
|
constexpr double kMaxDataRateFactor = 1 + kDataRateMargin;
|
|
inline Matcher<TargetTransferRate> TargetRateCloseTo(DataRate rate) {
|
|
DataRate min_data_rate = rate * kMinDataRateFactor;
|
|
DataRate max_data_rate = rate * kMaxDataRateFactor;
|
|
return Field(&TargetTransferRate::target_rate,
|
|
AllOf(Ge(min_data_rate), Le(max_data_rate)));
|
|
}
|
|
|
|
NetworkControllerConfig InitialConfig(
|
|
int starting_bandwidth_kbps = kInitialBitrate.kbps(),
|
|
int min_data_rate_kbps = 0,
|
|
int max_data_rate_kbps = 5 * kInitialBitrate.kbps()) {
|
|
NetworkControllerConfig config;
|
|
config.constraints.at_time = kDefaultStartTime;
|
|
config.constraints.min_data_rate = DataRate::kbps(min_data_rate_kbps);
|
|
config.constraints.max_data_rate = DataRate::kbps(max_data_rate_kbps);
|
|
config.starting_bandwidth = DataRate::kbps(starting_bandwidth_kbps);
|
|
return config;
|
|
}
|
|
|
|
NetworkRouteChange CreateRouteChange(Timestamp at_time,
|
|
DataRate start_rate,
|
|
DataRate min_rate = DataRate::Zero(),
|
|
DataRate max_rate = DataRate::Infinity()) {
|
|
NetworkRouteChange route_change;
|
|
route_change.at_time = at_time;
|
|
route_change.constraints.at_time = at_time;
|
|
route_change.constraints.min_data_rate = min_rate;
|
|
route_change.constraints.max_data_rate = max_rate;
|
|
route_change.starting_rate = start_rate;
|
|
return route_change;
|
|
}
|
|
} // namespace
|
|
|
|
class BbrNetworkControllerTest : public ::testing::Test {
|
|
protected:
|
|
BbrNetworkControllerTest() {}
|
|
~BbrNetworkControllerTest() override {}
|
|
};
|
|
|
|
TEST_F(BbrNetworkControllerTest, SendsConfigurationOnInitialization) {
|
|
StrictMock<webrtc::test::MockNetworkControllerObserver> observer;
|
|
EXPECT_CALL(observer,
|
|
OnTargetTransferRate(TargetRateCloseTo(kInitialBitrate)));
|
|
EXPECT_CALL(observer, OnPacerConfig(Property(&PacerConfig::data_rate,
|
|
Ge(kInitialBitrate))));
|
|
EXPECT_CALL(observer,
|
|
OnCongestionWindow(Field(&CongestionWindow::data_window,
|
|
Property(&DataSize::IsFinite, true))));
|
|
|
|
std::unique_ptr<NetworkControllerInterface> controller_;
|
|
controller_.reset(new BbrNetworkController(&observer, InitialConfig()));
|
|
testing::Mock::VerifyAndClearExpectations(&observer);
|
|
}
|
|
|
|
TEST_F(BbrNetworkControllerTest, SendsConfigurationOnNetworkRouteChanged) {
|
|
StrictMock<webrtc::test::MockNetworkControllerObserver> observer;
|
|
EXPECT_CALL(observer, OnTargetTransferRate(_));
|
|
EXPECT_CALL(observer, OnPacerConfig(_));
|
|
EXPECT_CALL(observer, OnCongestionWindow(_));
|
|
std::unique_ptr<NetworkControllerInterface> controller_;
|
|
controller_.reset(new BbrNetworkController(&observer, InitialConfig()));
|
|
|
|
DataRate new_bitrate = DataRate::bps(200000);
|
|
EXPECT_CALL(observer, OnTargetTransferRate(TargetRateCloseTo(new_bitrate)));
|
|
EXPECT_CALL(observer, OnPacerConfig(Property(&PacerConfig::data_rate,
|
|
Ge(kInitialBitrate))));
|
|
EXPECT_CALL(observer, OnCongestionWindow(_));
|
|
controller_->OnNetworkRouteChange(
|
|
CreateRouteChange(kDefaultStartTime, new_bitrate));
|
|
testing::Mock::VerifyAndClearExpectations(&observer);
|
|
}
|
|
|
|
// Bandwidth estimation is updated when feedbacks are received.
|
|
// Feedbacks which show an increasing delay cause the estimation to be reduced.
|
|
TEST_F(BbrNetworkControllerTest, UpdatesTargetSendRate) {
|
|
BbrNetworkControllerFactory factory;
|
|
webrtc::test::NetworkControllerTester tester(&factory,
|
|
InitialConfig(60, 0, 600));
|
|
auto packet_producer = &webrtc::test::SimpleTargetRateProducer::ProduceNext;
|
|
|
|
tester.RunSimulation(TimeDelta::seconds(5), TimeDelta::ms(10),
|
|
DataRate::kbps(300), TimeDelta::ms(100),
|
|
packet_producer);
|
|
EXPECT_GE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(300) * kMinDataRateFactor);
|
|
EXPECT_LE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(300) * kMaxDataRateFactor);
|
|
|
|
tester.RunSimulation(TimeDelta::seconds(30), TimeDelta::ms(10),
|
|
DataRate::kbps(500), TimeDelta::ms(100),
|
|
packet_producer);
|
|
EXPECT_GE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(500) * kMinDataRateFactor);
|
|
EXPECT_LE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(500) * kMaxDataRateFactor);
|
|
|
|
tester.RunSimulation(TimeDelta::seconds(30), TimeDelta::ms(10),
|
|
DataRate::kbps(100), TimeDelta::ms(200),
|
|
packet_producer);
|
|
EXPECT_GE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(100) * kMinDataRateFactor);
|
|
EXPECT_LE(tester.GetState().target_rate->target_rate,
|
|
DataRate::kbps(100) * kMaxDataRateFactor);
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace bbr
|
|
} // namespace webrtc
|