mac80211: export the expected throughput
Add get_expected_throughput() API to mac80211 so that each driver can implement its own version based on the RC algorithm they are using (might be using an HW RC algo). The API returns a value expressed in Kbps. Also, add the new get_expected_throughput() member to the rate_control_ops structure in order to be able to query the RC algorithm (this patch provides an implementation of this API for both minstrel and minstrel_ht). The related member in the station_info object is now filled accordingly when dumping a station. Cc: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
867d849fc8
commit
cca674d47e
|
@ -2769,6 +2769,10 @@ enum ieee80211_roc_type {
|
|||
* information in bss_conf is set up and the beacon can be retrieved. A
|
||||
* channel context is bound before this is called.
|
||||
* @leave_ibss: Leave the IBSS again.
|
||||
*
|
||||
* @get_expected_throughput: extract the expected throughput towards the
|
||||
* specified station. The returned value is expressed in Kbps. It returns 0
|
||||
* if the RC algorithm does not have proper data to provide.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
void (*tx)(struct ieee80211_hw *hw,
|
||||
|
@ -2962,6 +2966,7 @@ struct ieee80211_ops {
|
|||
|
||||
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -4535,6 +4540,8 @@ struct rate_control_ops {
|
|||
void (*add_sta_debugfs)(void *priv, void *priv_sta,
|
||||
struct dentry *dir);
|
||||
void (*remove_sta_debugfs)(void *priv, void *priv_sta);
|
||||
|
||||
u32 (*get_expected_throughput)(void *priv_sta);
|
||||
};
|
||||
|
||||
static inline int rate_supported(struct ieee80211_sta *sta,
|
||||
|
|
|
@ -472,8 +472,10 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct rate_control_ref *ref = local->rate_ctrl;
|
||||
struct timespec uptime;
|
||||
u64 packets = 0;
|
||||
u32 thr = 0;
|
||||
int i, ac;
|
||||
|
||||
sinfo->generation = sdata->local->sta_generation;
|
||||
|
@ -587,6 +589,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
|
||||
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER))
|
||||
sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER);
|
||||
|
||||
/* check if the driver has a SW RC implementation */
|
||||
if (ref && ref->ops->get_expected_throughput)
|
||||
thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv);
|
||||
else
|
||||
thr = drv_get_expected_throughput(local, &sta->sta);
|
||||
|
||||
if (thr != 0) {
|
||||
sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT;
|
||||
sinfo->expected_throughput = thr;
|
||||
}
|
||||
}
|
||||
|
||||
static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
|
||||
|
|
|
@ -1156,4 +1156,17 @@ static inline void drv_leave_ibss(struct ieee80211_local *local,
|
|||
trace_drv_return_void(local);
|
||||
}
|
||||
|
||||
static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
u32 ret = 0;
|
||||
|
||||
trace_drv_get_expected_throughput(sta);
|
||||
if (local->ops->get_expected_throughput)
|
||||
ret = local->ops->get_expected_throughput(sta);
|
||||
trace_drv_return_u32(local, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
|
|
@ -657,6 +657,17 @@ minstrel_free(void *priv)
|
|||
kfree(priv);
|
||||
}
|
||||
|
||||
static u32 minstrel_get_expected_throughput(void *priv_sta)
|
||||
{
|
||||
struct minstrel_sta_info *mi = priv_sta;
|
||||
int idx = mi->max_tp_rate[0];
|
||||
|
||||
/* convert pkt per sec in kbps (1200 is the average pkt size used for
|
||||
* computing cur_tp
|
||||
*/
|
||||
return MINSTREL_TRUNC(mi->r[idx].cur_tp) * 1200 * 8 / 1024;
|
||||
}
|
||||
|
||||
const struct rate_control_ops mac80211_minstrel = {
|
||||
.name = "minstrel",
|
||||
.tx_status = minstrel_tx_status,
|
||||
|
@ -670,6 +681,7 @@ const struct rate_control_ops mac80211_minstrel = {
|
|||
.add_sta_debugfs = minstrel_add_sta_debugfs,
|
||||
.remove_sta_debugfs = minstrel_remove_sta_debugfs,
|
||||
#endif
|
||||
.get_expected_throughput = minstrel_get_expected_throughput,
|
||||
};
|
||||
|
||||
int __init
|
||||
|
|
|
@ -1032,6 +1032,22 @@ minstrel_ht_free(void *priv)
|
|||
mac80211_minstrel.free(priv);
|
||||
}
|
||||
|
||||
static u32 minstrel_ht_get_expected_throughput(void *priv_sta)
|
||||
{
|
||||
struct minstrel_ht_sta_priv *msp = priv_sta;
|
||||
struct minstrel_ht_sta *mi = &msp->ht;
|
||||
int i, j;
|
||||
|
||||
if (!msp->is_ht)
|
||||
return mac80211_minstrel.get_expected_throughput(priv_sta);
|
||||
|
||||
i = mi->max_tp_rate / MCS_GROUP_RATES;
|
||||
j = mi->max_tp_rate % MCS_GROUP_RATES;
|
||||
|
||||
/* convert cur_tp from pkt per second in kbps */
|
||||
return mi->groups[i].rates[j].cur_tp * AVG_PKT_SIZE * 8 / 1024;
|
||||
}
|
||||
|
||||
static const struct rate_control_ops mac80211_minstrel_ht = {
|
||||
.name = "minstrel_ht",
|
||||
.tx_status = minstrel_ht_tx_status,
|
||||
|
@ -1046,6 +1062,7 @@ static const struct rate_control_ops mac80211_minstrel_ht = {
|
|||
.add_sta_debugfs = minstrel_ht_add_sta_debugfs,
|
||||
.remove_sta_debugfs = minstrel_ht_remove_sta_debugfs,
|
||||
#endif
|
||||
.get_expected_throughput = minstrel_ht_get_expected_throughput,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -184,6 +184,20 @@ TRACE_EVENT(drv_return_bool,
|
|||
"true" : "false")
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_return_u32,
|
||||
TP_PROTO(struct ieee80211_local *local, u32 ret),
|
||||
TP_ARGS(local, ret),
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(u32, ret)
|
||||
),
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->ret = ret;
|
||||
),
|
||||
TP_printk(LOCAL_PR_FMT " - %u", LOCAL_PR_ARG, __entry->ret)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_return_u64,
|
||||
TP_PROTO(struct ieee80211_local *local, u64 ret),
|
||||
TP_ARGS(local, ret),
|
||||
|
@ -1499,6 +1513,24 @@ DEFINE_EVENT(local_sdata_evt, drv_leave_ibss,
|
|||
TP_ARGS(local, sdata)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_get_expected_throughput,
|
||||
TP_PROTO(struct ieee80211_sta *sta),
|
||||
|
||||
TP_ARGS(sta),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
STA_ENTRY
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
STA_ASSIGN;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
STA_PR_FMT, STA_PR_ARG
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Tracing for API calls that drivers call.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue