144 lines
4.7 KiB
C++
144 lines
4.7 KiB
C++
//
|
|
// 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_
|