diff options
author | ttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-12 05:08:06 +0000 |
---|---|---|
committer | ttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-03-12 05:08:06 +0000 |
commit | e4e522d2a6bf3d977400f2eaba3682c32fcb65f9 (patch) | |
tree | 63272e4f63418325690eb6120b6f7882fe76acc7 | |
parent | d9a9d7a304657712b4d572fd0b58c24933c1bdec (diff) | |
download | chromium_src-e4e522d2a6bf3d977400f2eaba3682c32fcb65f9.zip chromium_src-e4e522d2a6bf3d977400f2eaba3682c32fcb65f9.tar.gz chromium_src-e4e522d2a6bf3d977400f2eaba3682c32fcb65f9.tar.bz2 |
Add AsyncDNS.NameServersType histogram.
Add a histogram that records how many users are using Google Public DNS, other
public resolver addresses, private resolver addresses, or a mix of the above
for their DNS servers.
BUG=350908
Review URL: https://codereview.chromium.org/187673005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@256435 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/dns/dns_config_service.cc | 86 | ||||
-rw-r--r-- | net/dns/dns_config_service.h | 35 | ||||
-rw-r--r-- | net/dns/dns_config_service_unittest.cc | 94 | ||||
-rw-r--r-- | tools/metrics/histograms/histograms.xml | 26 |
4 files changed, 240 insertions, 1 deletions
diff --git a/net/dns/dns_config_service.cc b/net/dns/dns_config_service.cc index 6613182..bfa4b8d 100644 --- a/net/dns/dns_config_service.cc +++ b/net/dns/dns_config_service.cc @@ -8,9 +8,91 @@ #include "base/metrics/histogram.h" #include "base/values.h" #include "net/base/ip_endpoint.h" +#include "net/base/ip_pattern.h" namespace net { +NameServerClassifier::NameServerClassifier() { + // Google Public DNS addresses from: + // https://developers.google.com/speed/public-dns/docs/using + AddRule("8.8.8.8", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS); + AddRule("8.8.4.4", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS); + AddRule("2001:4860:4860:0:0:0:0:8888", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS), + AddRule("2001:4860:4860:0:0:0:0:8844", NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS), + + // Count localhost as private, since we don't know what upstream it uses: + AddRule("127.*.*.*", NAME_SERVERS_TYPE_PRIVATE); + AddRule("0:0:0:0:0:0:0:1", NAME_SERVERS_TYPE_PRIVATE); + + // RFC 1918 private addresses: + AddRule("10.*.*.*", NAME_SERVERS_TYPE_PRIVATE); + AddRule("172.[16-31].*.*", NAME_SERVERS_TYPE_PRIVATE); + AddRule("192.168.*.*", NAME_SERVERS_TYPE_PRIVATE); + + // IPv4 link-local addresses: + AddRule("169.254.*.*", NAME_SERVERS_TYPE_PRIVATE); + + // IPv6 link-local addresses: + AddRule("fe80:*:*:*:*:*:*:*", NAME_SERVERS_TYPE_PRIVATE); + + // Anything else counts as public: + AddRule("*.*.*.*", NAME_SERVERS_TYPE_PUBLIC); + AddRule("*:*:*:*:*:*:*:*", NAME_SERVERS_TYPE_PUBLIC); +} + +NameServerClassifier::~NameServerClassifier() {} + +NameServerClassifier::NameServersType NameServerClassifier::GetNameServersType( + const std::vector<IPEndPoint>& nameservers) const { + NameServersType type = NAME_SERVERS_TYPE_NONE; + for (std::vector<IPEndPoint>::const_iterator it = nameservers.begin(); + it != nameservers.end(); + ++it) { + type = MergeNameServersTypes(type, GetNameServerType(it->address())); + } + return type; +} + +struct NameServerClassifier::NameServerTypeRule { + NameServerTypeRule(const char* pattern_string, NameServersType type) + : type(type) { + bool parsed = pattern.ParsePattern(pattern_string); + DCHECK(parsed); + } + + IPPattern pattern; + NameServersType type; +}; + +void NameServerClassifier::AddRule(const char* pattern_string, + NameServersType address_type) { + rules_.push_back(new NameServerTypeRule(pattern_string, address_type)); +} + +NameServerClassifier::NameServersType NameServerClassifier::GetNameServerType( + const IPAddressNumber& address) const { + for (ScopedVector<NameServerTypeRule>::const_iterator it = rules_.begin(); + it != rules_.end(); + ++it) { + if ((*it)->pattern.Match(address)) + return (*it)->type; + } + NOTREACHED(); + return NAME_SERVERS_TYPE_NONE; +} + +NameServerClassifier::NameServersType +NameServerClassifier::MergeNameServersTypes(NameServersType a, + NameServersType b) { + if (a == NAME_SERVERS_TYPE_NONE) + return b; + if (b == NAME_SERVERS_TYPE_NONE) + return a; + if (a == b) + return a; + return NAME_SERVERS_TYPE_MIXED; +} + // Default values are taken from glibc resolv.h except timeout which is set to // |kDnsTimeoutSeconds|. DnsConfig::DnsConfig() @@ -153,6 +235,10 @@ void DnsConfigService::OnConfigRead(const DnsConfig& config) { base::TimeTicks::Now() - last_sent_empty_time_); } UMA_HISTOGRAM_BOOLEAN("AsyncDNS.ConfigChange", changed); + UMA_HISTOGRAM_ENUMERATION( + "AsyncDNS.NameServersType", + classifier_.GetNameServersType(dns_config_.nameservers), + NameServerClassifier::NAME_SERVERS_TYPE_MAX_VALUE); have_config_ = true; if (have_hosts_ || watch_failed_) diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h index 7386e60..bfb5785 100644 --- a/net/dns/dns_config_service.h +++ b/net/dns/dns_config_service.h @@ -11,6 +11,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "base/threading/non_thread_safe.h" #include "base/time/time.h" #include "base/timer/timer.h" @@ -31,6 +32,37 @@ namespace net { // TODO(szym): Remove code which reads timeout from system. const unsigned kDnsTimeoutSeconds = 1; +// Classifies nameserver address lists for histograms. +class NET_EXPORT_PRIVATE NameServerClassifier { + public: + // This is used in a histogram (AsyncDNS.NameServersType); add new entries + // right before MAX_VALUE. + enum NameServersType { + NAME_SERVERS_TYPE_NONE, + NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS, + NAME_SERVERS_TYPE_PRIVATE, + NAME_SERVERS_TYPE_PUBLIC, + NAME_SERVERS_TYPE_MIXED, + NAME_SERVERS_TYPE_MAX_VALUE + }; + + NameServerClassifier(); + ~NameServerClassifier(); + + NameServersType GetNameServersType( + const std::vector<net::IPEndPoint>& nameservers) const; + + private: + struct NameServerTypeRule; + + void AddRule(const char* pattern_string, NameServersType type); + NameServersType GetNameServerType(const IPAddressNumber& address) const; + static NameServersType MergeNameServersTypes(NameServersType a, + NameServersType b); + + ScopedVector<NameServerTypeRule> rules_; +}; + // DnsConfig stores configuration of the system resolver. struct NET_EXPORT_PRIVATE DnsConfig { DnsConfig(); @@ -90,7 +122,6 @@ struct NET_EXPORT_PRIVATE DnsConfig { bool use_local_ipv6; }; - // Service for reading system DNS settings, on demand or when signalled by // internal watchers and NetworkChangeNotifier. class NET_EXPORT_PRIVATE DnsConfigService @@ -175,6 +206,8 @@ class NET_EXPORT_PRIVATE DnsConfigService // Started in Invalidate*, cleared in On*Read. base::OneShotTimer<DnsConfigService> timer_; + NameServerClassifier classifier_; + DISALLOW_COPY_AND_ASSIGN(DnsConfigService); }; diff --git a/net/dns/dns_config_service_unittest.cc b/net/dns/dns_config_service_unittest.cc index f420680..e71baef 100644 --- a/net/dns/dns_config_service_unittest.cc +++ b/net/dns/dns_config_service_unittest.cc @@ -9,13 +9,107 @@ #include "base/cancelable_callback.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/strings/string_split.h" #include "base/test/test_timeouts.h" +#include "net/base/net_util.h" +#include "net/dns/dns_protocol.h" #include "testing/gtest/include/gtest/gtest.h" namespace net { namespace { +const NameServerClassifier::NameServersType kNone = + NameServerClassifier::NAME_SERVERS_TYPE_NONE; +const NameServerClassifier::NameServersType kGoogle = + NameServerClassifier::NAME_SERVERS_TYPE_GOOGLE_PUBLIC_DNS; +const NameServerClassifier::NameServersType kPrivate = + NameServerClassifier::NAME_SERVERS_TYPE_PRIVATE; +const NameServerClassifier::NameServersType kPublic = + NameServerClassifier::NAME_SERVERS_TYPE_PUBLIC; +const NameServerClassifier::NameServersType kMixed = + NameServerClassifier::NAME_SERVERS_TYPE_MIXED; + +class NameServerClassifierTest : public testing::Test { + protected: + NameServerClassifier::NameServersType Classify( + const std::string& servers_string) { + std::vector<std::string> server_strings; + base::SplitString(servers_string, ' ', &server_strings); + + std::vector<IPEndPoint> servers; + for (std::vector<std::string>::const_iterator it = server_strings.begin(); + it != server_strings.end(); + ++it) { + if (*it == "") + continue; + + IPAddressNumber address; + bool parsed = ParseIPLiteralToNumber(*it, &address); + EXPECT_TRUE(parsed); + servers.push_back(IPEndPoint(address, dns_protocol::kDefaultPort)); + } + + return classifier_.GetNameServersType(servers); + } + + private: + NameServerClassifier classifier_; +}; + +TEST_F(NameServerClassifierTest, None) { + EXPECT_EQ(kNone, Classify("")); +} + +TEST_F(NameServerClassifierTest, Google) { + EXPECT_EQ(kGoogle, Classify("8.8.8.8")); + EXPECT_EQ(kGoogle, Classify("8.8.8.8 8.8.4.4")); + EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888")); + EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 2001:4860:4860::8844")); + EXPECT_EQ(kGoogle, Classify("2001:4860:4860::8888 8.8.8.8")); + + // Make sure nobody took any shortcuts on the IP matching: + EXPECT_EQ(kPublic, Classify("8.8.8.4")); + EXPECT_EQ(kPublic, Classify("8.8.4.8")); + EXPECT_EQ(kPublic, Classify("2001:4860:4860::8884")); + EXPECT_EQ(kPublic, Classify("2001:4860:4860::8848")); + EXPECT_EQ(kPublic, Classify("2001:4860:4860::1:8888")); + EXPECT_EQ(kPublic, Classify("2001:4860:4860:1::8888")); +} + +TEST_F(NameServerClassifierTest, PrivateLocalhost) { + EXPECT_EQ(kPrivate, Classify("127.0.0.1")); + EXPECT_EQ(kPrivate, Classify("::1")); +} + +TEST_F(NameServerClassifierTest, PrivateRfc1918) { + EXPECT_EQ(kPrivate, Classify("10.0.0.0 10.255.255.255")); + EXPECT_EQ(kPrivate, Classify("172.16.0.0 172.31.255.255")); + EXPECT_EQ(kPrivate, Classify("192.168.0.0 192.168.255.255")); + EXPECT_EQ(kPrivate, Classify("10.1.1.1 172.16.1.1 192.168.1.1")); +} + +TEST_F(NameServerClassifierTest, PrivateIPv4LinkLocal) { + EXPECT_EQ(kPrivate, Classify("169.254.0.0 169.254.255.255")); +} + +TEST_F(NameServerClassifierTest, PrivateIPv6LinkLocal) { + EXPECT_EQ(kPrivate, + Classify("fe80:: fe80:ffff:ffff:ffff:ffff:ffff:ffff:ffff")); +} + +TEST_F(NameServerClassifierTest, Public) { + EXPECT_EQ(kPublic, Classify("4.2.2.1")); + EXPECT_EQ(kPublic, Classify("4.2.2.1 4.2.2.2")); +} + +TEST_F(NameServerClassifierTest, Mixed) { + EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1")); + EXPECT_EQ(kMixed, Classify("8.8.8.8 4.2.2.1")); + EXPECT_EQ(kMixed, Classify("192.168.1.1 4.2.2.1")); + EXPECT_EQ(kMixed, Classify("8.8.8.8 192.168.1.1 4.2.2.1")); +} + class DnsConfigServiceTest : public testing::Test { public: void OnConfigChanged(const DnsConfig& config) { diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index b9ba671..75db949 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -732,6 +732,13 @@ other types of suffix sets. </summary> </histogram> +<histogram name="AsyncDNS.NameServersType" enum="AsyncDNSNameServersType"> + <summary> + Type of nameservers in the DNS config, recorded each time the config is read + by the DNSConfigService. + </summary> +</histogram> + <histogram name="AsyncDNS.ParseToAddressList" enum="AsyncDNSParseResult"> <summary> Counts of results of parsing addresses out of DNS responses in successful @@ -24796,6 +24803,25 @@ other types of suffix sets. <int value="4" label="BAD_ADDRESS"/> </enum> +<enum name="AsyncDNSNameServersType" type="int"> + <summary>Type of nameservers in the DNS config.</summary> + <int value="0" label="NONE">No nameservers configured.</int> + <int value="1" label="GOOGLE_PUBLIC_DNS"> + All nameservers are Google Public DNS servers. + </int> + <int value="2" label="PUBLIC"> + All nameservers have public IP addresses (and aren't Google Public DNS + servers). + </int> + <int value="3" label="PRIVATE"> + All nameservers have private IP addresses (loopback, link-local, or RFC + 1918). + </int> + <int value="4" label="MIXED"> + Nameservers are a mix of types (Google Public DNS, public, private). + </int> +</enum> + <enum name="AsyncDNSParseResult" type="int"> <summary>Results of DnsResponse::ParseToAddressList.</summary> <int value="0" label="SUCCESS"/> |