Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cca674d4 authored by Antonio Quartulli's avatar Antonio Quartulli Committed by Johannes Berg
Browse files

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: default avatarAntonio Quartulli <antonio@open-mesh.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 867d849f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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,
+13 −0
Original line number Diff line number Diff line
@@ -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] = {
+13 −0
Original line number Diff line number Diff line
@@ -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 */
+12 −0
Original line number Diff line number Diff line
@@ -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
+17 −0
Original line number Diff line number Diff line
@@ -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,
};


Loading