2018-12-03 12:05:02

by Vamsi Krishna

[permalink] [raw]
Subject: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate

NL80211_CMD_FRAME is used to send frames from userspace. Add support to
transmit the frames at a rate specified by userspace when needed.
The drivers shall indicate the support to send frames at rate specified
by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
wiphy capabilities. The userspace can specify the rate within
%NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.

NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
attributes defined in &enum nl80211_rate_info.

Signed-off-by: vamsi krishna <[email protected]>

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index c032375..dbf58c6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2629,6 +2629,11 @@ struct cfg80211_update_ft_ies_params {
* @dont_wait_for_ack: tells the low level not to wait for an ack
* @n_csa_offsets: length of csa_offsets array
* @csa_offsets: array of all the csa offsets in the frame
+ * @txrate: Tx rate at which this frame shall be transmitted on-air.
+ * txrate->legacy shall be used to determine 11abg rate only when none of
+ * RATE_INFO_FLAGS_MCS, RATE_INFO_FLAGS_VHT_MCS and RATE_INFO_FLAGS_HE_MCS
+ * flags in txrate->flags.
+ * @txrate_specified: Indicates whether any valid tx rate specified @txrate.
*/
struct cfg80211_mgmt_tx_params {
struct ieee80211_channel *chan;
@@ -2640,6 +2645,8 @@ struct cfg80211_mgmt_tx_params {
bool dont_wait_for_ack;
int n_csa_offsets;
const u16 *csa_offsets;
+ struct rate_info txrate;
+ bool txrate_specified;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0d4dd14..b731868 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -646,6 +646,11 @@
* %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
* counters which will be updated to the current value. This attribute
* is used during CSA period.
+ * Optionally the rate at which this frame shall be transmitted can be
+ * specified using %NL80211_ATTR_RATE_INFO if the driver indicates the
+ * support by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE feature flag.
+ * NL80211_RATE_INFO_BITRATE* shall not be populated within
+ * %NL80211_ATTR_RATE_INFO unless one of the 11abg rates is specified.
* @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
* command may be used with the corresponding cookie to cancel the wait
* time if it is known that it is no longer necessary.
@@ -2270,6 +2275,12 @@ enum nl80211_commands {
* or bssid attribute will have higher precedence than the thresholds
* mentioned in this attribute while checking rssi.
*
+ * @NL80211_ATTR_RATE_INFO: Specifies either tx rate at which a packet shall be
+ * transmitted or rx rate at which a packet has been received. Nested
+ * attribute containing info as possible, see &enum nl80211_rate_info.
+ * Will be used with %NL80211_CMD_FRAME to specify the phy rate at which
+ * the frame associated with this command shall be transmitted over the
+ * air.
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2717,6 +2728,8 @@ enum nl80211_attrs {

NL80211_ATTR_SCHED_SCAN_MIN_RSSI,

+ NL80211_ATTR_RATE_INFO,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -2930,7 +2943,9 @@ enum nl80211_he_ru_alloc {
* enum nl80211_rate_info - bitrate information
*
* These attribute types are used with %NL80211_STA_INFO_TXRATE
- * when getting information about the bitrate of a station.
+ * when getting information about the bitrate of a station and with
+ * %NL80211_CMD_FRAME to specify the phy rate at which the frame shall
+ * be transmitted.
* There are 2 attributes for bitrate, a legacy one that represents
* a 16-bit value, and new one that represents a 32-bit value.
* If the rate value fits into 16 bit, both attributes are reported
@@ -5278,6 +5293,10 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: The driver supports
* filtering scan results with band specific rssi thresholds that are
* specified within %NL80211_ATTR_SCHED_SCAN_MIN_RSSI.
+ * @NL80211_EXT_FEATURE_CMD_FRAME_TXRATE: The driver supports sending frames
+ * at rate specified by userspace with %NL80211_CMD_FRAME. The tx rate
+ * shall be specified within %NL80211_ATTR_RATE_INFO nested attribute
+ * with %NL80211_CMD_FRAME command.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5319,6 +5338,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
+ NL80211_EXT_FEATURE_CMD_FRAME_TXRATE,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4fc0bfc..9bb7b65 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -498,6 +498,7 @@ static int validate_ie_attr(const struct nlattr *attr,
.validation_data = nl80211_ftm_responder_policy,
},
[NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
+ [NL80211_ATTR_RATE_INFO] = { .type = NLA_NESTED },
};

/* policy for the key attributes */
@@ -638,6 +639,27 @@ static int validate_ie_attr(const struct nlattr *attr,
[NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
};

+static const struct nla_policy
+nl80211_rate_info_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
+ [NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_80_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_80P80_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_160_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_10_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_5_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_HE_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_NSS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_GI] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_DCM] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_RU_ALLOC] = { .type = NLA_U8 },
+};
+
static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
struct cfg80211_registered_device **rdev,
struct wireless_dev **wdev)
@@ -9918,6 +9940,92 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
}

+static int
+nl80211_parse_rate_info(struct genl_info *info, struct rate_info *rate)
+{
+ struct nlattr *tb[NL80211_RATE_INFO_MAX + 1];
+ struct nlattr *attr;
+ int err;
+
+ attr = info->attrs[NL80211_ATTR_RATE_INFO];
+ if (!attr)
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, NL80211_RATE_INFO_MAX, attr,
+ nl80211_rate_info_policy, NULL);
+ if (err)
+ return err;
+
+ if (tb[NL80211_RATE_INFO_BITRATE] || tb[NL80211_RATE_INFO_BITRATE32]) {
+ if (tb[NL80211_RATE_INFO_MCS] ||
+ tb[NL80211_RATE_INFO_VHT_MCS] ||
+ tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_MCS]) {
+ if (tb[NL80211_RATE_INFO_VHT_MCS] ||
+ tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_VHT_MCS]) {
+ if (tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ if (!tb[NL80211_RATE_INFO_VHT_NSS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ if (!(tb[NL80211_RATE_INFO_HE_NSS] &&
+ tb[NL80211_RATE_INFO_HE_GI] &&
+ tb[NL80211_RATE_INFO_HE_DCM]))
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ memset(rate, 0, sizeof(struct rate_info));
+
+ if (tb[NL80211_RATE_INFO_BITRATE32]) {
+ /* Safe to truncate, as 11abg rates will fit into 16-bits */
+ rate->legacy =
+ (u16)nla_get_u32(tb[NL80211_RATE_INFO_BITRATE32]);
+ } else if (tb[NL80211_RATE_INFO_BITRATE]) {
+ rate->legacy = nla_get_u16(tb[NL80211_RATE_INFO_BITRATE]);
+ } else if (tb[NL80211_RATE_INFO_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_MCS]);
+ rate->flags |= RATE_INFO_FLAGS_MCS;
+ } else if (tb[NL80211_RATE_INFO_VHT_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_VHT_MCS]);
+ rate->nss = nla_get_u8(tb[NL80211_RATE_INFO_VHT_NSS]);
+ rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_HE_MCS]);
+ rate->nss = nla_get_u8(tb[NL80211_RATE_INFO_HE_NSS]);
+ rate->flags |= RATE_INFO_FLAGS_HE_MCS;
+ }
+
+ if (tb[NL80211_RATE_INFO_MCS] || tb[NL80211_RATE_INFO_VHT_MCS]) {
+ if (nla_get_flag(tb[NL80211_RATE_INFO_SHORT_GI]))
+ rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ rate->he_gi = nla_get_u8(tb[NL80211_RATE_INFO_HE_GI]);
+ rate->he_dcm = nla_get_u8(tb[NL80211_RATE_INFO_HE_DCM]);
+ }
+
+ if (nla_get_flag(tb[NL80211_RATE_INFO_5_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_5;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_10_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_10;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_40_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_40;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_80_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_80;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_160_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_160;
+ else if (tb[NL80211_RATE_INFO_HE_MCS])
+ rate->bw = RATE_INFO_BW_HE_RU;
+ else
+ rate->bw = RATE_INFO_BW_20;
+
+ return 0;
+}
+
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9955,6 +10063,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
}

+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_CMD_FRAME_TXRATE) &&
+ info->attrs[NL80211_ATTR_RATE_INFO])
+ return -EINVAL;
+
if (info->attrs[NL80211_ATTR_DURATION]) {
if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
return -EINVAL;
@@ -10017,6 +10130,15 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
}
}

