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 {
QueueStateQueueState41     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 
link_name()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