UMA Metric for reporting network problem while connected. Added a UMA metric for reporting network problem while connected to a network. Network problem is detected by TrafficMonitor. Max of one network problem will be reported per connection. BUG=chromium:374274 TEST=unit tests, manual Manual Test: 1. Connect a chrome device an AP without internet access. 2. Wait for few minutes, then browse to "chrome://histograms", and verify there is a histogram for Network.Shill.Wifi.NetworkProblemDetected". Change-Id: Iad019d147feebcd429445c687a7c37d8e1e281f9 Reviewed-on: https://chromium-review.googlesource.com/200469 Reviewed-by: Peter Qiu <zqiu@chromium.org> Commit-Queue: Peter Qiu <zqiu@chromium.org> Tested-by: Peter Qiu <zqiu@chromium.org>
diff --git a/active_passive_out_of_credits_detector.cc b/active_passive_out_of_credits_detector.cc index 9a3b99e..ea02fd0 100644 --- a/active_passive_out_of_credits_detector.cc +++ b/active_passive_out_of_credits_detector.cc
@@ -31,7 +31,7 @@ traffic_monitor_( new TrafficMonitor(service->cellular(), dispatcher)) { ResetDetector(); - traffic_monitor_->set_tcp_out_traffic_not_routed_callback( + traffic_monitor_->set_network_problem_detected_callback( Bind(&ActivePassiveOutOfCreditsDetector::OnNoNetworkRouting, weak_ptr_factory_.GetWeakPtr())); } @@ -102,7 +102,7 @@ traffic_monitor_->Stop(); } -void ActivePassiveOutOfCreditsDetector::OnNoNetworkRouting() { +void ActivePassiveOutOfCreditsDetector::OnNoNetworkRouting(int reason) { SLOG(Cellular, 2) << "Service " << service()->friendly_name() << ": Traffic Monitor detected network congestion."; SLOG(Cellular, 2) << "Requesting active probe for out-of-credit detection.";
diff --git a/active_passive_out_of_credits_detector.h b/active_passive_out_of_credits_detector.h index 3843e52..b49b7fa 100644 --- a/active_passive_out_of_credits_detector.h +++ b/active_passive_out_of_credits_detector.h
@@ -58,7 +58,7 @@ void StopTrafficMonitor(); // Responds to a TrafficMonitor no-network-routing failure. - void OnNoNetworkRouting(); + void OnNoNetworkRouting(int reason); // Initializes and configures the connection health checker. void SetupConnectionHealthChecker();
diff --git a/active_passive_out_of_credits_detector_unittest.cc b/active_passive_out_of_credits_detector_unittest.cc index b7dec85..de1e23c 100644 --- a/active_passive_out_of_credits_detector_unittest.cc +++ b/active_passive_out_of_credits_detector_unittest.cc
@@ -282,7 +282,7 @@ Unretained(this))); SetConnectionHealthChecker(health_checker); // Passes ownership. EXPECT_CALL(*health_checker, Start()); - out_of_credits_detector_->OnNoNetworkRouting(); + out_of_credits_detector_->OnNoNetworkRouting(0); EXPECT_FALSE(out_of_credits_detector_->out_of_credits()); Mock::VerifyAndClearExpectations(health_checker); @@ -291,7 +291,7 @@ EXPECT_CALL(*health_checker, health_check_in_progress()) .WillOnce(Return(true)); EXPECT_CALL(*health_checker, Start()).Times(0); - out_of_credits_detector_->OnNoNetworkRouting(); + out_of_credits_detector_->OnNoNetworkRouting(0); } TEST_F(ActivePassiveOutOfCreditsDetectorTest,
diff --git a/device.cc b/device.cc index 3482747..b8a3a46 100644 --- a/device.cc +++ b/device.cc
@@ -43,6 +43,7 @@ #include "shill/store_interface.h" #include "shill/technology.h" #include "shill/tethering.h" +#include "shill/traffic_monitor.h" using base::Bind; using base::FilePath; @@ -566,6 +567,7 @@ StartPortalDetection(); } StartLinkMonitor(); + StartTrafficMonitor(); UpdateIPConfigsProperty(); } @@ -656,6 +658,7 @@ void Device::DestroyConnection() { SLOG(Device, 2) << __func__ << " on " << link_name_; + StopTrafficMonitor(); StopPortalDetection(); StopLinkMonitor(); if (selected_service_.get()) { @@ -684,6 +687,7 @@ // Just in case the Device subclass has not already done so, make // sure the previously selected service has its connection removed. selected_service_->SetConnection(NULL); + StopTrafficMonitor(); StopLinkMonitor(); StopPortalDetection(); } @@ -914,6 +918,65 @@ fallback_dns_test_client_.reset(); } +void Device::set_traffic_monitor(TrafficMonitor *traffic_monitor) { + traffic_monitor_.reset(traffic_monitor); +} + +bool Device::IsTrafficMonitorEnabled() const { + return false; +} + +void Device::StartTrafficMonitor() { + // Return if traffic monitor is not enabled for this device. + if (!IsTrafficMonitorEnabled()) { + return; + } + + SLOG(Device, 2) << "Device " << FriendlyName() + << ": Traffic Monitor starting."; + if (!traffic_monitor_.get()) { + traffic_monitor_.reset(new TrafficMonitor(this, dispatcher_)); + traffic_monitor_->set_network_problem_detected_callback( + Bind(&Device::OnEncounterNetworkProblem, + weak_ptr_factory_.GetWeakPtr())); + } + traffic_monitor_->Start(); +} + +void Device::StopTrafficMonitor() { + // Return if traffic monitor is not enabled for this device. + if (!IsTrafficMonitorEnabled()) { + return; + } + + if (traffic_monitor_.get()) { + SLOG(Device, 2) << "Device " << FriendlyName() + << ": Traffic Monitor stopping."; + traffic_monitor_->Stop(); + } + traffic_monitor_.reset(); +} + +void Device::OnEncounterNetworkProblem(int reason) { + int metric_code; + switch (reason) { + case TrafficMonitor::kNetworkProblemCongestedTxQueue: + metric_code = Metrics::kNetworkProblemCongestedTCPTxQueue; + break; + case TrafficMonitor::kNetworkProblemDNSFailure: + metric_code = Metrics::kNetworkProblemDNSFailure; + break; + default: + LOG(ERROR) << "Invalid network problem code: " << reason; + return; + } + + metrics()->NotifyNetworkProblemDetected(technology_, metric_code); + // Stop the traffic monitor, only report the first network problem detected + // on the connection for now. + StopTrafficMonitor(); +} + void Device::SetServiceConnectedState(Service::ConnectState state) { DCHECK(selected_service_.get());
diff --git a/device.h b/device.h index 34500aa..e1408db 100644 --- a/device.h +++ b/device.h
@@ -436,6 +436,23 @@ // Respond to a LinkMonitor gateway's MAC address found/change event. virtual void OnLinkMonitorGatewayChange(); + // Returns true if traffic monitor is enabled on this device. The default + // implementation will return false, which can be overridden by a derived + // class. + virtual bool IsTrafficMonitorEnabled() const; + + // Initiates traffic monitoring on the device if traffic monitor is enabled. + void StartTrafficMonitor(); + + // Stops traffic monitoring on the device if traffic monitor is enabled. + void StopTrafficMonitor(); + + // Called by the Traffic Monitor when it detects a network problem. Device + // subclasses that want to roam to a different network when encountering + // network problems can override this method in order to do so. The parent + // implementation handles the metric reporting of the network problem. + virtual void OnEncounterNetworkProblem(int reason); + // Set the state of the selected service, with checks to make sure // the service is already in a connected state before doing so. void SetServiceConnectedState(Service::ConnectState state); @@ -469,6 +486,8 @@ Manager *manager() const { return manager_; } const LinkMonitor *link_monitor() const { return link_monitor_.get(); } void set_link_monitor(LinkMonitor *link_monitor); + // Use for unit test. + void set_traffic_monitor(TrafficMonitor *traffic_monitor); private: friend class CellularCapabilityTest; @@ -593,6 +612,7 @@ portal_detector_callback_; base::Callback<void(const Error &, const IPAddress &)> dns_client_callback_; + scoped_ptr<TrafficMonitor> traffic_monitor_; Technology::Identifier technology_; // The number of portal detection attempts from Connected to Online state. // This includes all failure/timeout attempts and the final successful
diff --git a/device_unittest.cc b/device_unittest.cc index 468408b..bc5ad9b 100644 --- a/device_unittest.cc +++ b/device_unittest.cc
@@ -92,6 +92,9 @@ .WillByDefault(Invoke(this, &TestDevice::DeviceIsIPv6Allowed)); ON_CALL(*this, SetIPFlag(_, _, _)) .WillByDefault(Invoke(this, &TestDevice::DeviceSetIPFlag)); + ON_CALL(*this, IsTrafficMonitorEnabled()) + .WillByDefault(Invoke(this, + &TestDevice::DeviceIsTrafficMonitorEnabled)); } ~TestDevice() {} @@ -107,6 +110,7 @@ } MOCK_CONST_METHOD0(IsIPv6Allowed, bool()); + MOCK_CONST_METHOD0(IsTrafficMonitorEnabled, bool()); MOCK_METHOD3(SetIPFlag, bool(IPAddress::Family family, const std::string &flag, @@ -116,6 +120,10 @@ return Device::IsIPv6Allowed(); } + virtual bool DeviceIsTrafficMonitorEnabled() const { + return Device::IsTrafficMonitorEnabled(); + } + virtual bool DeviceSetIPFlag(IPAddress::Family family, const std::string &flag, const std::string &value) { @@ -192,6 +200,22 @@ return device_->GetLinkMonitorResponseTime(error); } + void SetTrafficMonitor(TrafficMonitor *traffic_monitor) { + device_->set_traffic_monitor(traffic_monitor); // Passes ownership. + } + + void StartTrafficMonitor() { + device_->StartTrafficMonitor(); + } + + void StopTrafficMonitor() { + device_->StopTrafficMonitor(); + } + + void NetworkProblemDetected(int reason) { + device_->OnEncounterNetworkProblem(reason); + } + DeviceMockAdaptor *GetDeviceMockAdaptor() { return dynamic_cast<DeviceMockAdaptor *>(device_->adaptor_.get()); } @@ -696,6 +720,73 @@ EXPECT_FALSE(HasLinkMonitor()); } +TEST_F(DeviceTest, TrafficMonitor) { + scoped_refptr<MockConnection> connection( + new StrictMock<MockConnection>(&device_info_)); + MockManager manager(control_interface(), + dispatcher(), + metrics(), + glib()); + scoped_refptr<MockService> service( + new StrictMock<MockService>(control_interface(), + dispatcher(), + metrics(), + &manager)); + SelectService(service); + SetConnection(connection.get()); + MockTrafficMonitor *traffic_monitor = new StrictMock<MockTrafficMonitor>(); + SetTrafficMonitor(traffic_monitor); // Passes ownership. + SetManager(&manager); + + EXPECT_CALL(*device_, IsTrafficMonitorEnabled()).WillRepeatedly(Return(true)); + EXPECT_CALL(*traffic_monitor, Start()); + StartTrafficMonitor(); + EXPECT_CALL(*traffic_monitor, Stop()); + StopTrafficMonitor(); + Mock::VerifyAndClearExpectations(traffic_monitor); + + EXPECT_CALL(metrics_, NotifyNetworkProblemDetected(_, + Metrics::kNetworkProblemDNSFailure)).Times(1); + NetworkProblemDetected(TrafficMonitor::kNetworkProblemDNSFailure); + + // Verify traffic monitor not running when it is disabled. + traffic_monitor = new StrictMock<MockTrafficMonitor>(); + SetTrafficMonitor(traffic_monitor); + EXPECT_CALL(*device_, IsTrafficMonitorEnabled()) + .WillRepeatedly(Return(false)); + EXPECT_CALL(*traffic_monitor, Start()).Times(0); + StartTrafficMonitor(); + EXPECT_CALL(*traffic_monitor, Stop()).Times(0); + StopTrafficMonitor(); + +} + +TEST_F(DeviceTest, TrafficMonitorCancelledOnSelectService) { + scoped_refptr<MockConnection> connection( + new StrictMock<MockConnection>(&device_info_)); + MockManager manager(control_interface(), + dispatcher(), + metrics(), + glib()); + scoped_refptr<MockService> service( + new StrictMock<MockService>(control_interface(), + dispatcher(), + metrics(), + &manager)); + SelectService(service); + SetConnection(connection.get()); + MockTrafficMonitor *traffic_monitor = new StrictMock<MockTrafficMonitor>(); + SetTrafficMonitor(traffic_monitor); // Passes ownership. + EXPECT_CALL(*device_, IsTrafficMonitorEnabled()).WillRepeatedly(Return(true)); + SetManager(&manager); + EXPECT_CALL(*service, state()) + .WillOnce(Return(Service::kStateIdle)); + EXPECT_CALL(*service, SetState(_)); + EXPECT_CALL(*service, SetConnection(_)); + EXPECT_CALL(*traffic_monitor, Stop()); + SelectService(NULL); +} + TEST_F(DeviceTest, ShouldUseArpGateway) { EXPECT_FALSE(device_->ShouldUseArpGateway()); }
diff --git a/metrics.cc b/metrics.cc index a6c91c9..d42e2b3 100644 --- a/metrics.cc +++ b/metrics.cc
@@ -304,6 +304,10 @@ const char Metrics::kMetricFallbackDNSTestResult[] = "Network.Shill.FallbackDNSTestResult"; +// static +const char Metrics::kMetricNetworkProblemDetectedSuffix[] = + "NetworkProblemDetected"; + Metrics::Metrics(EventDispatcher *dispatcher) : dispatcher_(dispatcher), library_(&metrics_library_), @@ -1134,6 +1138,15 @@ kDNSTestResultMax); } +void Metrics::NotifyNetworkProblemDetected(Technology::Identifier technology_id, + int reason) { + string histogram = GetFullMetricName(kMetricNetworkProblemDetectedSuffix, + technology_id); + SendEnumToUMA(histogram, + reason, + kNetworkProblemMax); +} + bool Metrics::SendEnumToUMA(const string &name, int sample, int max) { SLOG(Metrics, 5) << "Sending enum " << name << " with value " << sample << ".";
diff --git a/metrics.h b/metrics.h index 58ea4fd..9abdd0e 100644 --- a/metrics.h +++ b/metrics.h
@@ -291,6 +291,13 @@ kDNSTestResultMax }; + // Network problem detected by traffic monitor. + enum NetworkProblem { + kNetworkProblemCongestedTCPTxQueue = 0, + kNetworkProblemDNSFailure, + kNetworkProblemMax + }; + static const char kMetricDisconnectSuffix[]; static const int kMetricDisconnectMax; static const int kMetricDisconnectMin; @@ -494,6 +501,9 @@ // DNS test result. static const char kMetricFallbackDNSTestResult[]; + // Network problem detected by traffic monitor + static const char kMetricNetworkProblemDetectedSuffix[]; + explicit Metrics(EventDispatcher *dispatcher); virtual ~Metrics(); @@ -683,6 +693,11 @@ // Notifies this object about the result of the fallback DNS test. virtual void NotifyFallbackDNSTestResult(int result); + // Notifies this object about a network problem detected on the currently + // connected network. + virtual void NotifyNetworkProblemDetected( + Technology::Identifier technology_id, int reason); + // Sends linear histogram data to UMA. virtual bool SendEnumToUMA(const std::string &name, int sample, int max);
diff --git a/metrics_unittest.cc b/metrics_unittest.cc index a32b2fc..111d8a4 100644 --- a/metrics_unittest.cc +++ b/metrics_unittest.cc
@@ -799,6 +799,15 @@ metrics_.NotifyFallbackDNSTestResult(Metrics::kDNSTestResultSuccess); } +TEST_F(MetricsTest, NotifyNetworkProblemDetected) { + EXPECT_CALL(library_, + SendEnumToUMA("Network.Shill.Wifi.NetworkProblemDetected", + Metrics::kNetworkProblemDNSFailure, + Metrics::kNetworkProblemMax)); + metrics_.NotifyNetworkProblemDetected(Technology::kWifi, + Metrics::kNetworkProblemDNSFailure); +} + #ifndef NDEBUG typedef MetricsTest MetricsDeathTest;
diff --git a/mock_metrics.h b/mock_metrics.h index e050a59..35087d7 100644 --- a/mock_metrics.h +++ b/mock_metrics.h
@@ -50,6 +50,8 @@ MOCK_METHOD2(NotifyUserInitiatedConnectionResult, void(const std::string &name, int result)); MOCK_METHOD1(NotifyFallbackDNSTestResult, void(int result)); + MOCK_METHOD2(NotifyNetworkProblemDetected, + void(Technology::Identifier technology_id, int reason)); private: DISALLOW_COPY_AND_ASSIGN(MockMetrics);
diff --git a/traffic_monitor.cc b/traffic_monitor.cc index 4bca373..1b623a3 100644 --- a/traffic_monitor.cc +++ b/traffic_monitor.cc
@@ -190,20 +190,22 @@ void TrafficMonitor::SampleTraffic() { SLOG(Link, 3) << __func__; + // Schedule the sample callback first, so it is possible for the network + // problem callback to stop the traffic monitor. + dispatcher_->PostDelayedTask(sample_traffic_callback_.callback(), + kSamplingIntervalMilliseconds); + if (IsCongestedTxQueues() && accummulated_congested_tx_queues_samples_ == kMinimumFailedSamplesToTrigger) { LOG(WARNING) << "Congested tx queues detected, out-of-credits?"; - outgoing_tcp_packets_not_routed_callback_.Run(); + network_problem_detected_callback_.Run(kNetworkProblemCongestedTxQueue); } else if (IsDnsFailing() && accummulated_dns_failures_samples_ == kMinimumFailedSamplesToTrigger) { LOG(WARNING) << "DNS queries failing, out-of-credits?"; - outgoing_tcp_packets_not_routed_callback_.Run(); + network_problem_detected_callback_.Run(kNetworkProblemDNSFailure); } - - dispatcher_->PostDelayedTask(sample_traffic_callback_.callback(), - kSamplingIntervalMilliseconds); } } // namespace shill
diff --git a/traffic_monitor.h b/traffic_monitor.h index 2f19876..4a6ba1a 100644 --- a/traffic_monitor.h +++ b/traffic_monitor.h
@@ -25,7 +25,14 @@ // and notifies an observer of various scenarios via callbacks. class TrafficMonitor { public: - typedef base::Closure TcpOutTrafficNotRoutedCallback; + // Network problem detected by traffic monitor. + enum NetworkProblem { + kNetworkProblemCongestedTxQueue=0, + kNetworkProblemDNSFailure, + kNetworkProblemMax + }; + + typedef base::Callback<void(int)> NetworkProblemDetectedCallback; TrafficMonitor(const DeviceRefPtr &device, EventDispatcher *dispatcher); virtual ~TrafficMonitor(); @@ -36,11 +43,12 @@ // Stops traffic monitoring on the selected device. virtual void Stop(); - // Sets the callback to invoke, if the traffic monitor detects that too many - // packets are failing to get transmitted over a TCP connection. - void set_tcp_out_traffic_not_routed_callback( - const TcpOutTrafficNotRoutedCallback &callback) { - outgoing_tcp_packets_not_routed_callback_ = callback; + // Sets the callback to invoke, if the traffic monitor detects a network + // problem, either too many packets are failing to get transmitted over a + // TCP connection or DNS is failing. + void set_network_problem_detected_callback( + const NetworkProblemDetectedCallback &callback) { + network_problem_detected_callback_ = callback; } private: @@ -121,9 +129,11 @@ // of the network interface. base::CancelableClosure sample_traffic_callback_; - // Callback to invoke when we detect that the send queue has been increasing - // on an ESTABLISHED TCP connection through the network interface. - TcpOutTrafficNotRoutedCallback outgoing_tcp_packets_not_routed_callback_; + // Callback to invoke when we detect a network problem. Possible network + // problems that can be detected are congested TCP TX queue and DNS failure. + // Refer to enum NetworkProblem for all possible network problems that can be + // detected by Traffic Monitor. + NetworkProblemDetectedCallback network_problem_detected_callback_; // Reads and parses socket information from the system. scoped_ptr<SocketInfoReader> socket_info_reader_;
diff --git a/traffic_monitor_unittest.cc b/traffic_monitor_unittest.cc index e4ee9a5..225f289 100644 --- a/traffic_monitor_unittest.cc +++ b/traffic_monitor_unittest.cc
@@ -63,7 +63,7 @@ remote_addr_.SetAddressFromString(kRemoteIpAddr); } - MOCK_METHOD0(OnNoOutgoingPackets, void()); + MOCK_METHOD1(OnNoOutgoingPackets, void(int)); protected: virtual void SetUp() { @@ -314,20 +314,21 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); // Mimic same queue length by using same mock socket info. - EXPECT_CALL(*this, OnNoOutgoingPackets()); + EXPECT_CALL(*this, OnNoOutgoingPackets( + TrafficMonitor::kNetworkProblemCongestedTxQueue)); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); // Perform another sampling pass and make sure the callback is only // triggered once. - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); } @@ -343,9 +344,9 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); @@ -360,7 +361,8 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - EXPECT_CALL(*this, OnNoOutgoingPackets()); + EXPECT_CALL(*this, OnNoOutgoingPackets( + TrafficMonitor::kNetworkProblemCongestedTxQueue)); monitor_.SampleTraffic(); } @@ -376,9 +378,9 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); @@ -393,7 +395,7 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); @@ -408,7 +410,8 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - EXPECT_CALL(*this, OnNoOutgoingPackets()); + EXPECT_CALL(*this, OnNoOutgoingPackets( + TrafficMonitor::kNetworkProblemCongestedTxQueue)); monitor_.SampleTraffic(); } @@ -424,9 +427,9 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); socket_infos.clear(); @@ -456,9 +459,9 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); socket_infos.clear(); @@ -479,9 +482,9 @@ 0, SocketInfo::kTimerStateRetransmitTimerPending)); SetupMockSocketInfos(socket_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); socket_infos.clear(); @@ -509,11 +512,11 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); // Make sure the no routing event is not fired before the threshold is // exceeded. - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -521,12 +524,13 @@ Mock::VerifyAndClearExpectations(this); // This call should cause the threshold to exceed. - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(1); + EXPECT_CALL(*this, OnNoOutgoingPackets( + TrafficMonitor::kNetworkProblemDNSFailure)).Times(1); monitor_.SampleTraffic(); Mock::VerifyAndClearExpectations(this); // Make sure the event is only fired once. - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); } @@ -540,9 +544,9 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -559,9 +563,9 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -578,9 +582,9 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -596,7 +600,7 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); monitor_.SampleTraffic(); EXPECT_EQ(0, monitor_.accummulated_dns_failures_samples_); } @@ -611,9 +615,9 @@ remote_addr_, TrafficMonitor::kDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -630,9 +634,9 @@ remote_addr_, TrafficMonitor::kDnsPort, remote_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -650,9 +654,9 @@ remote_addr_, TrafficMonitor::kDnsPort, remote_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic(); @@ -670,9 +674,9 @@ remote_addr_, kNonDnsPort, local_addr_, TrafficMonitorTest::kLocalPort1)); SetupMockConnectionInfos(connection_infos); - monitor_.set_tcp_out_traffic_not_routed_callback( + monitor_.set_network_problem_detected_callback( Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); - EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); + EXPECT_CALL(*this, OnNoOutgoingPackets(_)).Times(0); for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; ++count) { monitor_.SampleTraffic();
diff --git a/wifi.cc b/wifi.cc index 51b05c7..8e5dcc1 100644 --- a/wifi.cc +++ b/wifi.cc
@@ -2581,6 +2581,11 @@ return ""; } +// Traffic monitor is enabled for wifi. +bool WiFi::IsTrafficMonitorEnabled() const { + return true; +} + bool WiFi::ResolvePeerMacAddress(const string &input, string *output, Error *error) { if (!WiFiEndpoint::MakeHardwareAddressFromString(input).empty()) {
diff --git a/wifi.h b/wifi.h index 1747676..440e61d 100644 --- a/wifi.h +++ b/wifi.h
@@ -216,6 +216,10 @@ virtual std::string PerformTDLSOperation(const std::string &operation, const std::string &peer, Error *error) override; + + // Overridden from Device superclass. + virtual bool IsTrafficMonitorEnabled() const override; + private: enum ScanMethod { kScanMethodNone,