+ if (info->attrs[NL80211_ATTR_RATE_INFO]) {
+ err = nl80211_parse_rate_info(info, &params.txrate);
+ if (err)
+ return err;
+ params.txrate_specified = true;
+ } else {
+ params.txrate_specified = false;
+ }
+
if (!params.dont_wait_for_ack) {
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



2018-12-18 13:12:31

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate

On Mon, 2018-12-03 at 17:34 +0530, vamsi krishna wrote:
> NL80211_CMD_FRAME is used to send frames from userspace. Add support to
> transmit the frames at a rate specified by userspace when needed.
> The drivers shall indicate the support to send frames at rate specified
> by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
> wiphy capabilities. The userspace can specify the rate within
> %NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
>
> NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
> attributes defined in &enum nl80211_rate_info.

It'd be good if you were to repost this with a driver that uses it.

Also, please explain why you think userspace needs this? It's not like
it can make better rate decisions than the rate control algorithm,
right?

> [NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
> + [NL80211_ATTR_RATE_INFO] = { .type = NLA_NESTED },

This should use NLA_POLICY_NESTED(nl80211_rate_info_policy)

johannes


2018-12-18 13:45:43

by Ben Greear

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate



On 12/18/2018 05:12 AM, Johannes Berg wrote:
> On Mon, 2018-12-03 at 17:34 +0530, vamsi krishna wrote:
>> NL80211_CMD_FRAME is used to send frames from userspace. Add support to
>> transmit the frames at a rate specified by userspace when needed.
>> The drivers shall indicate the support to send frames at rate specified
>> by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
>> wiphy capabilities. The userspace can specify the rate within
>> %NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
>>
>> NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
>> attributes defined in &enum nl80211_rate_info.
>
> It'd be good if you were to repost this with a driver that uses it.
>
> Also, please explain why you think userspace needs this? It's not like
> it can make better rate decisions than the rate control algorithm,
> right?
>
>> [NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
>> + [NL80211_ATTR_RATE_INFO] = { .type = NLA_NESTED },
>
> This should use NLA_POLICY_NESTED(nl80211_rate_info_policy)

I missed the first posting of this patch. Here are some of my own
suggestions.

The wave-2 ath10k firmware has an option to specify tx-power, preamble
(CCK, OFDM, HT, VHT), bandwidth, mcs, nss and retry-count on a per-packet
basis. This is not enabled in the ath10k driver, and I am not certain QCA
firmware compiles in this option, but I have both ath10k-ct driver and firmware
able to do this currently.

For HT and VHT, the mcs is fairly obvious I think. For CCK and OFDM, the
mcs is treated as an index into the CCK and OFDM rate tables.

So, maybe the patch could use these basic constructs instead of the
different flags/rates for MCS vs VHT_MCS vs HE_MCS?

Or, do you want to be able to specify multiple different tx rates per
frame? wave-2 firmware that I have seen wouldn't support that, but I guess newer stuff
could?

Either way, please at least consider adding retry-count and tx-power to this API and I
can tie it into my ath10k-ct driver and firmware API.

As for purpose, I use this for testing, though someone could probably use the
API to make it use a somewhat minimal rate-ctrl in the kernel instead of firmware if they wanted
(ignoring the complexities of MU-MIMO and such).

Thanks,
Ben


--
Ben Greear <[email protected]>
Candela Technologies Inc http://www.candelatech.com

2019-01-08 17:22:59

by Vamsi Krishna

[permalink] [raw]
Subject: [PATCH v2] nl80211/cfg80211: Add support to send tx packet specific params

Add support to transmit the frames at a rate specified by userspace
when needed in NL80211_CMD_FRAME command. This commit adds support to
specify tx rate, number of retries and tx power.

Tx rate at which packet shall be transmitted can be specified in
%NL80211_ATTR_RATE_INFO, number of retries can be specified in
%NL80211_ATTR_WIPHY_RETRY_SHORT and %NL80211_ATTR_WIPHY_RETRY_LONG,
tx power can be specified in %NL80211_ATTR_WIPHY_TX_POWER_LEVEL.

The drivers shall indicate the support to send frames at rate specified
by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
wiphy capabilities. The userspace can specify the rate within
%NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
attributes defined in &enum nl80211_rate_info.

Signed-off-by: vamsi krishna <[email protected]>

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index c032375..bbaa5c3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2616,6 +2616,24 @@ struct cfg80211_update_ft_ies_params {
};

/**
+ * enum cfg80211_mgmt_tx_params_filled - Mgmt. tx params that are filled.
+ *
+ * This enum provides information on which all mgmt tx parameters are filled
+ * in struct cfg80211_mgmt_tx_params. The variables defined in this enum will
+ * be used as bitmap in cfg80211_mgmt_tx_params->filled.
+ *
+ * @MGMT_PACKET_TX_RATE: Indicates whether tx rate is filled.
+ * @MGMT_PACKET_TX_RETRIES: Indicates whether at least one of the short or long
+ * retries are filled or not.
+ * @MGMT_PACKET_TX_POWER: Indicates whether tx power is specified or not.
+ */
+enum cfg80211_mgmt_tx_params_filled {
+ MGMT_PACKET_TX_RATE = BIT(0),
+ MGMT_PACKET_TX_RETRIES = BIT(1),
+ MGMT_PACKET_TX_POWER = BIT(2),
+};
+
+/**
* struct cfg80211_mgmt_tx_params - mgmt tx parameters
*
* This structure provides information needed to transmit a mgmt frame
@@ -2629,6 +2647,16 @@ struct cfg80211_update_ft_ies_params {
* @dont_wait_for_ack: tells the low level not to wait for an ack
* @n_csa_offsets: length of csa_offsets array
* @csa_offsets: array of all the csa offsets in the frame
+ * @filled: bitmap of different optional mgmt tx parameters that are filled in
+ * this structure. Bit mappings are defined in
+ * enum cfg80211_mgmt_tx_params_filled.
+ * @txrate: Tx rate at which this frame shall be transmitted on-air.
+ * txrate->legacy shall be used to determine 11abg rate only when none of
+ * RATE_INFO_FLAGS_MCS, RATE_INFO_FLAGS_VHT_MCS and RATE_INFO_FLAGS_HE_MCS
+ * flags in txrate->flags.
+ * @retry_short: Retry limit for short frames for this packet
+ * @retry_long: Retry limit for long frames for this packet
+ * @max_power: Transmission power for this packet (in mBm)
*/
struct cfg80211_mgmt_tx_params {
struct ieee80211_channel *chan;
@@ -2640,6 +2668,11 @@ struct cfg80211_mgmt_tx_params {
bool dont_wait_for_ack;
int n_csa_offsets;
const u16 *csa_offsets;
+ u32 filled;
+ struct rate_info txrate;
+ u8 retry_short;
+ u8 retry_long;
+ s32 tx_power;
};

/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 0d4dd14..0d49c80 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -646,6 +646,16 @@
* %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA
* counters which will be updated to the current value. This attribute
* is used during CSA period.
+ * Optionally the rate at which this frame shall be transmitted can be
+ * specified using %NL80211_ATTR_RATE_INFO if the driver indicates the
+ * support by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE feature flag.
+ * NL80211_RATE_INFO_BITRATE* shall not be populated within
+ * %NL80211_ATTR_RATE_INFO unless one of the 11abg rates is specified.
+ * The number of retries that can be made to successfully transmit this
+ * frame can be specified using %NL80211_ATTR_WIPHY_RETRY_SHORT and/or
+ * %NL80211_ATTR_WIPHY_RETRY_LONG attributes.
+ * The tx power at which this frame shall be transmitted can be specified
+ * using %NL80211_ATTR_WIPHY_TX_POWER_LEVEL attribute.
* @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
* command may be used with the corresponding cookie to cancel the wait
* time if it is known that it is no longer necessary.
@@ -1621,7 +1631,8 @@ enum nl80211_commands {
* &enum nl80211_tx_power_setting for possible values.
* @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
* This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
- * for non-automatic settings.
+ * for non-automatic settings. When used in @NL80211_CMD_FRAME, it
+ * specifies the fixed power at which the frame shall be transmitted.
*
* @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly
* means support for per-station GTKs.
@@ -2270,6 +2281,12 @@ enum nl80211_commands {
* or bssid attribute will have higher precedence than the thresholds
* mentioned in this attribute while checking rssi.
*
+ * @NL80211_ATTR_RATE_INFO: Specifies either tx rate at which a packet shall be
+ * transmitted or rx rate at which a packet has been received. Nested
+ * attribute containing info as possible, see &enum nl80211_rate_info.
+ * Will be used with %NL80211_CMD_FRAME to specify the phy rate at which
+ * the frame associated with this command shall be transmitted over the
+ * air.
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2717,6 +2734,8 @@ enum nl80211_attrs {

NL80211_ATTR_SCHED_SCAN_MIN_RSSI,

+ NL80211_ATTR_RATE_INFO,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -2930,7 +2949,9 @@ enum nl80211_he_ru_alloc {
* enum nl80211_rate_info - bitrate information
*
* These attribute types are used with %NL80211_STA_INFO_TXRATE
- * when getting information about the bitrate of a station.
+ * when getting information about the bitrate of a station and with
+ * %NL80211_CMD_FRAME to specify the phy rate at which the frame shall
+ * be transmitted.
* There are 2 attributes for bitrate, a legacy one that represents
* a 16-bit value, and new one that represents a 32-bit value.
* If the rate value fits into 16 bit, both attributes are reported
@@ -5278,6 +5299,10 @@ enum nl80211_feature_flags {
* @NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD: The driver supports
* filtering scan results with band specific rssi thresholds that are
* specified within %NL80211_ATTR_SCHED_SCAN_MIN_RSSI.
+ * @NL80211_EXT_FEATURE_CMD_FRAME_TXRATE: The driver supports sending frames
+ * at rate specified by userspace with %NL80211_CMD_FRAME. The tx rate
+ * shall be specified within %NL80211_ATTR_RATE_INFO nested attribute
+ * with %NL80211_CMD_FRAME command.
*
* @NUM_NL80211_EXT_FEATURES: number of extended features.
* @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5319,6 +5344,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_CAN_REPLACE_PTK0,
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER,
NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD,
+ NL80211_EXT_FEATURE_CMD_FRAME_TXRATE,

/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4fc0bfc..70c19f5 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -240,6 +240,27 @@ static int validate_ie_attr(const struct nlattr *attr,
.len = U8_MAX },
};

+static const struct nla_policy
+nl80211_rate_info_policy[NL80211_RATE_INFO_MAX + 1] = {
+ [NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+ [NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_BITRATE32] = { .type = NLA_U32 },
+ [NL80211_RATE_INFO_VHT_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_VHT_NSS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_80_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_80P80_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_160_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_10_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_5_MHZ_WIDTH] = { .type = NLA_FLAG },
+ [NL80211_RATE_INFO_HE_MCS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_NSS] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_GI] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_DCM] = { .type = NLA_U8 },
+ [NL80211_RATE_INFO_HE_RU_ALLOC] = { .type = NLA_U8 },
+};
+
static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
@@ -498,6 +519,8 @@ static int validate_ie_attr(const struct nlattr *attr,
.validation_data = nl80211_ftm_responder_policy,
},
[NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
+ [NL80211_ATTR_RATE_INFO] = NLA_POLICY_NESTED(NL80211_RATE_INFO_MAX,
+ nl80211_rate_info_policy),
};

/* policy for the key attributes */
@@ -9918,6 +9941,92 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
nla_len(info->attrs[NL80211_ATTR_FRAME_MATCH]));
}

+static int
+nl80211_parse_rate_info(struct genl_info *info, struct rate_info *rate)
+{
+ struct nlattr *tb[NL80211_RATE_INFO_MAX + 1];
+ struct nlattr *attr;
+ int err;
+
+ attr = info->attrs[NL80211_ATTR_RATE_INFO];
+ if (!attr)
+ return -EINVAL;
+
+ err = nla_parse_nested(tb, NL80211_RATE_INFO_MAX, attr,
+ nl80211_rate_info_policy, NULL);
+ if (err)
+ return err;
+
+ if (tb[NL80211_RATE_INFO_BITRATE] || tb[NL80211_RATE_INFO_BITRATE32]) {
+ if (tb[NL80211_RATE_INFO_MCS] ||
+ tb[NL80211_RATE_INFO_VHT_MCS] ||
+ tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_MCS]) {
+ if (tb[NL80211_RATE_INFO_VHT_MCS] ||
+ tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_VHT_MCS]) {
+ if (tb[NL80211_RATE_INFO_HE_MCS])
+ return -EINVAL;
+ if (!tb[NL80211_RATE_INFO_VHT_NSS])
+ return -EINVAL;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ if (!(tb[NL80211_RATE_INFO_HE_NSS] &&
+ tb[NL80211_RATE_INFO_HE_GI] &&
+ tb[NL80211_RATE_INFO_HE_DCM]))
+ return -EINVAL;
+ } else {
+ return -EINVAL;
+ }
+
+ memset(rate, 0, sizeof(struct rate_info));
+
+ if (tb[NL80211_RATE_INFO_BITRATE32]) {
+ /* Safe to truncate, as 11abg rates will fit into 16-bits */
+ rate->legacy =
+ (u16)nla_get_u32(tb[NL80211_RATE_INFO_BITRATE32]);
+ } else if (tb[NL80211_RATE_INFO_BITRATE]) {
+ rate->legacy = nla_get_u16(tb[NL80211_RATE_INFO_BITRATE]);
+ } else if (tb[NL80211_RATE_INFO_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_MCS]);
+ rate->flags |= RATE_INFO_FLAGS_MCS;
+ } else if (tb[NL80211_RATE_INFO_VHT_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_VHT_MCS]);
+ rate->nss = nla_get_u8(tb[NL80211_RATE_INFO_VHT_NSS]);
+ rate->flags |= RATE_INFO_FLAGS_VHT_MCS;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ rate->mcs = nla_get_u16(tb[NL80211_RATE_INFO_HE_MCS]);
+ rate->nss = nla_get_u8(tb[NL80211_RATE_INFO_HE_NSS]);
+ rate->flags |= RATE_INFO_FLAGS_HE_MCS;
+ }
+
+ if (tb[NL80211_RATE_INFO_MCS] || tb[NL80211_RATE_INFO_VHT_MCS]) {
+ if (nla_get_flag(tb[NL80211_RATE_INFO_SHORT_GI]))
+ rate->flags |= RATE_INFO_FLAGS_SHORT_GI;
+ } else if (tb[NL80211_RATE_INFO_HE_MCS]) {
+ rate->he_gi = nla_get_u8(tb[NL80211_RATE_INFO_HE_GI]);
+ rate->he_dcm = nla_get_u8(tb[NL80211_RATE_INFO_HE_DCM]);
+ }
+
+ if (nla_get_flag(tb[NL80211_RATE_INFO_5_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_5;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_10_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_10;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_40_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_40;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_80_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_80;
+ else if (nla_get_flag(tb[NL80211_RATE_INFO_160_MHZ_WIDTH]))
+ rate->bw = RATE_INFO_BW_160;
+ else if (tb[NL80211_RATE_INFO_HE_MCS])
+ rate->bw = RATE_INFO_BW_HE_RU;
+ else
+ rate->bw = RATE_INFO_BW_20;
+
+ return 0;
+}
+
static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9955,6 +10064,11 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
return -EOPNOTSUPP;
}

+ if (!wiphy_ext_feature_isset(&rdev->wiphy,
+ NL80211_EXT_FEATURE_CMD_FRAME_TXRATE) &&
+ info->attrs[NL80211_ATTR_RATE_INFO])
+ return -EINVAL;
+
if (info->attrs[NL80211_ATTR_DURATION]) {
if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
return -EINVAL;
@@ -10017,6 +10131,32 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
}
}

+ if (info->attrs[NL80211_ATTR_RATE_INFO]) {
+ err = nl80211_parse_rate_info(info, &params.txrate);
+ if (err)
+ return err;
+ params.filled |= MGMT_PACKET_TX_RATE;
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]) {
+ params.retry_short =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_RETRY_SHORT]);
+ params.filled |= MGMT_PACKET_TX_RETRIES;
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]) {
+ params.retry_long =
+ nla_get_u8(info->attrs[NL80211_ATTR_WIPHY_RETRY_LONG]);
+ params.filled |= MGMT_PACKET_TX_RETRIES;
+ }
+
+ if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL]) {
+ int idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
+
+ params.tx_power = nla_get_s32(info->attrs[idx]);
+ params.filled |= MGMT_PACKET_TX_POWER;
+ }
+
if (!params.dont_wait_for_ack) {
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg)
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project


