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

Commit 593b7303 authored by Johannes Berg's avatar Johannes Berg Committed by Purushottam Kushwaha
Browse files

cfg80211: add checks for beacon rate, extend to mesh



The previous commit added support for specifying the beacon rate
for AP mode. Add features checks to this, and extend it to also
support the rate configuration for mesh networks. For IBSS it's
not as simple due to joining etc., so that's not yet supported.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>

Git-commit: 8564e38206de2ff005a27c8d7c2ce3869a44f0dd
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git


Change-Id: Id1f43276701f805dc93d2bcdabec4f333942e31c
CRs-fixed: 1096202
[pkushwah@codeaurora.org: an additional check for NULL chan in chandef is
added before the validation.
backport to 3.18-This commit includes the changes from following commits
in include/uapi/linux/nl80211.h to compile for msm-3.18.
ffc1199122d83d60ad99f9c55df32feb650b7bff :
cfg80211: add VHT support for IBSS
0c9ca11b1ae8eb16c1b6bbae91991392d2321372 :
cfg80211: Add global RRM capability
c6e6a0c8be575c830a97b1942dabeab70f423fe0 :
nl80211: Add API to support VHT MU-MIMO air sniffer
1d76250bd34af86c6498fc51e50cab3bfbbeceaa :
nl80211: support beacon report scanning ]
Signed-off-by: default avatarPurushottam Kushwaha <pkushwah@codeaurora.org>
parent 10b43e84
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -728,7 +728,7 @@ struct cfg80211_bitrate_mask {
 *	MAC address based access control
 *	MAC address based access control
 * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
 * @pbss: If set, start as a PCP instead of AP. Relevant for DMG
 *	networks.
 *	networks.
 * @beacon_rate: masks for setting user configured beacon tx rate.
 * @beacon_rate: bitrate to be used for beacons
 */
 */
struct cfg80211_ap_settings {
struct cfg80211_ap_settings {
	struct cfg80211_chan_def chandef;
	struct cfg80211_chan_def chandef;
@@ -1422,6 +1422,7 @@ struct mesh_config {
 * @beacon_interval: beacon interval to use
 * @beacon_interval: beacon interval to use
 * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
 * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
 * @basic_rates: basic rates to use when creating the mesh
 * @basic_rates: basic rates to use when creating the mesh
 * @beacon_rate: bitrate to be used for beacons
 *
 *
 * These parameters are fixed when the mesh is created.
 * These parameters are fixed when the mesh is created.
 */
 */
@@ -1442,6 +1443,7 @@ struct mesh_setup {
	u16 beacon_interval;
	u16 beacon_interval;
	int mcast_rate[IEEE80211_NUM_BANDS];
	int mcast_rate[IEEE80211_NUM_BANDS];
	u32 basic_rates;
	u32 basic_rates;
	struct cfg80211_bitrate_mask beacon_rate;
};
};


/**
/**
+44 −1
Original line number Original line Diff line number Diff line
@@ -1289,7 +1289,13 @@ enum nl80211_commands {
 *	enum nl80211_band value is used as the index (nla_type() of the nested
 *	enum nl80211_band value is used as the index (nla_type() of the nested
 *	data. If a band is not included, it will be configured to allow all
 *	data. If a band is not included, it will be configured to allow all
 *	rates based on negotiated supported rates information. This attribute
 *	rates based on negotiated supported rates information. This attribute
 *	is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
 *	is used with %NL80211_CMD_SET_TX_BITRATE_MASK and with starting AP,
 *	and joining mesh networks (not IBSS yet). In the later case, it must
 *	specify just a single bitrate, which is to be used for the beacon.
 *	The driver must also specify support for this with the extended
 *	features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
 *	NL80211_EXT_FEATURE_BEACON_RATE_HT and
 *	NL80211_EXT_FEATURE_BEACON_RATE_VHT.
 *
 *
 * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
 * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
 *	at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
 *	at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME.
@@ -4259,11 +4265,48 @@ enum nl80211_feature_flags {


/**
/**
 * enum nl80211_ext_feature_index - bit index of extended features.
 * enum nl80211_ext_feature_index - bit index of extended features.
 * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates.
 * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can
 *	can request to use RRM (see %NL80211_ATTR_USE_RRM) with
 *	%NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
 *	the ASSOC_REQ_USE_RRM flag in the association request even if
 *	NL80211_FEATURE_QUIET is not advertized.
 * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
 *	sniffer which means that it can be configured to hear packets from
 *	certain groups which can be configured by the
 *	%NL80211_ATTR_MU_MIMO_GROUP_DATA attribute,
 *	or can be configured to follow a station by configuring the
 *	%NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute.
 * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual
 *	time the scan started in scan results event. The time is the TSF of
 *	the BSS that the interface that requested the scan is connected to
 *	(if available).
 * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
 *	time the last beacon/probe was received. The time is the TSF of the
 *	BSS that the interface that requested the scan is connected to
 *	(if available).
 * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
 *	channel dwell time.
 * @NL80211_EXT_FEATURE_BEACON_RATE_LEGACY: Driver supports beacon rate
 *	configuration (AP/mesh), supporting a legacy (non HT/VHT) rate.
 * @NL80211_EXT_FEATURE_BEACON_RATE_HT: Driver supports beacon rate
 *	configuration (AP/mesh) with HT rates.
 * @NL80211_EXT_FEATURE_BEACON_RATE_VHT: Driver supports beacon rate
 *	configuration (AP/mesh) with VHT rates.
 *
 *
 * @NUM_NL80211_EXT_FEATURES: number of extended features.
 * @NUM_NL80211_EXT_FEATURES: number of extended features.
 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
 * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
 */
 */
enum nl80211_ext_feature_index {
enum nl80211_ext_feature_index {
	NL80211_EXT_FEATURE_VHT_IBSS,
	NL80211_EXT_FEATURE_RRM,
	NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER,
	NL80211_EXT_FEATURE_SCAN_START_TIME,
	NL80211_EXT_FEATURE_BSS_PARENT_TSF,
	NL80211_EXT_FEATURE_SET_SCAN_DWELL,
	NL80211_EXT_FEATURE_BEACON_RATE_LEGACY,
	NL80211_EXT_FEATURE_BEACON_RATE_HT,
	NL80211_EXT_FEATURE_BEACON_RATE_VHT,


	/* add new features before the definition below */
	/* add new features before the definition below */
	NUM_NL80211_EXT_FEATURES,
	NUM_NL80211_EXT_FEATURES,
+35 −11
Original line number Original line Diff line number Diff line
@@ -3391,13 +3391,12 @@ out:
	return 0;
	return 0;
}
}


static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)
static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
				   enum nl80211_band band,
				   struct cfg80211_bitrate_mask *beacon_rate)
{
{
	u32 rate, count_ht, count_vht, i;
	u32 count_ht, count_vht, i;
	enum nl80211_band band;
	u32 rate = beacon_rate->control[band].legacy;

	band = params->chandef.chan->band;
	rate = params->beacon_rate.control[band].legacy;


	/* Allow only one rate */
	/* Allow only one rate */
	if (hweight32(rate) > 1)
	if (hweight32(rate) > 1)
@@ -3405,9 +3404,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)


	count_ht = 0;
	count_ht = 0;
	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
	for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) {
		if (hweight8(params->beacon_rate.control[band].ht_mcs[i]) > 1) {
		if (hweight8(beacon_rate->control[band].ht_mcs[i]) > 1) {
			return -EINVAL;
			return -EINVAL;
		} else if (params->beacon_rate.control[band].ht_mcs[i]) {
		} else if (beacon_rate->control[band].ht_mcs[i]) {
			count_ht++;
			count_ht++;
			if (count_ht > 1)
			if (count_ht > 1)
				return -EINVAL;
				return -EINVAL;
@@ -3418,9 +3417,9 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)


	count_vht = 0;
	count_vht = 0;
	for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
	for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
		if (hweight16(params->beacon_rate.control[band].vht_mcs[i]) > 1) {
		if (hweight16(beacon_rate->control[band].vht_mcs[i]) > 1) {
			return -EINVAL;
			return -EINVAL;
		} else if (params->beacon_rate.control[band].vht_mcs[i]) {
		} else if (beacon_rate->control[band].vht_mcs[i]) {
			count_vht++;
			count_vht++;
			if (count_vht > 1)
			if (count_vht > 1)
				return -EINVAL;
				return -EINVAL;
@@ -3432,6 +3431,19 @@ static int validate_beacon_tx_rate(struct cfg80211_ap_settings *params)
	if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht))
	if ((count_ht && count_vht) || (!rate && !count_ht && !count_vht))
		return -EINVAL;
		return -EINVAL;


	if (rate &&
	    !wiphy_ext_feature_isset(&rdev->wiphy,
				     NL80211_EXT_FEATURE_BEACON_RATE_LEGACY))
		return -EINVAL;
	if (count_ht &&
	    !wiphy_ext_feature_isset(&rdev->wiphy,
				     NL80211_EXT_FEATURE_BEACON_RATE_HT))
		return -EINVAL;
	if (count_vht &&
	    !wiphy_ext_feature_isset(&rdev->wiphy,
				     NL80211_EXT_FEATURE_BEACON_RATE_VHT))
		return -EINVAL;

	return 0;
	return 0;
}
}


@@ -3670,7 +3682,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
		if (err)
		if (err)
			return err;
			return err;


		err = validate_beacon_tx_rate(&params);
		err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
					      &params.beacon_rate);
		if (err)
		if (err)
			return err;
			return err;
	}
	}
@@ -8546,6 +8559,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
			return err;
			return err;
	}
	}


	if (info->attrs[NL80211_ATTR_TX_RATES] && setup.chandef.chan != NULL) {
		err = nl80211_parse_tx_bitrate_mask(info, &setup.beacon_rate);
		if (err)
			return err;

		err = validate_beacon_tx_rate(rdev, setup.chandef.chan->band,
					      &setup.beacon_rate);
		if (err)
			return err;
	}

	return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
	return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
}
}