Add small cost to Vpn

This patch adds small cost to Vpn connections
so that a "raw" connection identical to a vpn connection
will be chosen first.

The feature is gated by a field trial WebRTC-AddNetworkCostToVpn
for safe roll out.

Bug: webrtc:13097
Change-Id: I4ad40fa00780a6d7f89cacf6f85f3db4ecd0988c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/229585
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34822}
This commit is contained in:
Jonas Oreland 2021-08-23 12:16:33 +02:00 committed by WebRTC LUCI CQ
parent b0cb4d1b5d
commit b477fc73cf
4 changed files with 71 additions and 17 deletions

View file

@ -87,29 +87,36 @@ bool SortNetworks(const Network* a, const Network* b) {
}
uint16_t ComputeNetworkCostByType(int type,
bool use_differentiated_cellular_costs) {
bool is_vpn,
bool use_differentiated_cellular_costs,
bool add_network_cost_to_vpn) {
// TODO(jonaso) : Rollout support for cellular network cost using A/B
// experiment to make sure it does not introduce regressions.
int vpnCost = (is_vpn && add_network_cost_to_vpn) ? kNetworkCostVpn : 0;
switch (type) {
case rtc::ADAPTER_TYPE_ETHERNET:
case rtc::ADAPTER_TYPE_LOOPBACK:
return kNetworkCostMin;
return kNetworkCostMin + vpnCost;
case rtc::ADAPTER_TYPE_WIFI:
return kNetworkCostLow;
return kNetworkCostLow + vpnCost;
case rtc::ADAPTER_TYPE_CELLULAR:
return kNetworkCostCellular;
return kNetworkCostCellular + vpnCost;
case rtc::ADAPTER_TYPE_CELLULAR_2G:
return use_differentiated_cellular_costs ? kNetworkCostCellular2G
: kNetworkCostCellular;
return (use_differentiated_cellular_costs ? kNetworkCostCellular2G
: kNetworkCostCellular) +
vpnCost;
case rtc::ADAPTER_TYPE_CELLULAR_3G:
return use_differentiated_cellular_costs ? kNetworkCostCellular3G
: kNetworkCostCellular;
return (use_differentiated_cellular_costs ? kNetworkCostCellular3G
: kNetworkCostCellular) +
vpnCost;
case rtc::ADAPTER_TYPE_CELLULAR_4G:
return use_differentiated_cellular_costs ? kNetworkCostCellular4G
: kNetworkCostCellular;
return (use_differentiated_cellular_costs ? kNetworkCostCellular4G
: kNetworkCostCellular) +
vpnCost;
case rtc::ADAPTER_TYPE_CELLULAR_5G:
return use_differentiated_cellular_costs ? kNetworkCostCellular5G
: kNetworkCostCellular;
return (use_differentiated_cellular_costs ? kNetworkCostCellular5G
: kNetworkCostCellular) +
vpnCost;
case rtc::ADAPTER_TYPE_ANY:
// Candidates gathered from the any-address/wildcard ports, as backups,
// are given the maximum cost so that if there are other candidates with
@ -120,13 +127,13 @@ uint16_t ComputeNetworkCostByType(int type,
// ADAPTER_TYPE_CELLULAR would then have a higher cost. See
// P2PTransportChannel::SortConnectionsAndUpdateState for how we rank and
// select candidate pairs, where the network cost is among the criteria.
return kNetworkCostMax;
return kNetworkCostMax + vpnCost;
case rtc::ADAPTER_TYPE_VPN:
// The cost of a VPN should be computed using its underlying network type.
RTC_NOTREACHED();
return kNetworkCostUnknown;
default:
return kNetworkCostUnknown;
return kNetworkCostUnknown + vpnCost;
}
}
@ -999,7 +1006,9 @@ Network::Network(const std::string& name,
type_(ADAPTER_TYPE_UNKNOWN),
preference_(0),
use_differentiated_cellular_costs_(webrtc::field_trial::IsEnabled(
"WebRTC-UseDifferentiatedCellularCosts")) {}
"WebRTC-UseDifferentiatedCellularCosts")),
add_network_cost_to_vpn_(
webrtc::field_trial::IsEnabled("WebRTC-AddNetworkCostToVpn")) {}
Network::Network(const std::string& name,
const std::string& desc,
@ -1016,7 +1025,9 @@ Network::Network(const std::string& name,
type_(type),
preference_(0),
use_differentiated_cellular_costs_(webrtc::field_trial::IsEnabled(
"WebRTC-UseDifferentiatedCellularCosts")) {}
"WebRTC-UseDifferentiatedCellularCosts")),
add_network_cost_to_vpn_(
webrtc::field_trial::IsEnabled("WebRTC-AddNetworkCostToVpn")) {}
Network::Network(const Network&) = default;
@ -1088,7 +1099,9 @@ webrtc::MdnsResponderInterface* Network::GetMdnsResponder() const {
uint16_t Network::GetCost() const {
AdapterType type = IsVpn() ? underlying_type_for_vpn_ : type_;
return ComputeNetworkCostByType(type, use_differentiated_cellular_costs_);
return ComputeNetworkCostByType(type, IsVpn(),
use_differentiated_cellular_costs_,
add_network_cost_to_vpn_);
}
std::string Network::ToString() const {

View file

@ -504,6 +504,7 @@ class RTC_EXPORT Network {
bool active_ = true;
uint16_t id_ = 0;
bool use_differentiated_cellular_costs_ = false;
bool add_network_cost_to_vpn_ = false;
NetworkPreference network_preference_ = NetworkPreference::NEUTRAL;
friend class NetworkManager;

View file

@ -27,6 +27,11 @@ constexpr uint16_t kNetworkCostUnknown = 50;
constexpr uint16_t kNetworkCostLow = 10;
constexpr uint16_t kNetworkCostMin = 0;
// Add 1 to network cost of underlying network type
// so that e.g a "plain" WIFI is prefered over a VPN over WIFI
// everything else being equal.
constexpr uint16_t kNetworkCostVpn = 1;
// alias
constexpr uint16_t kNetworkCostHigh = kNetworkCostCellular;

View file

@ -1350,4 +1350,39 @@ TEST_F(NetworkTest, WebRTC_BindUsingInterfaceName) {
}
#endif
TEST_F(NetworkTest, NetworkCostVpn_Default) {
IPAddress ip1;
EXPECT_TRUE(IPFromString("2400:4030:1:2c00:be30:0:0:1", &ip1));
Network* net1 = new Network("em1", "em1", TruncateIP(ip1, 64), 64);
net1->set_type(ADAPTER_TYPE_VPN);
net1->set_underlying_type_for_vpn(ADAPTER_TYPE_ETHERNET);
Network* net2 = new Network("em1", "em1", TruncateIP(ip1, 64), 64);
net2->set_type(ADAPTER_TYPE_ETHERNET);
EXPECT_EQ(net1->GetCost(), net2->GetCost());
delete net1;
delete net2;
}
TEST_F(NetworkTest, NetworkCostVpn_VpnMoreExpensive) {
webrtc::test::ScopedFieldTrials field_trials(
"WebRTC-AddNetworkCostToVpn/Enabled/");
IPAddress ip1;
EXPECT_TRUE(IPFromString("2400:4030:1:2c00:be30:0:0:1", &ip1));
Network* net1 = new Network("em1", "em1", TruncateIP(ip1, 64), 64);
net1->set_type(ADAPTER_TYPE_VPN);
net1->set_underlying_type_for_vpn(ADAPTER_TYPE_ETHERNET);
Network* net2 = new Network("em1", "em1", TruncateIP(ip1, 64), 64);
net2->set_type(ADAPTER_TYPE_ETHERNET);
EXPECT_GT(net1->GetCost(), net2->GetCost());
delete net1;
delete net2;
}
} // namespace rtc