blob: ba4207acd0f44686ab8758a3577d92b4b923566b [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GARNET_DRIVERS_WLAN_WLAN_MINSTREL_H_
#define GARNET_DRIVERS_WLAN_WLAN_MINSTREL_H_
#include "probe_sequence.h"
#include <wlan/common/macaddr.h>
#include <wlan/common/tx_vector.h>
#include <wlan/mlme/client/station.h>
#include <wlan/mlme/timer_manager.h>
#include <wlan/protocol/info.h>
#include <wlan/protocol/mac.h>
#include <fbl/unique_ptr.h>
#include <zx/time.h>
#include <fuchsia/wlan/minstrel/cpp/fidl.h>
#include <array>
#include <unordered_map>
#include <unordered_set>
namespace wlan {
static constexpr uint16_t kMinstrelFrameLength = 1400; // bytes
static constexpr float kMinstrelExpWeight = 0.75; // Used to calculate moving average throughput
static constexpr float kMinstrelProbabilityThreshold =
0.9; // If probability is past this level, only consider throughput
static constexpr uint8_t kProbeInterval = 16; // normal packets to sent between two probe packets
// LINT.IfChange
struct TxStats {
tx_vec_idx_t tx_vector_idx;
zx::duration perfect_tx_time;
size_t success_cur = 0; // successful transmissions since last update.
size_t attempts_cur = 0; // transmission attempts since last update.
float probability =
1.0f - kMinstrelProbabilityThreshold; // Moving Average Probability of success.
float cur_tp = 0.0; // Expected average throughput.
size_t success_total = 0; // cumulative success counts.
size_t attempts_total = 0; // cumulative attempts.
size_t probes_total = 0;
// Delay probe if probability < (1 - kMinstrelProbabilityThreshold).
uint8_t probe_cycles_skipped = 0;
constexpr bool PhyPreferredOver(const TxStats& other) const;
constexpr bool ThroughputHigherThan(const TxStats& other) const;
constexpr bool ProbabilityHigherThan(const TxStats& other) const;
::fuchsia::wlan::minstrel::StatsEntry ToFidl() const;
};
struct Peer {
common::MacAddr addr;
bool is_ht = false;
bool is_vht = false;
std::unique_ptr<std::mutex> update_lock = std::make_unique<std::mutex>();
std::unordered_map<tx_vec_idx_t, TxStats> tx_stats_map __TA_GUARDED(*update_lock);
std::unordered_set<tx_vec_idx_t> basic_rates;
tx_vec_idx_t basic_highest = kErpStartIdx; // will be replaced when assoc_ctx is parsed.
tx_vec_idx_t basic_max_probability = kErpStartIdx; // optimality based on success probability
// Index of the optimal tx vector
tx_vec_idx_t max_tp = kInvalidTxVectorIdx; // optimality based on expected throughput.
tx_vec_idx_t max_probability = kInvalidTxVectorIdx; // optimality based on success probability.
ProbeSequence::Entry probe_entry;
uint8_t num_probe_cycles_done = 0; // +1 when all tx_vectors are probed at least once.
uint8_t num_pkt_until_next_probe = kProbeInterval - 1;
size_t probes;
};
// LINT.ThenChange(//garnet/public/fidl/fuchsia.wlan.minstrel/wlan_minstrel.fidl)
class MinstrelRateSelector {
public:
MinstrelRateSelector(fbl::unique_ptr<Timer>&& timer, ProbeSequence&& probe_sequence,
zx::duration update_interval);
void AddPeer(const wlan_assoc_ctx_t& assoc_ctx);
void RemovePeer(const common::MacAddr& addr);
// Called after every tx packet.
void HandleTxStatusReport(const wlan_tx_status_t& tx_status);
bool HandleTimeout();
tx_vec_idx_t GetTxVectorIdx(const FrameControl& fc, const common::MacAddr& peer_addr,
uint32_t flags);
zx_status_t GetListToFidl(::fuchsia::wlan::minstrel::Peers* peers_fidl) const;
zx_status_t GetStatsToFidl(const common::MacAddr& peer_addr,
::fuchsia::wlan::minstrel::Peer* peer_fidl) const;
bool IsActive() const;
private:
void UpdateStats();
Peer* GetPeer(const common::MacAddr& addr);
const Peer* GetPeer(const common::MacAddr& addr) const;
// Holds MAC addresses of peers with at least one status report but has not been processed.
std::unordered_set<common::MacAddr, common::MacAddrHasher> outdated_peers_;
std::unordered_map<common::MacAddr, Peer, common::MacAddrHasher> peer_map_;
TimerManager<> timer_mgr_;
TimeoutId next_update_;
const ProbeSequence probe_sequence_;
const zx::duration update_interval_;
};
ProbeSequence RandomProbeSequence();
namespace debug {
std::string Describe(const TxStats& tx_stats);
} // namespace debug
} // namespace wlan
#endif // GARNET_DRIVERS_WLAN_WLAN_MINSTREL_H_