Home | History | Annotate | Download | only in wifi
      1 //
      2 // Copyright (C) 2014 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #ifndef SHILL_WIFI_MAC80211_MONITOR_H_
     18 #define SHILL_WIFI_MAC80211_MONITOR_H_
     19 
     20 #include <time.h>
     21 
     22 #include <string>
     23 #include <vector>
     24 
     25 #include <base/callback.h>
     26 #include <base/cancelable_callback.h>
     27 #include <base/files/file_path.h>
     28 #include <base/macros.h>
     29 #include <base/memory/weak_ptr.h>
     30 #include <gtest/gtest_prod.h>  // for FRIEND_TEST
     31 
     32 namespace shill {
     33 
     34 class EventDispatcher;
     35 class Metrics;
     36 class Time;
     37 
     38 class Mac80211Monitor {
     39  public:
     40   struct QueueState {
     41     QueueState(size_t queue_number_in,
     42                uint32_t stop_flags_in,
     43                size_t queue_length_in)
     44     : queue_number(queue_number_in), stop_flags(stop_flags_in),
     45       queue_length(queue_length_in) {}
     46 
     47     size_t queue_number;
     48     uint32_t stop_flags;
     49     size_t queue_length;
     50   };
     51 
     52   Mac80211Monitor(EventDispatcher* dispatcher,
     53                   const std::string& link_name,
     54                   size_t queue_length_limit,
     55                   const base::Closure& on_repair_callback,
     56                   Metrics* metrics);
     57   virtual ~Mac80211Monitor();
     58 
     59   virtual void Start(const std::string& phy_name);
     60   virtual void Stop();
     61   virtual void UpdateConnectedState(bool new_state);
     62 
     63   const std::string& link_name() const { return link_name_; }
     64 
     65  private:
     66   friend class Mac80211MonitorTest;
     67   FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckMultipleReasons);
     68   FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckMultipleQueues);
     69   FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckNotStuck);
     70   FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckQueueLength);
     71   FRIEND_TEST(Mac80211MonitorTest,
     72               CheckAreQueuesStuckQueueLengthIgnoresUnstopped);
     73   FRIEND_TEST(Mac80211MonitorTest, CheckAreQueuesStuckSingleReason);
     74   FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateBadInput);
     75   FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateSimple);
     76   FRIEND_TEST(Mac80211MonitorTest, ParseQueueStateStopped);
     77 
     78   static const size_t kMaxQueueStateSizeBytes;
     79   static const char kQueueStatusPathFormat[];
     80   static const char kWakeQueuesPathFormat[];
     81   static const time_t kQueueStatePollIntervalSeconds;
     82   static const time_t kMinimumTimeBetweenWakesSeconds;
     83 
     84   // Values must be kept in sync with ieee80211_i.h.
     85   enum QueueStopReason {
     86     kStopReasonDriver,
     87     kStopReasonPowerSave,
     88     kStopReasonChannelSwitch,
     89     kStopReasonAggregation,
     90     kStopReasonSuspend,
     91     kStopReasonBufferAdd,
     92     kStopReasonChannelTypeChange,
     93     kStopReasonMax = kStopReasonChannelTypeChange
     94   };
     95   enum QueueStopFlag {
     96     kStopFlagDriver = 1 << kStopReasonDriver,
     97     kStopFlagPowerSave = 1 << kStopReasonPowerSave,
     98     kStopFlagChannelSwitch = 1 << kStopReasonChannelSwitch,
     99     kStopFlagAggregation = 1 << kStopReasonAggregation,
    100     kStopFlagSuspend = 1 << kStopReasonSuspend,
    101     kStopFlagBufferAdd = 1 << kStopReasonBufferAdd,
    102     kStopFlagChannelTypeChange = 1 << kStopReasonChannelTypeChange,
    103     kStopFlagInvalid
    104   };
    105 
    106   void StartTimer();
    107   void StopTimer();
    108 
    109   // Check if queues need to be woken. If so, and we haven't woken them
    110   // too recently, then wake them now.
    111   void WakeQueuesIfNeeded();
    112 
    113   // Check |queue_states|, to determine if any queues are stuck.
    114   // Returns a bitmask of QueueStopFlags. A flag will be set if
    115   // any of the queues has that flag set, and is non-empty.
    116   // A return value if 0 indicates no queues are stuck.
    117   uint32_t CheckAreQueuesStuck(const std::vector<QueueState>& queue_states);
    118 
    119   static std::vector<QueueState> ParseQueueState(
    120       const std::string& state_string);
    121   static QueueStopFlag GetFlagForReason(QueueStopReason reason);
    122 
    123   Time* time_;  // for mocking in tests
    124   EventDispatcher* dispatcher_;
    125   const std::string link_name_;
    126   size_t queue_length_limit_;
    127   base::Closure on_repair_callback_;
    128   Metrics* metrics_;
    129   std::string phy_name_;
    130   time_t last_woke_queues_monotonic_seconds_;
    131   bool is_running_;
    132   bool have_ever_read_queue_state_file_;
    133   base::FilePath queue_state_file_path_;
    134   base::FilePath wake_queues_file_path_;
    135   base::CancelableClosure check_queues_callback_;
    136   bool is_device_connected_;
    137   base::WeakPtrFactory<Mac80211Monitor> weak_ptr_factory_;  // keep last
    138 
    139   DISALLOW_COPY_AND_ASSIGN(Mac80211Monitor);
    140 };
    141 
    142 }  // namespace shill
    143 
    144 #endif  // SHILL_WIFI_MAC80211_MONITOR_H_
    145