Skip to content

Commit

Permalink
nl80211: Add wmm rule attribute to NL80211_CMD_GET_WIPHY dump command
Browse files Browse the repository at this point in the history
This will serve userspace entity to maintain its regulatory limitation.
More specifcally APs can use this data to calculate the WMM IE when
building: beacons, probe responses, assoc responses etc...

Signed-off-by: Haim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Haim Dreyfuss authored and Johannes Berg committed May 7, 2018
1 parent 0373700 commit 50f3271
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 4 deletions.
28 changes: 28 additions & 0 deletions include/uapi/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Copyright 2008 Jouni Malinen <jouni.malinen@atheros.com>
* Copyright 2008 Colin McCabe <colin@cozybit.com>
* Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
Expand Down Expand Up @@ -3141,6 +3142,29 @@ enum nl80211_band_attr {

#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA

/**
* enum nl80211_wmm_rule - regulatory wmm rule
*
* @__NL80211_WMMR_INVALID: attribute number 0 is reserved
* @NL80211_WMMR_CW_MIN: Minimum contention window slot.
* @NL80211_WMMR_CW_MAX: Maximum contention window slot.
* @NL80211_WMMR_AIFSN: Arbitration Inter Frame Space.
* @NL80211_WMMR_TXOP: Maximum allowed tx operation time.
* @nl80211_WMMR_MAX: highest possible wmm rule.
* @__NL80211_WMMR_LAST: Internal use.
*/
enum nl80211_wmm_rule {
__NL80211_WMMR_INVALID,
NL80211_WMMR_CW_MIN,
NL80211_WMMR_CW_MAX,
NL80211_WMMR_AIFSN,
NL80211_WMMR_TXOP,

/* keep last */
__NL80211_WMMR_LAST,
NL80211_WMMR_MAX = __NL80211_WMMR_LAST - 1
};

/**
* enum nl80211_frequency_attr - frequency attributes
* @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved
Expand Down Expand Up @@ -3190,6 +3214,9 @@ enum nl80211_band_attr {
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed
* on this channel in current regulatory domain.
* @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations.
* This is a nested attribute that contains the wmm limitation per AC.
* (see &enum nl80211_wmm_rule)
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
Expand Down Expand Up @@ -3218,6 +3245,7 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_IR_CONCURRENT,
NL80211_FREQUENCY_ATTR_NO_20MHZ,
NL80211_FREQUENCY_ATTR_NO_10MHZ,
NL80211_FREQUENCY_ATTR_WMM,

/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
Expand Down
57 changes: 53 additions & 4 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright 2015-2017 Intel Deutschland GmbH
* Copyright (C) 2018 Intel Corporation
*/

#include <linux/if.h>
Expand Down Expand Up @@ -645,7 +646,43 @@ static inline void *nl80211hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
return genlmsg_put(skb, portid, seq, &nl80211_fam, flags, cmd);
}

static int nl80211_msg_put_channel(struct sk_buff *msg,
static int nl80211_msg_put_wmm_rules(struct sk_buff *msg,
const struct ieee80211_reg_rule *rule)
{
int j;
struct nlattr *nl_wmm_rules =
nla_nest_start(msg, NL80211_FREQUENCY_ATTR_WMM);

if (!nl_wmm_rules)
goto nla_put_failure;

for (j = 0; j < IEEE80211_NUM_ACS; j++) {
struct nlattr *nl_wmm_rule = nla_nest_start(msg, j);

if (!nl_wmm_rule)
goto nla_put_failure;

if (nla_put_u16(msg, NL80211_WMMR_CW_MIN,
rule->wmm_rule->client[j].cw_min) ||
nla_put_u16(msg, NL80211_WMMR_CW_MAX,
rule->wmm_rule->client[j].cw_max) ||
nla_put_u8(msg, NL80211_WMMR_AIFSN,
rule->wmm_rule->client[j].aifsn) ||
nla_put_u8(msg, NL80211_WMMR_TXOP,
rule->wmm_rule->client[j].cot))
goto nla_put_failure;

nla_nest_end(msg, nl_wmm_rule);
}
nla_nest_end(msg, nl_wmm_rules);

return 0;

nla_put_failure:
return -ENOBUFS;
}

static int nl80211_msg_put_channel(struct sk_buff *msg, struct wiphy *wiphy,
struct ieee80211_channel *chan,
bool large)
{
Expand Down Expand Up @@ -721,6 +758,16 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
DBM_TO_MBM(chan->max_power)))
goto nla_put_failure;

if (large) {
const struct ieee80211_reg_rule *rule =
freq_reg_info(wiphy, chan->center_freq);

if (!IS_ERR(rule) && rule->wmm_rule) {
if (nl80211_msg_put_wmm_rules(msg, rule))
goto nla_put_failure;
}
}

return 0;

nla_put_failure:
Expand Down Expand Up @@ -1631,7 +1678,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
chan = &sband->channels[i];

if (nl80211_msg_put_channel(
msg, chan,
msg, &rdev->wiphy, chan,
state->split))
goto nla_put_failure;

Expand Down Expand Up @@ -14320,15 +14367,17 @@ void nl80211_send_beacon_hint_event(struct wiphy *wiphy,
nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_BEFORE);
if (!nl_freq)
goto nla_put_failure;
if (nl80211_msg_put_channel(msg, channel_before, false))

if (nl80211_msg_put_channel(msg, wiphy, channel_before, false))
goto nla_put_failure;
nla_nest_end(msg, nl_freq);

/* After */
nl_freq = nla_nest_start(msg, NL80211_ATTR_FREQ_AFTER);
if (!nl_freq)
goto nla_put_failure;
if (nl80211_msg_put_channel(msg, channel_after, false))

if (nl80211_msg_put_channel(msg, wiphy, channel_after, false))
goto nla_put_failure;
nla_nest_end(msg, nl_freq);

Expand Down

0 comments on commit 50f3271

Please sign in to comment.