From df8a39defad46b83694ea6dd868d332976d62cc0 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 13 Jan 2015 17:13:44 +0100 Subject: net: rename vlan_tx_* helpers since "tx" is misleading there The same macros are used for rx as well. So rename it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/wireless/util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/wireless/util.c') diff --git a/net/wireless/util.c b/net/wireless/util.c index d0ac795445b7..1d2fcfad06cc 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -708,8 +708,8 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb, if (skb->priority >= 256 && skb->priority <= 263) return skb->priority - 256; - if (vlan_tx_tag_present(skb)) { - vlan_priority = (vlan_tx_tag_get(skb) & VLAN_PRIO_MASK) + if (skb_vlan_tag_present(skb)) { + vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; if (vlan_priority > 0) return vlan_priority; -- cgit v1.2.3 From 97d910d0aaa619ca530d08e2b1125b8014ccb030 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Jan 2015 16:05:21 +0100 Subject: cfg80211: remove 80+80 MHz rate reporting These rates are treated the same as 160 MHz in the spec, so it makes no sense to distinguish them. As no driver uses them yet, this is also not a problem, just remove them. In the userspace API the field remains reserved to preserve API and ABI. Signed-off-by: Johannes Berg --- include/net/cfg80211.h | 8 +++----- include/uapi/linux/nl80211.h | 3 ++- net/wireless/nl80211.c | 3 --- net/wireless/util.c | 3 +-- 4 files changed, 6 insertions(+), 11 deletions(-) (limited to 'net/wireless/util.c') diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 38abc07503fd..0322048fddab 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -875,7 +875,6 @@ int cfg80211_check_station_change(struct wiphy *wiphy, * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission - * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval * @RATE_INFO_FLAGS_60G: 60GHz MCS @@ -885,10 +884,9 @@ enum rate_info_flags { RATE_INFO_FLAGS_VHT_MCS = BIT(1), RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2), RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3), - RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4), - RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5), - RATE_INFO_FLAGS_SHORT_GI = BIT(6), - RATE_INFO_FLAGS_60G = BIT(7), + RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(4), + RATE_INFO_FLAGS_SHORT_GI = BIT(5), + RATE_INFO_FLAGS_60G = BIT(6), }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index b6c1a00bd8d2..11cdb85ac646 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2278,7 +2278,8 @@ struct nl80211_sta_flag_update { * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate - * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate + * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: unused - 80+80 is treated the + * same as 160 for purposes of the bitrates * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate * @__NL80211_RATE_INFO_AFTER_LAST: internal use */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 380784378df8..8998484ea970 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3614,9 +3614,6 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) return false; - if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH)) - return false; if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) return false; diff --git a/net/wireless/util.c b/net/wireless/util.c index d0ac795445b7..6942d48f1ac5 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1073,8 +1073,7 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) if (WARN_ON_ONCE(rate->mcs > 9)) return 0; - idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH | - RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 : + idx = rate->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH ? 3 : rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 : rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0; -- cgit v1.2.3 From b51f3beecfbbfc946749a91fb444cb8917cf444f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 15 Jan 2015 16:14:02 +0100 Subject: cfg80211: change bandwidth reporting to explicit field For some reason, we made the bandwidth separate flags, which is rather confusing - a single rate cannot have different bandwidths at the same time. Change this to no longer be flags but use a separate field for the bandwidth ('bw') instead. While at it, add support for 5 and 10 MHz rates - these are reported as regular legacy rates with their real bitrate, but tagged as 5/10 now to make it easier to distinguish them. In the nl80211 API, the flags are preserved, but the code now can also clearly only set a single one of the flags. Signed-off-by: Johannes Berg --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 ++- drivers/net/wireless/mwifiex/cfg80211.c | 11 ++++---- include/net/cfg80211.h | 33 ++++++++++++++++++------ include/uapi/linux/nl80211.h | 8 ++++++ net/mac80211/cfg.c | 31 +++++++++++++++-------- net/mac80211/util.c | 25 +++++++++++++------ net/wireless/nl80211.c | 40 +++++++++++++++++++++--------- net/wireless/util.c | 24 ++++++++++++++---- 8 files changed, 125 insertions(+), 50 deletions(-) (limited to 'net/wireless/util.c') diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 44dd6ef923cd..85da63a67faf 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1827,6 +1827,7 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, } sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + sinfo->txrate.bw = RATE_INFO_BW_20; } else if (is_rate_ht40(rate, &mcs, &sgi)) { if (sgi) { sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; @@ -1835,7 +1836,7 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, sinfo->txrate.mcs = mcs; } - sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.bw = RATE_INFO_BW_40; sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; } else { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 71312ff52703..1996a8b612d2 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -856,16 +856,16 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, /* HT or VHT */ switch (tx_htinfo & (BIT(3) | BIT(2))) { case 0: - /* This will be 20MHz */ + rate->bw = RATE_INFO_BW_20; break; case (BIT(2)): - rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + rate->bw = RATE_INFO_BW_40; break; case (BIT(3)): - rate->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + rate->bw = RATE_INFO_BW_80; break; case (BIT(3) | BIT(2)): - rate->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + rate->bw = RATE_INFO_BW_160; break; } @@ -885,8 +885,9 @@ mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { rate->mcs = priv->tx_rate; rate->flags |= RATE_INFO_FLAGS_MCS; + rate->bw = RATE_INFO_BW_20; if (tx_htinfo & BIT(1)) - rate->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + rate->bw = RATE_INFO_BW_40; if (tx_htinfo & BIT(2)) rate->flags |= RATE_INFO_FLAGS_SHORT_GI; } diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0322048fddab..7b44ba0a7632 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -873,20 +873,35 @@ int cfg80211_check_station_change(struct wiphy *wiphy, * * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS - * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission - * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission - * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval * @RATE_INFO_FLAGS_60G: 60GHz MCS */ enum rate_info_flags { RATE_INFO_FLAGS_MCS = BIT(0), RATE_INFO_FLAGS_VHT_MCS = BIT(1), - RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2), - RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3), - RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(4), - RATE_INFO_FLAGS_SHORT_GI = BIT(5), - RATE_INFO_FLAGS_60G = BIT(6), + RATE_INFO_FLAGS_SHORT_GI = BIT(2), + RATE_INFO_FLAGS_60G = BIT(3), +}; + +/** + * enum rate_info_bw - rate bandwidth information + * + * Used by the driver to indicate the rate bandwidth. + * + * @RATE_INFO_BW_5: 5 MHz bandwidth + * @RATE_INFO_BW_10: 10 MHz bandwidth + * @RATE_INFO_BW_20: 20 MHz bandwidth + * @RATE_INFO_BW_40: 40 MHz bandwidth + * @RATE_INFO_BW_80: 80 MHz bandwidth + * @RATE_INFO_BW_160: 160 MHz bandwidth + */ +enum rate_info_bw { + RATE_INFO_BW_5, + RATE_INFO_BW_10, + RATE_INFO_BW_20, + RATE_INFO_BW_40, + RATE_INFO_BW_80, + RATE_INFO_BW_160, }; /** @@ -898,12 +913,14 @@ enum rate_info_flags { * @mcs: mcs index if struct describes a 802.11n bitrate * @legacy: bitrate in 100kbit/s for 802.11abg * @nss: number of streams (VHT only) + * @bw: bandwidth (from &enum rate_info_bw) */ struct rate_info { u8 flags; u8 mcs; u16 legacy; u8 nss; + u8 bw; }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 11cdb85ac646..f52797a90816 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -2281,6 +2281,12 @@ struct nl80211_sta_flag_update { * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: unused - 80+80 is treated the * same as 160 for purposes of the bitrates * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate + * @NL80211_RATE_INFO_10_MHZ_WIDTH: 10 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * half the base (20 MHz) rate + * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * a quarter of the base (20 MHz) rate * @__NL80211_RATE_INFO_AFTER_LAST: internal use */ enum nl80211_rate_info { @@ -2295,6 +2301,8 @@ enum nl80211_rate_info { NL80211_RATE_INFO_80_MHZ_WIDTH, NL80211_RATE_INFO_80P80_MHZ_WIDTH, NL80211_RATE_INFO_160_MHZ_WIDTH, + NL80211_RATE_INFO_10_MHZ_WIDTH, + NL80211_RATE_INFO_5_MHZ_WIDTH, /* keep last */ __NL80211_RATE_INFO_AFTER_LAST, diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6d5076fbf87a..ff090ef1ea2c 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -428,11 +428,13 @@ void sta_set_rate_info_tx(struct sta_info *sta, rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); } if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) - rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) - rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + rinfo->bw = RATE_INFO_BW_40; + else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + rinfo->bw = RATE_INFO_BW_80; + else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + rinfo->bw = RATE_INFO_BW_160; + else + rinfo->bw = RATE_INFO_BW_20; if (rate->flags & IEEE80211_TX_RC_SHORT_GI) rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; } @@ -459,14 +461,21 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); } - if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) - rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; - if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) - rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) - rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + + if (sta->last_rx_rate_flag & RX_FLAG_5MHZ) + rinfo->bw = RATE_INFO_BW_5; + else if (sta->last_rx_rate_flag & RX_FLAG_10MHZ) + rinfo->bw = RATE_INFO_BW_10; + else if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) + rinfo->bw = RATE_INFO_BW_40; + else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) + rinfo->bw = RATE_INFO_BW_80; + else if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) + rinfo->bw = RATE_INFO_BW_160; + else + rinfo->bw = RATE_INFO_BW_20; } static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index db7216124736..fbd37d43dfce 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2541,7 +2541,9 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ri.mcs = status->rate_idx; ri.flags |= RATE_INFO_FLAGS_MCS; if (status->flag & RX_FLAG_40MHZ) - ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + ri.bw = RATE_INFO_BW_40; + else + ri.bw = RATE_INFO_BW_20; if (status->flag & RX_FLAG_SHORT_GI) ri.flags |= RATE_INFO_FLAGS_SHORT_GI; } else if (status->flag & RX_FLAG_VHT) { @@ -2549,11 +2551,13 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, ri.mcs = status->rate_idx; ri.nss = status->vht_nss; if (status->flag & RX_FLAG_40MHZ) - ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; - if (status->vht_flag & RX_VHT_FLAG_80MHZ) - ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; - if (status->vht_flag & RX_VHT_FLAG_160MHZ) - ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; + ri.bw = RATE_INFO_BW_40; + else if (status->vht_flag & RX_VHT_FLAG_80MHZ) + ri.bw = RATE_INFO_BW_80; + else if (status->vht_flag & RX_VHT_FLAG_160MHZ) + ri.bw = RATE_INFO_BW_160; + else + ri.bw = RATE_INFO_BW_20; if (status->flag & RX_FLAG_SHORT_GI) ri.flags |= RATE_INFO_FLAGS_SHORT_GI; } else { @@ -2561,10 +2565,15 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, int shift = 0; int bitrate; - if (status->flag & RX_FLAG_10MHZ) + if (status->flag & RX_FLAG_10MHZ) { shift = 1; - if (status->flag & RX_FLAG_5MHZ) + ri.bw = RATE_INFO_BW_10; + } else if (status->flag & RX_FLAG_5MHZ) { shift = 2; + ri.bw = RATE_INFO_BW_5; + } else { + ri.bw = RATE_INFO_BW_20; + } sband = local->hw.wiphy->bands[status->band]; bitrate = sband->bitrates[status->rate_idx].bitrate; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8998484ea970..8e56eeb583aa 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3578,6 +3578,7 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, struct nlattr *rate; u32 bitrate; u16 bitrate_compat; + enum nl80211_attrs rate_flg; rate = nla_nest_start(msg, attr); if (!rate) @@ -3594,12 +3595,36 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate_compat)) return false; + switch (info->bw) { + case RATE_INFO_BW_5: + rate_flg = NL80211_RATE_INFO_5_MHZ_WIDTH; + break; + case RATE_INFO_BW_10: + rate_flg = NL80211_RATE_INFO_10_MHZ_WIDTH; + break; + default: + WARN_ON(1); + /* fall through */ + case RATE_INFO_BW_20: + rate_flg = 0; + break; + case RATE_INFO_BW_40: + rate_flg = NL80211_RATE_INFO_40_MHZ_WIDTH; + break; + case RATE_INFO_BW_80: + rate_flg = NL80211_RATE_INFO_80_MHZ_WIDTH; + break; + case RATE_INFO_BW_160: + rate_flg = NL80211_RATE_INFO_160_MHZ_WIDTH; + break; + } + + if (rate_flg && nla_put_flag(msg, rate_flg)) + return false; + if (info->flags & RATE_INFO_FLAGS_MCS) { if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs)) return false; - if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) - return false; if (info->flags & RATE_INFO_FLAGS_SHORT_GI && nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) return false; @@ -3608,15 +3633,6 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, return false; if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss)) return false; - if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH)) - return false; - if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH && - nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH)) - return false; if (info->flags & RATE_INFO_FLAGS_SHORT_GI && nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI)) return false; diff --git a/net/wireless/util.c b/net/wireless/util.c index 6942d48f1ac5..3535e8ade48f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1073,9 +1073,24 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) if (WARN_ON_ONCE(rate->mcs > 9)) return 0; - idx = rate->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH ? 3 : - rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 : - rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0; + switch (rate->bw) { + case RATE_INFO_BW_160: + idx = 3; + break; + case RATE_INFO_BW_80: + idx = 2; + break; + case RATE_INFO_BW_40: + idx = 1; + break; + case RATE_INFO_BW_5: + case RATE_INFO_BW_10: + default: + WARN_ON(1); + /* fall through */ + case RATE_INFO_BW_20: + idx = 0; + } bitrate = base[idx][rate->mcs]; bitrate *= rate->nss; @@ -1106,8 +1121,7 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate) modulation = rate->mcs & 7; streams = (rate->mcs >> 3) + 1; - bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? - 13500000 : 6500000; + bitrate = (rate->bw == RATE_INFO_BW_40) ? 13500000 : 6500000; if (modulation < 4) bitrate *= (modulation + 1); -- cgit v1.2.3 From 37720569cc89205c23011d6b52f8c63ea2057c3d Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 24 Jan 2015 19:52:04 +0200 Subject: cfg80211: Fix BIP (AES-CMAC) cipher validation This cipher can be used only as a group management frame cipher and as such, there is no point in validating that it is not used with non-zero key-index. Instead, verify that it is not used as a pairwise cipher regardless of the key index. Signed-off-by: Jouni Malinen [change code to use switch statement which is easier to extend] Signed-off-by: Johannes Berg --- net/wireless/util.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'net/wireless/util.c') diff --git a/net/wireless/util.c b/net/wireless/util.c index 3535e8ade48f..08f136ad2ea5 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -227,18 +227,26 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, if (pairwise && !mac_addr) return -EINVAL; - /* - * Disallow pairwise keys with non-zero index unless it's WEP - * or a vendor specific cipher (because current deployments use - * pairwise WEP keys with non-zero indices and for vendor specific - * ciphers this should be validated in the driver or hardware level - * - but 802.11i clearly specifies to use zero) - */ - if (pairwise && key_idx && - ((params->cipher == WLAN_CIPHER_SUITE_TKIP) || - (params->cipher == WLAN_CIPHER_SUITE_CCMP) || - (params->cipher == WLAN_CIPHER_SUITE_AES_CMAC))) - return -EINVAL; + switch (params->cipher) { + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + /* Disallow pairwise keys with non-zero index unless it's WEP + * or a vendor specific cipher (because current deployments use + * pairwise WEP keys with non-zero indices and for vendor + * specific ciphers this should be validated in the driver or + * hardware level - but 802.11i clearly specifies to use zero) + */ + if (pairwise && key_idx) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + /* Disallow BIP (group-only) cipher as pairwise cipher */ + if (pairwise) + return -EINVAL; + break; + default: + break; + } switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: -- cgit v1.2.3 From cfcf1682c4ca8f601a4702255958e0b1c9aa12cc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 24 Jan 2015 19:52:05 +0200 Subject: cfg80211: Add new GCMP, CCMP-256, BIP-GMAC, BIP-CMAC-256 ciphers This makes cfg80211 aware of the GCMP, GCMP-256, CCMP-256, BIP-GMAC-128, BIP-GMAC-256, and BIP-CMAC-256 cipher suites. These new cipher suites were defined in IEEE Std 802.11ac-2013. Signed-off-by: Jouni Malinen Signed-off-by: Johannes Berg --- include/linux/ieee80211.h | 18 ++++++++++++++++++ net/wireless/util.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'net/wireless/util.c') diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 4f4eea8a6288..dbf417bf25bf 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1994,9 +1994,15 @@ enum ieee80211_key_len { WLAN_KEY_LEN_WEP40 = 5, WLAN_KEY_LEN_WEP104 = 13, WLAN_KEY_LEN_CCMP = 16, + WLAN_KEY_LEN_CCMP_256 = 32, WLAN_KEY_LEN_TKIP = 32, WLAN_KEY_LEN_AES_CMAC = 16, WLAN_KEY_LEN_SMS4 = 32, + WLAN_KEY_LEN_GCMP = 16, + WLAN_KEY_LEN_GCMP_256 = 32, + WLAN_KEY_LEN_BIP_CMAC_256 = 32, + WLAN_KEY_LEN_BIP_GMAC_128 = 16, + WLAN_KEY_LEN_BIP_GMAC_256 = 32, }; #define IEEE80211_WEP_IV_LEN 4 @@ -2004,9 +2010,16 @@ enum ieee80211_key_len { #define IEEE80211_CCMP_HDR_LEN 8 #define IEEE80211_CCMP_MIC_LEN 8 #define IEEE80211_CCMP_PN_LEN 6 +#define IEEE80211_CCMP_256_HDR_LEN 8 +#define IEEE80211_CCMP_256_MIC_LEN 16 +#define IEEE80211_CCMP_256_PN_LEN 6 #define IEEE80211_TKIP_IV_LEN 8 #define IEEE80211_TKIP_ICV_LEN 4 #define IEEE80211_CMAC_PN_LEN 6 +#define IEEE80211_GMAC_PN_LEN 6 +#define IEEE80211_GCMP_HDR_LEN 8 +#define IEEE80211_GCMP_MIC_LEN 16 +#define IEEE80211_GCMP_PN_LEN 6 /* Public action codes */ enum ieee80211_pub_actioncode { @@ -2230,6 +2243,11 @@ enum ieee80211_sa_query_action { #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 #define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 +#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 +#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B +#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C +#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D #define WLAN_CIPHER_SUITE_SMS4 0x00147201 diff --git a/net/wireless/util.c b/net/wireless/util.c index 08f136ad2ea5..919fee807dd9 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -230,6 +230,9 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, switch (params->cipher) { case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: /* Disallow pairwise keys with non-zero index unless it's WEP * or a vendor specific cipher (because current deployments use * pairwise WEP keys with non-zero indices and for vendor @@ -240,6 +243,9 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, return -EINVAL; break; case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: /* Disallow BIP (group-only) cipher as pairwise cipher */ if (pairwise) return -EINVAL; @@ -261,6 +267,18 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, if (params->key_len != WLAN_KEY_LEN_CCMP) return -EINVAL; break; + case WLAN_CIPHER_SUITE_CCMP_256: + if (params->key_len != WLAN_KEY_LEN_CCMP_256) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_GCMP: + if (params->key_len != WLAN_KEY_LEN_GCMP) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_GCMP_256: + if (params->key_len != WLAN_KEY_LEN_GCMP_256) + return -EINVAL; + break; case WLAN_CIPHER_SUITE_WEP104: if (params->key_len != WLAN_KEY_LEN_WEP104) return -EINVAL; @@ -269,6 +287,18 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, if (params->key_len != WLAN_KEY_LEN_AES_CMAC) return -EINVAL; break; + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + if (params->key_len != WLAN_KEY_LEN_BIP_CMAC_256) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_128) + return -EINVAL; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_256) + return -EINVAL; + break; default: /* * We don't know anything about this algorithm, @@ -288,7 +318,13 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, return -EINVAL; case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_CCMP: + case WLAN_CIPHER_SUITE_CCMP_256: + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_AES_CMAC: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: if (params->seq_len != 6) return -EINVAL; break; -- cgit v1.2.3