2019-01-08 17:49:47

by Vamsi Krishna

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate

On 2018-12-18 19:15, Ben Greear wrote:
> On 12/18/2018 05:12 AM, Johannes Berg wrote:
>> On Mon, 2018-12-03 at 17:34 +0530, vamsi krishna wrote:
>>> NL80211_CMD_FRAME is used to send frames from userspace. Add support
>>> to
>>> transmit the frames at a rate specified by userspace when needed.
>>> The drivers shall indicate the support to send frames at rate
>>> specified
>>> by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
>>> wiphy capabilities. The userspace can specify the rate within
>>> %NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
>>>
>>> NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
>>> attributes defined in &enum nl80211_rate_info.
>>
>> It'd be good if you were to repost this with a driver that uses it.
Unfortunately, the driver that I am working now is not upstreamed. I
would like to check with Ben if he likes to propose a patch ath10k
driver that he is working on as I see he is also interested in this
feature. Please let me know if it is mandatory or good to have driver
implementation.

>>
>> Also, please explain why you think userspace needs this? It's not like
>> it can make better rate decisions than the rate control algorithm,
>> right?
Yes, you are correct. Rate control algorithm will continue to be in the
lower layers only. This is mostly for testing and experimenting
purposes.

>>
>>> [NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
>>> + [NL80211_ATTR_RATE_INFO] = { .type = NLA_NESTED },
>>
>> This should use NLA_POLICY_NESTED(nl80211_rate_info_policy)
Thanks for pointing out this MACRO, I used it in my new version of the
patch.

>
> I missed the first posting of this patch. Here are some of my own
> suggestions.
>
> The wave-2 ath10k firmware has an option to specify tx-power, preamble
> (CCK, OFDM, HT, VHT), bandwidth, mcs, nss and retry-count on a
> per-packet
> basis. This is not enabled in the ath10k driver, and I am not certain
> QCA
> firmware compiles in this option, but I have both ath10k-ct driver and
> firmware
> able to do this currently.
>
> For HT and VHT, the mcs is fairly obvious I think. For CCK and OFDM,
> the
> mcs is treated as an index into the CCK and OFDM rate tables.
>
> So, maybe the patch could use these basic constructs instead of the
> different flags/rates for MCS vs VHT_MCS vs HE_MCS?
I am not sure if I understand your comment correctly. If you are
proposing to remove the different attribute ids for MCS, VHT_MCS and
HE_MCS, I think that will lead to unnecessary confusion especially as we
have duplicate indices between different modes(for example between HT
and VHT). I believe it is better to keep this similar to reporting tx
and rx rates in NL80211_CMD_GET_STATION in order to avoid problems with
future technologies like EHT.


> Or, do you want to be able to specify multiple different tx rates per
> frame? wave-2 firmware that I have seen wouldn't support that, but I
> guess newer stuff
> could?
My intention is to add single rate only.

> Either way, please at least consider adding retry-count and tx-power
> to this API and I
> can tie it into my ath10k-ct driver and firmware API.
Sure, I have added them in the newer version of the patch.

Though I used in-reply-to option with git send-email, still the patch
that I sent is coming in a new thread @
https://patchwork.kernel.org/patch/10752599/ . I am not sure if that is
because of subject change, I had to change the subject of the patch in
order to reflect the new additions done to the patch. Could you please
kindly guide me with the right process to send the new patch.

Thanks,
Vamsi

2019-01-08 20:21:08

by Ben Greear

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate

On 1/8/19 9:49 AM, [email protected] wrote:
> On 2018-12-18 19:15, Ben Greear wrote:
>> On 12/18/2018 05:12 AM, Johannes Berg wrote:
>>> On Mon, 2018-12-03 at 17:34 +0530, vamsi krishna wrote:
>>>> NL80211_CMD_FRAME is used to send frames from userspace. Add support to
>>>> transmit the frames at a rate specified by userspace when needed.
>>>> The drivers shall indicate the support to send frames at rate specified
>>>> by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
>>>> wiphy capabilities. The userspace can specify the rate within
>>>> %NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
>>>>
>>>> NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
>>>> attributes defined in &enum nl80211_rate_info.
>>>
>>> It'd be good if you were to repost this with a driver that uses it.
> Unfortunately, the driver that I am working now is not upstreamed. I would like to check with Ben if he likes to propose a patch ath10k driver that he is
> working on as I see he is also interested in this feature. Please let me know if it is mandatory or good to have driver implementation.

Kalle will not accept any of my patches that enable my firmware, though my ath10k-ct
driver/firmware is in OpenWRT if that is upstream enough.

>>> Also, please explain why you think userspace needs this? It's not like
>>> it can make better rate decisions than the rate control algorithm,
>>> right?
> Yes, you are correct. Rate control algorithm will continue to be in the lower layers only. This is mostly for testing and experimenting purposes.
>
>>>
>>>>      [NL80211_ATTR_SCHED_SCAN_MIN_RSSI] = { .type = NLA_NESTED },
>>>> +    [NL80211_ATTR_RATE_INFO] = { .type = NLA_NESTED },
>>>
>>> This should use NLA_POLICY_NESTED(nl80211_rate_info_policy)
> Thanks for pointing out this MACRO, I used it in my new version of the patch.
>
>>
>> I missed the first posting of this patch.  Here are some of my own
>> suggestions.
>>
>> The wave-2 ath10k firmware has an option to specify tx-power, preamble
>> (CCK, OFDM, HT, VHT), bandwidth, mcs, nss and retry-count on a per-packet
>> basis.  This is not enabled in the ath10k driver, and I am not certain QCA
>> firmware compiles in this option, but I have both ath10k-ct driver and firmware
>> able to do this currently.
>>
>> For HT and VHT, the mcs is fairly obvious I think.  For CCK and OFDM, the
>> mcs is treated as an index into the CCK and OFDM rate tables.
>>
>> So, maybe the patch could use these basic constructs instead of the
>> different flags/rates for MCS vs VHT_MCS vs HE_MCS?
> I am not sure if I understand your comment correctly. If you are proposing to remove the different attribute ids for MCS, VHT_MCS and HE_MCS, I think that will
> lead to unnecessary confusion especially as we have duplicate indices between different modes(for example between HT and VHT). I believe it is better to keep
> this similar to reporting tx and rx rates in NL80211_CMD_GET_STATION in order to avoid problems with future technologies like EHT.

Here is the API that I have in my modified ath10k-ct driver (and the ath10k-ct wave-2 firmware handles it accordingly):

/* Create a rate-info object that (some) 10.4 CT firmware
* can understand.
*/
u32 ath10k_convert_hw_rate_to_rate_info(u8 tpc, u8 mcs, u8 sgi, u8 nss, u8 pream_type,
u8 num_retries, u8 bw, u8 dyn_bw)

/* Re-use logic from 10.4 firmware */
struct __ath10k_rate_info {
u32 power : 6, /* units of the power field is dbm */
unused : 1, /* Room for growth */
sgi : 1, /* Enable SGI or not, checked when valid_rate is enabled. */
mcs : 4, /* mcs = 0 ~ 9 */
nss : 2, /* 0 = 1 nss, 1 = 2 nss, 2 = 3 nss, 3 = 4 nss */
pream_type : 2, /* 0 = WIFI_RATECODE_PREAM_OFDM,
1 = WIFI_RATECODE_PREAM_CCK,
2 = WIFI_RATECODE_PREAM_HT ,
3 = WIFI_RATECODE_PREAM_VHT */
num_retries : 4, /* 0 ~ 15: 0 means no-ack */
dyn_bw : 1, /* 0 = static bw, 1 = dynamic bw */
bw : 3, /* valid only if dyn_bw == 0 (static bw).
(0 = 20 mhz, 1 = 40 mhz, 2 = 80 mhz, 3 = 160 mhz , 4 = 80+80mhz) */
valid_power : 1, /* power info field has valid power. */
valid_rate : 1, /* mcs,nss,pream_type fields have valid rates. */
valid_num_retries : 1, /* num_retries field has valid value */
valid_dyn_bw : 1, /* dyn_bw field has valid value */
valid_bw : 1, /* bw field has valid value */

any_valid : 1, /* 1 : htt_tx_msdu_desc_t contains valid tx meta data */
key_id : 2; /* key index 0 to 3 for per packet key rotation */
};
...

So, the best API for me would allow me to specify all of this from user-space. pream-type could have a new 'HE'
in the upper stacks, ath10k would just ignore it.

Thanks,
Ben


--
Ben Greear <[email protected]>
Candela Technologies Inc http://www.candelatech.com


2019-01-15 13:13:13

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate

On Tue, 2019-01-08 at 23:19 +0530, [email protected] wrote:

> Unfortunately, the driver that I am working now is not upstreamed. I
> would like to check with Ben if he likes to propose a patch ath10k
> driver that he is working on as I see he is also interested in this
> feature. Please let me know if it is mandatory or good to have driver
> implementation.

I'm not sure it really has to be *mandatory*, but if nobody else even
wants to have support for this (and e.g. iwlwifi cannot even easily do
this I believe) then what value does something have upstream?

johannes


2019-01-15 13:18:17

by Ben Greear

[permalink] [raw]
Subject: Re: [PATCH] nl80211/cfg80211: Add support to send tx frames at specified rate



On 01/15/2019 05:13 AM, Johannes Berg wrote:
> On Tue, 2019-01-08 at 23:19 +0530, [email protected] wrote:
>
>> Unfortunately, the driver that I am working now is not upstreamed. I
>> would like to check with Ben if he likes to propose a patch ath10k
>> driver that he is working on as I see he is also interested in this
>> feature. Please let me know if it is mandatory or good to have driver
>> implementation.
>
> I'm not sure it really has to be *mandatory*, but if nobody else even
> wants to have support for this (and e.g. iwlwifi cannot even easily do
> this I believe) then what value does something have upstream?

Maybe ath9k could get support for this API?

Likely I'll eventually implement support for ath9k for this API if it is
in the kernel and no one does it first, but not sure when I'd get to it.

Thanks,
Ben


--
Ben Greear <[email protected]>
Candela Technologies Inc http://www.candelatech.com

2019-01-25 12:48:59

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2] nl80211/cfg80211: Add support to send tx packet specific params

