1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2013 The Android Open Source Project
3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License");
5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License.
6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at
7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//      http://www.apache.org/licenses/LICENSE-2.0
9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software
11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS,
12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and
14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License.
15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu//
16b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
17b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan#include "shill/traffic_monitor.h"
18b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
19b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan#include <base/bind.h>
20a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/stringprintf.h>
21fa7960effd89d27830ee742c22cf825e3c126097Thieu Le#include <netinet/in.h>
22b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
23b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan#include "shill/device.h"
24b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan#include "shill/device_info.h"
25b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan#include "shill/event_dispatcher.h"
260302666245cea4a54dac13a9b6b11ddf04048143Thieu Le#include "shill/logging.h"
270302666245cea4a54dac13a9b6b11ddf04048143Thieu Le#include "shill/socket_info_reader.h"
28b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
290302666245cea4a54dac13a9b6b11ddf04048143Thieu Leusing base::StringPrintf;
300302666245cea4a54dac13a9b6b11ddf04048143Thieu Leusing std::string;
310302666245cea4a54dac13a9b6b11ddf04048143Thieu Leusing std::vector;
32b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
330302666245cea4a54dac13a9b6b11ddf04048143Thieu Lenamespace shill {
34b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
35c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging {
36c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kLink;
371a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartstatic string ObjectID(Device* d) { return d->link_name(); }
38c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein}
39c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein
400302666245cea4a54dac13a9b6b11ddf04048143Thieu Le// static
417fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst uint16_t TrafficMonitor::kDnsPort = 53;
427fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst int64_t TrafficMonitor::kDnsTimedOutThresholdSeconds = 15;
430302666245cea4a54dac13a9b6b11ddf04048143Thieu Leconst int TrafficMonitor::kMinimumFailedSamplesToTrigger = 2;
447fab89734d88724a288e96a9996b15548c5294c7Ben Chanconst int64_t TrafficMonitor::kSamplingIntervalMilliseconds = 5000;
45b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
461a212a6b98b22ad1d69652bb26a9e94138635476Paul StewartTrafficMonitor::TrafficMonitor(const DeviceRefPtr& device,
471a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart                               EventDispatcher* dispatcher)
48b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan    : device_(device),
49b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan      dispatcher_(dispatcher),
500302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      socket_info_reader_(new SocketInfoReader),
51fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      accummulated_congested_tx_queues_samples_(0),
52fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      connection_info_reader_(new ConnectionInfoReader),
53fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      accummulated_dns_failures_samples_(0) {
54b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}
55b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
56b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen ChanTrafficMonitor::~TrafficMonitor() {
57b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  Stop();
58b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}
59b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
60b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chanvoid TrafficMonitor::Start() {
610951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 2) << __func__;
62b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  Stop();
63b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
64b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  sample_traffic_callback_.Reset(base::Bind(&TrafficMonitor::SampleTraffic,
65b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan                                            base::Unretained(this)));
66b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  dispatcher_->PostDelayedTask(sample_traffic_callback_.callback(),
67b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan                               kSamplingIntervalMilliseconds);
68b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}
69b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
70b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chanvoid TrafficMonitor::Stop() {
710951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 2) << __func__;
72b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  sample_traffic_callback_.Cancel();
73fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  ResetCongestedTxQueuesStats();
74fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  ResetDnsFailingStats();
75fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
76fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
77fa7960effd89d27830ee742c22cf825e3c126097Thieu Levoid TrafficMonitor::ResetCongestedTxQueuesStats() {
78fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  accummulated_congested_tx_queues_samples_ = 0;
79fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
80fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
81fa7960effd89d27830ee742c22cf825e3c126097Thieu Levoid TrafficMonitor::ResetCongestedTxQueuesStatsWithLogging() {
820951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 2) << __func__ << ": Tx-queues decongested";
83fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  ResetCongestedTxQueuesStats();
84b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}
85b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
860302666245cea4a54dac13a9b6b11ddf04048143Thieu Levoid TrafficMonitor::BuildIPPortToTxQueueLength(
871a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart    const vector<SocketInfo>& socket_infos,
881a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart    IPPortToTxQueueLengthMap* tx_queue_lengths) {
890951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 3) << __func__;
900302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  string device_ip_address = device_->ipconfig()->properties().address;
911a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart  for (const auto& info : socket_infos) {
920951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko    SLOG(device_.get(), 4) << "SocketInfo(IP="
930951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << info.local_ip_address().ToString()
940951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << ", TX=" << info.transmit_queue_value()
950951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << ", State=" << info.connection_state()
960951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << ", TimerState=" << info.timer_state();
976db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    if (info.local_ip_address().ToString() != device_ip_address ||
986db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart        info.transmit_queue_value() == 0 ||
996db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart        info.connection_state() != SocketInfo::kConnectionStateEstablished ||
1006db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart        (info.timer_state() != SocketInfo::kTimerStateRetransmitTimerPending &&
1016db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart         info.timer_state() !=
102d42d8ec85a9a1bdc406870b75d1b9e266fbaaa02Arman Uguray            SocketInfo::kTimerStateZeroWindowProbeTimerPending)) {
1030951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko      SLOG(device_.get(), 4) << "Connection Filtered.";
1040302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      continue;
105d42d8ec85a9a1bdc406870b75d1b9e266fbaaa02Arman Uguray    }
1060951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko    SLOG(device_.get(), 3) << "Monitoring connection: TX="
1070951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << info.transmit_queue_value()
1080951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                           << " TimerState=" << info.timer_state();
1090302666245cea4a54dac13a9b6b11ddf04048143Thieu Le
1100302666245cea4a54dac13a9b6b11ddf04048143Thieu Le    string local_ip_port =
1110302666245cea4a54dac13a9b6b11ddf04048143Thieu Le        StringPrintf("%s:%d",
1126db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart                     info.local_ip_address().ToString().c_str(),
1136db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart                     info.local_port());
1146db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart    (*tx_queue_lengths)[local_ip_port] = info.transmit_queue_value();
115b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  }
1160302666245cea4a54dac13a9b6b11ddf04048143Thieu Le}
117b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
118fa7960effd89d27830ee742c22cf825e3c126097Thieu Lebool TrafficMonitor::IsCongestedTxQueues() {
1190951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 4) << __func__;
1200302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  vector<SocketInfo> socket_infos;
1210302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  if (!socket_info_reader_->LoadTcpSocketInfo(&socket_infos) ||
1220302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      socket_infos.empty()) {
1230951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko    SLOG(device_.get(), 3) << __func__ << ": Empty socket info";
124fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    ResetCongestedTxQueuesStatsWithLogging();
125fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    return false;
1260302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  }
127fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  bool congested_tx_queues = true;
1280302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  IPPortToTxQueueLengthMap curr_tx_queue_lengths;
1290302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  BuildIPPortToTxQueueLength(socket_infos, &curr_tx_queue_lengths);
1300302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  if (curr_tx_queue_lengths.empty()) {
1310951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko    SLOG(device_.get(), 3) << __func__ << ": No interesting socket info";
132fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    ResetCongestedTxQueuesStatsWithLogging();
1330302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  } else {
1341a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart    for (const auto& length_entry : old_tx_queue_lengths_) {
1350302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      IPPortToTxQueueLengthMap::iterator curr_tx_queue_it =
1366db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          curr_tx_queue_lengths.find(length_entry.first);
1370302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      if (curr_tx_queue_it == curr_tx_queue_lengths.end() ||
1386db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          curr_tx_queue_it->second < length_entry.second) {
1390302666245cea4a54dac13a9b6b11ddf04048143Thieu Le        congested_tx_queues = false;
140f84a4242b4218dc375449ab2d68085226f43ce5bArman Uguray        // TODO(armansito): If we had a false positive earlier, we may
141f84a4242b4218dc375449ab2d68085226f43ce5bArman Uguray        // want to correct it here by invoking a "connection back to normal
142f84a4242b4218dc375449ab2d68085226f43ce5bArman Uguray        // callback", so that the OutOfCredits property can be set to
143f84a4242b4218dc375449ab2d68085226f43ce5bArman Uguray        // false.
1440302666245cea4a54dac13a9b6b11ddf04048143Thieu Le        break;
1450302666245cea4a54dac13a9b6b11ddf04048143Thieu Le      }
1460302666245cea4a54dac13a9b6b11ddf04048143Thieu Le    }
147fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    if (congested_tx_queues) {
148fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      ++accummulated_congested_tx_queues_samples_;
1490951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko      SLOG(device_.get(), 2) << __func__
1500951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                             << ": Congested tx-queues detected ("
1510951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                             << accummulated_congested_tx_queues_samples_
1520951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                             << ")";
153b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan    }
154b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan  }
1550302666245cea4a54dac13a9b6b11ddf04048143Thieu Le  old_tx_queue_lengths_ = curr_tx_queue_lengths;
156b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
157fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  return congested_tx_queues;
158fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
159fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
160fa7960effd89d27830ee742c22cf825e3c126097Thieu Levoid TrafficMonitor::ResetDnsFailingStats() {
161fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  accummulated_dns_failures_samples_ = 0;
162fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
163fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
164fa7960effd89d27830ee742c22cf825e3c126097Thieu Levoid TrafficMonitor::ResetDnsFailingStatsWithLogging() {
1650951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 2) << __func__ << ": DNS queries restored";
166fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  ResetDnsFailingStats();
167fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
168fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
169fa7960effd89d27830ee742c22cf825e3c126097Thieu Lebool TrafficMonitor::IsDnsFailing() {
1700951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 4) << __func__;
171fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  vector<ConnectionInfo> connection_infos;
172fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  if (!connection_info_reader_->LoadConnectionInfo(&connection_infos) ||
173fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      connection_infos.empty()) {
1740951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko    SLOG(device_.get(), 3) << __func__ << ": Empty connection info";
175fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  } else {
176fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // The time-to-expire counter is used to determine when a DNS request
177fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // has timed out.  This counter is the number of seconds remaining until
178fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // the entry is removed from the system IP connection tracker.  The
179fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // default time is 30 seconds.  This is too long of a wait.  Instead, we
180fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // want to time out at |kDnsTimedOutThresholdSeconds|.  Unfortunately,
181fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // we cannot simply look for entries less than
182fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // |kDnsTimedOutThresholdSeconds| because we will count the entry
183fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // multiple times once its time-to-expire is less than
184fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // |kDnsTimedOutThresholdSeconds|.  To ensure that we only count an
185fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // entry once, we look for entries in this time window between
186fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    // |kDnsTimedOutThresholdSeconds| and |kDnsTimedOutLowerThresholdSeconds|.
1877fab89734d88724a288e96a9996b15548c5294c7Ben Chan    const int64_t kDnsTimedOutLowerThresholdSeconds =
188fa7960effd89d27830ee742c22cf825e3c126097Thieu Le        kDnsTimedOutThresholdSeconds - kSamplingIntervalMilliseconds / 1000;
189fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    string device_ip_address = device_->ipconfig()->properties().address;
1901a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart    for (const auto& info : connection_infos) {
1916db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart      if (info.protocol() != IPPROTO_UDP ||
1926db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          info.time_to_expire_seconds() > kDnsTimedOutThresholdSeconds ||
1936db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          info.time_to_expire_seconds() <= kDnsTimedOutLowerThresholdSeconds ||
1946db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          !info.is_unreplied() ||
1956db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          info.original_source_ip_address().ToString() != device_ip_address ||
1966db7b24348e69639e19cd6c408388b10d6ee54fePaul Stewart          info.original_destination_port() != kDnsPort)
197fa7960effd89d27830ee742c22cf825e3c126097Thieu Le        continue;
198fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
199fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      ++accummulated_dns_failures_samples_;
2000951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko      SLOG(device_.get(), 2) << __func__
2010951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                             << ": DNS failures detected ("
2020951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko                             << accummulated_dns_failures_samples_ << ")";
203fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      return true;
204fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    }
205fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  }
206fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  ResetDnsFailingStatsWithLogging();
207fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  return false;
208fa7960effd89d27830ee742c22cf825e3c126097Thieu Le}
209fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
210fa7960effd89d27830ee742c22cf825e3c126097Thieu Levoid TrafficMonitor::SampleTraffic() {
2110951ccbfca977a9cf218b2e4308aa26fb4d06ef9Alex Vakulenko  SLOG(device_.get(), 3) << __func__;
212fa7960effd89d27830ee742c22cf825e3c126097Thieu Le
213dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu  // Schedule the sample callback first, so it is possible for the network
214dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu  // problem callback to stop the traffic monitor.
215dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu  dispatcher_->PostDelayedTask(sample_traffic_callback_.callback(),
216dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu                               kSamplingIntervalMilliseconds);
217dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu
218fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  if (IsCongestedTxQueues() &&
219fa7960effd89d27830ee742c22cf825e3c126097Thieu Le      accummulated_congested_tx_queues_samples_ ==
220fa7960effd89d27830ee742c22cf825e3c126097Thieu Le          kMinimumFailedSamplesToTrigger) {
221fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    LOG(WARNING) << "Congested tx queues detected, out-of-credits?";
222dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu    network_problem_detected_callback_.Run(kNetworkProblemCongestedTxQueue);
223fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  } else if (IsDnsFailing() &&
224fa7960effd89d27830ee742c22cf825e3c126097Thieu Le             accummulated_dns_failures_samples_ ==
225fa7960effd89d27830ee742c22cf825e3c126097Thieu Le                 kMinimumFailedSamplesToTrigger) {
226fa7960effd89d27830ee742c22cf825e3c126097Thieu Le    LOG(WARNING) << "DNS queries failing, out-of-credits?";
227dc335f81a9d0ffe8efd02a96d3cd17399a06e61ePeter Qiu    network_problem_detected_callback_.Run(kNetworkProblemDNSFailure);
228fa7960effd89d27830ee742c22cf825e3c126097Thieu Le  }
229b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}
230b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan
231b061f89e7088c7fba50b49ee5ac876619c9e8a7eBen Chan}  // namespace shill
232