//
// 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_