C++程序  |  145行  |  4.74 KB

//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#ifndef SHILL_WIFI_MAC80211_MONITOR_H_
#define SHILL_WIFI_MAC80211_MONITOR_H_

#include <time.h>

#include <string>
#include <vector>

#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <base/files/file_path.h>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <gtest/gtest_prod.h>  // for FRIEND_TEST

namespace shill {

class EventDispatcher;
class Metrics;
class Time;

class Mac80211Monitor {
 public:
  struct QueueState {
    QueueState(size_t queue_number_in,
               uint32_t stop_flags_in,
               size_t queue_length_in)
    : queue_number(queue_number_in), stop_flags(stop_flags_in),
      queue_length(queue_length_in) {}

    size_t queue_number;
    uint32_t stop_flags;
    size_t queue_length;
  };

  Mac80211Monitor(EventDispatcher* dispatcher,
                  const std::string& link_name,
                  size_t queue_length_limit,
                  const base::Closure& on_repair_callback,
                  Metrics* metrics);
  virtual ~Mac80211Monitor();

  virtual void Start(const std::string& phy_name);
  virtual void Stop();
  virtual void UpdateConnectedState(bool new_state);

  const std::string& link_name() const { return link_name_; }

 private:
  friend class Mac80211MonitorTest;
  FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckMultipleReasons);
  FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues);
  FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckNotStuck);
  FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength);
  FRIEND_TEST(Mac80211MonitorTest,
              CheckAreQueuesStuckQueueLengthIgnoresUnstopped);
  FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason);
  FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateBadInput);
  FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateSimple);
  FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateStopped);

  static const size_t kMaxQueueStateSizeBytes;
  static const char kQueueStatusPathFormat[];
  static const char kWakeQueuesPathFormat[];
  static const time_t kQueueStatePollIntervalSeconds;
  static const time_t kMinimumTimeBetweenWakesSeconds;

  // Values must be kept in sync with ieee80211_i.h.
  enum QueueStopReason {
    kStopReasonDriver,
    kStopReasonPowerSave,
    kStopReasonChannelSwitch,
    kStopReasonAggregation,
    kStopReasonSuspend,
    kStopReasonBufferAdd,
    kStopReasonChannelTypeChange,
    kStopReasonMax = kStopReasonChannelTypeChange
  };
  enum QueueStopFlag {
    kStopFlagDriver = 1 << kStopReasonDriver,
    kStopFlagPowerSave = 1 << kStopReasonPowerSave,
    kStopFlagChannelSwitch = 1 << kStopReasonChannelSwitch,
    kStopFlagAggregation = 1 << kStopReasonAggregation,
    kStopFlagSuspend = 1 << kStopReasonSuspend,
    kStopFlagBufferAdd = 1 << kStopReasonBufferAdd,
    kStopFlagChannelTypeChange = 1 << kStopReasonChannelTypeChange,
    kStopFlagInvalid
  };

  void StartTimer();
  void StopTimer();

  // Check if queues need to be woken. If so, and we haven't woken them
  // too recently, then wake them now.
  void WakeQueuesIfNeeded();

  // Check |queue_states|, to determine if any queues are stuck.
  // Returns a bitmask of QueueStopFlags. A flag will be set if
  // any of the queues has that flag set, and is non-empty.
  // A return value if 0 indicates no queues are stuck.
  uint32_t CheckAreQueuesStuck(const std::vector<QueueState>& queue_states);

  static std::vector<QueueState> ParseQueueState(
      const std::string& state_string);
  static QueueStopFlag GetFlagForReason(QueueStopReason reason);

  Time* time_;  // for mocking in tests
  EventDispatcher* dispatcher_;
  const std::string link_name_;
  size_t queue_length_limit_;
  base::Closure on_repair_callback_;
  Metrics* metrics_;
  std::string phy_name_;
  time_t last_woke_queues_monotonic_seconds_;
  bool is_running_;
  bool have_ever_read_queue_state_file_;
  base::FilePath queue_state_file_path_;
  base::FilePath wake_queues_file_path_;
  base::CancelableClosure check_queues_callback_;
  bool is_device_connected_;
  base::WeakPtrFactory<Mac80211Monitor> weak_ptr_factory_;  // keep last

  DISALLOW_COPY_AND_ASSIGN(Mac80211Monitor);
};

}  // namespace shill

#endif  // SHILL_WIFI_MAC80211_MONITOR_H_