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

Commit dd5b4cc7 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville
Browse files

cfg80211/mac80211: improve ad-hoc multicast rate handling



- store the multicast rate as an index instead of the rate value
  (reduces cpu overhead in a hotpath)
- validate the rate values (must match a bitrate in at least one sband)

Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 46090979
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -923,7 +923,7 @@ struct cfg80211_disassoc_request {
 * @privacy: this is a protected network, keys will be configured
 *	after joining
 * @basic_rates: bitmap of basic rates to use when creating the IBSS
 * @mcast_rate: multicast tx rate (in 100 kbps)
 * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
 */
struct cfg80211_ibss_params {
	u8 *ssid;
@@ -935,7 +935,7 @@ struct cfg80211_ibss_params {
	u32 basic_rates;
	bool channel_fixed;
	bool privacy;
	int mcast_rate;
	int mcast_rate[IEEE80211_NUM_BANDS];
};

/**
+2 −2
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ enum ieee80211_bss_change {
 * @basic_rates: bitmap of basic rates, each bit stands for an
 *	index into the rate table configured by the driver in
 *	the current band.
 * @mcast_rate: multicast rate for AP and Ad-Hoc (in 100 kbps)
 * @mcast_rate: per-band multicast rate index + 1 (0: disabled)
 * @bssid: The BSSID for this BSS
 * @enable_beacon: whether beaconing should be enabled or not
 * @channel_type: Channel type for this BSS -- the hardware might be
@@ -259,7 +259,7 @@ struct ieee80211_bss_conf {
	u16 assoc_capability;
	u64 timestamp;
	u32 basic_rates;
	u32 mcast_rate;
	int mcast_rate[IEEE80211_NUM_BANDS];
	u16 ht_operation_mode;
	s32 cqm_rssi_thold;
	u32 cqm_rssi_hyst;
+2 −1
Original line number Diff line number Diff line
@@ -915,7 +915,8 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,

	sdata->u.ibss.privacy = params->privacy;
	sdata->u.ibss.basic_rates = params->basic_rates;
	sdata->vif.bss_conf.mcast_rate = params->mcast_rate;
	memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
	       sizeof(params->mcast_rate));

	sdata->vif.bss_conf.beacon_int = params->beacon_interval;

+12 −13
Original line number Diff line number Diff line
@@ -211,20 +211,11 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
	return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
}

static void rc_send_low_broadcast(s8 *idx, u32 basic_rates, u32 mcast_rate,
static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
				  struct ieee80211_supported_band *sband)
{
	u8 i;

	if (mcast_rate) {
		for (i = 0; i < sband->n_bitrates; i++) {
			if (sband->bitrates[i].bitrate == mcast_rate) {
				*idx = i;
				return;
			}
		}
	}

	if (basic_rates == 0)
		return; /* assume basic rates unknown and accept rate */
	if (*idx < 0)
@@ -247,17 +238,25 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
			   struct ieee80211_tx_rate_control *txrc)
{
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb);
	struct ieee80211_supported_band *sband = txrc->sband;
	int mcast_rate;

	if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) {
		info->control.rates[0].idx = rate_lowest_index(txrc->sband, sta);
		info->control.rates[0].count =
			(info->flags & IEEE80211_TX_CTL_NO_ACK) ?
			1 : txrc->hw->max_rate_tries;
		if (!sta && txrc->bss)
		if (!sta && txrc->bss) {
			mcast_rate = txrc->bss_conf->mcast_rate[sband->band];
			if (mcast_rate > 0) {
				info->control.rates[0].idx = mcast_rate - 1;
				return true;
			}

			rc_send_low_broadcast(&info->control.rates[0].idx,
					      txrc->bss_conf->basic_rates,
					      txrc->bss_conf->mcast_rate,
					      txrc->sband);
					      sband);
		}
		return true;
	}
	return false;
+33 −3
Original line number Diff line number Diff line
@@ -3600,6 +3600,34 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
				      local_state_change);
}

static bool
nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
			 int mcast_rate[IEEE80211_NUM_BANDS],
			 int rateval)
{
	struct wiphy *wiphy = &rdev->wiphy;
	bool found = false;
	int band, i;

	for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
		struct ieee80211_supported_band *sband;

		sband = wiphy->bands[band];
		if (!sband)
			continue;

		for (i = 0; i < sband->n_bitrates; i++) {
			if (sband->bitrates[i].bitrate == rateval) {
				mcast_rate[band] = i + 1;
				found = true;
				break;
			}
		}
	}

	return found;
}

static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
{
	struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -3683,9 +3711,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
				return -EINVAL;
		}
	}
	if (info->attrs[NL80211_ATTR_MCAST_RATE])
		ibss.mcast_rate =
			nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE]);

	if (info->attrs[NL80211_ATTR_MCAST_RATE] &&
	    !nl80211_parse_mcast_rate(rdev, ibss.mcast_rate,
			nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
		return -EINVAL;

	if (ibss.privacy && info->attrs[NL80211_ATTR_KEYS]) {
		connkeys = nl80211_parse_connkeys(rdev,