On Tue, 2019-01-08 at 22:52 +0530, vamsi krishna wrote:
> Add support to transmit the frames at a rate specified by userspace
> when needed in NL80211_CMD_FRAME command. This commit adds support to
> specify tx rate, number of retries and tx power.
>
> Tx rate at which packet shall be transmitted can be specified in
> %NL80211_ATTR_RATE_INFO, number of retries can be specified in
> %NL80211_ATTR_WIPHY_RETRY_SHORT and %NL80211_ATTR_WIPHY_RETRY_LONG,
> tx power can be specified in %NL80211_ATTR_WIPHY_TX_POWER_LEVEL.
>
> The drivers shall indicate the support to send frames at rate specified
> by userspace by setting %NL80211_EXT_FEATURE_CMD_FRAME_TXRATE flag in
> wiphy capabilities. The userspace can specify the rate within
> %NL80211_ATTR_RATE_INFO attribute while sending %NL80211_CMD_FRAME.
> NL80211_ATTR_RATE_INFO is a nested attribute and encapsulates the
> attributes defined in &enum nl80211_rate_info.

I don't usually strongly enforce that we'd like to see upstream users
for upstream cfg80211 functionality, but in this case I feel that we
don't even have the *ability* to implement this in most/any upstream
driver(s), so there's no point.

Perhaps also a mac80211 implementation would make sense to some extent.

I also feel that to some extent this overlaps with the per-station TX
power control?

I'd like you to come back with this when there's more upstream support
in general, and when you've fleshed out the exact use cases and whether
or not this fine-grained control is actually needed/desired, or if
something like what Ben had suggested earlier would make sense (IIRC he
suggested limiting to a certain preamble type and similar - i.e. classes
of rates rather than a single very precisely defined rate).


Also, some nitpicks since I'm looking anyway:
* don't support RATE_INFO_BITRATE - RATE_INFO_BITRATE32 is for new
applications and by definition there can be no old application for a
new feature
* NL80211_ATTR_WIPHY_TX_POWER_LEVEL has a small indentation problem in
the docs
* would make sense to capitalize "TX" throughout, rather than writing
"tx power"

johannes