From b477fc73cfd2f4c09bb9c416b170ba4b566cecaf Mon Sep 17 00:00:00 2001 From: Jonas Oreland Date: Mon, 23 Aug 2021 12:16:33 +0200 Subject: [PATCH] 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 Reviewed-by: Harald Alvestrand Cr-Commit-Position: refs/heads/master@{#34822} --- rtc_base/network.cc | 47 +++++++++++++++++++++++------------- rtc_base/network.h | 1 + rtc_base/network_constants.h | 5 ++++ rtc_base/network_unittest.cc | 35 +++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 17 deletions(-) diff --git a/rtc_base/network.cc b/rtc_base/network.cc index ab0e1232ba..e1d39ebff5 100644 --- a/rtc_base/network.cc +++ b/rtc_base/network.cc @@ -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 { diff --git a/rtc_base/network.h b/rtc_base/network.h index 8088840e69..74b4aed2f9 100644 --- a/rtc_base/network.h +++ b/rtc_base/network.h @@ -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; diff --git a/rtc_base/network_constants.h b/rtc_base/network_constants.h index cdb505f9d7..0495afdcc9 100644 --- a/rtc_base/network_constants.h +++ b/rtc_base/network_constants.h @@ -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; diff --git a/rtc_base/network_unittest.cc b/rtc_base/network_unittest.cc index 4bfe93fa0c..325d1a1a5c 100644 --- a/rtc_base/network_unittest.cc +++ b/rtc_base/network_unittest.cc @@ -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