From 9bcb084f0b648d032efdbb8226fe33663f8fca79 Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Tue, 10 Dec 2019 15:34:17 +0100 Subject: mac80211: Always show airtime debugfs file when TXQs are enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The AQL statistics are displayed in the 'airtime' station debugfs file, but that file was only shown if a driver has enabled the airtime fairness feature flag. Since AQL can be enabled without airtime fairness, let's expose the airtime file whenever TXQs are enabled, so the AQL data can be read. Signed-off-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20191210143417.142964-1-toke@redhat.com Signed-off-by: Johannes Berg --- net/mac80211/debugfs_sta.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index b3c9001d1f43..c190c29fe0dd 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c @@ -989,12 +989,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) DEBUGFS_ADD_COUNTER(rx_fragments, rx_stats.fragments); DEBUGFS_ADD_COUNTER(tx_filtered, status_stats.filtered); - if (local->ops->wake_tx_queue) + if (local->ops->wake_tx_queue) { DEBUGFS_ADD(aqm); - - if (wiphy_ext_feature_isset(local->hw.wiphy, - NL80211_EXT_FEATURE_AIRTIME_FAIRNESS)) DEBUGFS_ADD(airtime); + } debugfs_create_xul("driver_buffered_tids", 0400, sta->debugfs_dir, &sta->driver_buffered_tids); -- cgit From 50ff477a8639fa1fbbeecb5a6f2f8b6c5557ecec Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 25 Nov 2019 11:04:37 +0100 Subject: mac80211: add 802.11 encapsulation offloading support This patch adds a new transmit path for hardware that supports 802.11 encapsulation offloading. In those cases 802.3 frames get passed directly to the driver allowing the hardware to handle the encapsulation. Some features such as monitor mode and TKIP would break when encapsulation offloading is enabled. If any of these get enabled, the code will alwyas fallback to the normal sw encapsulation data path. The patch defines a secondary netdev_ops struct that the device gets assigned if 802.11 encap support is available and enabled. The driver needs to enable the support on a per vif basis if it finds that all pre-reqs are meet. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20191125100438.16539-1-john@phrozen.org [reword comments, remove SUPPORTS_80211_ENCAP HW flag, minor cleanups] Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 9 +++ net/mac80211/iface.c | 67 ++++++++++++++++++ net/mac80211/key.c | 11 +++ net/mac80211/status.c | 71 +++++++++++++++++++ net/mac80211/tx.c | 170 +++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 324 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ad15b3be8bb3..e3cf24cb4615 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -984,6 +984,8 @@ struct ieee80211_sub_if_data { } debugfs; #endif + bool hw_80211_encap; + /* must be last, dynamically sized area in this! */ struct ieee80211_vif vif; }; @@ -1762,6 +1764,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, + struct net_device *dev); void __ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev, u32 info_flags, @@ -1948,6 +1952,11 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, enum nl80211_band band, u32 txdata_flags); +/* sta_out needs to be checked for ERR_PTR() before using */ +int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct sta_info **sta_out); + static inline void ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int tid, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index af8b09214786..9b833e170c20 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1205,6 +1205,72 @@ static const struct net_device_ops ieee80211_monitorif_ops = { .ndo_get_stats64 = ieee80211_get_stats64, }; +static const struct net_device_ops ieee80211_dataif_8023_ops = { + .ndo_open = ieee80211_open, + .ndo_stop = ieee80211_stop, + .ndo_uninit = ieee80211_uninit, + .ndo_start_xmit = ieee80211_subif_start_xmit_8023, + .ndo_set_rx_mode = ieee80211_set_multicast_list, + .ndo_set_mac_address = ieee80211_change_mac, + .ndo_select_queue = ieee80211_netdev_select_queue, + .ndo_get_stats64 = ieee80211_get_stats64, +}; + +static void __ieee80211_set_hw_80211_encap(struct ieee80211_sub_if_data *sdata, + bool enable) +{ + sdata->dev->netdev_ops = enable ? &ieee80211_dataif_8023_ops : + &ieee80211_dataif_ops; + sdata->hw_80211_encap = enable; +} + +bool ieee80211_set_hw_80211_encap(struct ieee80211_vif *vif, bool enable) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *iter; + struct ieee80211_key *key; + + mutex_lock(&local->iflist_mtx); + list_for_each_entry(iter, &local->interfaces, list) { + struct ieee80211_sub_if_data *disable = NULL; + + if (vif->type == NL80211_IFTYPE_MONITOR) { + disable = iter; + __ieee80211_set_hw_80211_encap(iter, false); + } else if (iter->vif.type == NL80211_IFTYPE_MONITOR) { + disable = sdata; + enable = false; + } + if (disable) + sdata_dbg(disable, + "disable hw 80211 encap due to mon co-exist\n"); + } + mutex_unlock(&local->iflist_mtx); + + if (enable == sdata->hw_80211_encap) + return enable; + + if (!sdata->dev) + return false; + + if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && + (local->hw.wiphy->frag_threshold != (u32)-1)) + enable = false; + + mutex_lock(&sdata->local->key_mtx); + list_for_each_entry(key, &sdata->key_list, list) { + if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) + enable = false; + } + mutex_unlock(&sdata->local->key_mtx); + + __ieee80211_set_hw_80211_encap(sdata, enable); + + return enable; +} +EXPORT_SYMBOL(ieee80211_set_hw_80211_encap); + static void ieee80211_if_free(struct net_device *dev) { free_percpu(dev->tstats); @@ -1404,6 +1470,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->vif.bss_conf.idle = true; sdata->noack_map = 0; + sdata->hw_80211_encap = false; /* only monitor/p2p-device differ */ if (sdata->dev) { diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 0f889b919b06..9a3a6b95fa27 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -177,6 +177,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) } } + /* TKIP countermeasures don't work in encap offload mode */ + if (key->conf.cipher == WLAN_CIPHER_SUITE_TKIP && + sdata->hw_80211_encap) { + sdata_dbg(sdata, "TKIP is not allowed in hw 80211 encap mode\n"); + return -EINVAL; + } + ret = drv_set_key(key->local, SET_KEY, sdata, sta ? &sta->sta : NULL, &key->conf); @@ -203,6 +210,10 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->sta.addr : bcast_addr, ret); + /* cannot do software crypto with encapsulation offload */ + if (sdata->hw_80211_encap) + return -EINVAL; + out_unsupported: switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_WEP40: diff --git a/net/mac80211/status.c b/net/mac80211/status.c index b720feaf9a74..0344b82a34f5 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -1198,6 +1198,77 @@ void ieee80211_tx_rate_update(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_tx_rate_update); +void ieee80211_tx_status_8023(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct sk_buff *skb) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct sta_info *sta; + int retry_count; + int rates_idx; + bool acked; + + sdata = vif_to_sdata(vif); + + acked = info->flags & IEEE80211_TX_STAT_ACK; + rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); + + rcu_read_lock(); + + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) + goto counters_update; + + if (IS_ERR(sta)) + goto counters_update; + + if (!acked) + sta->status_stats.retry_failed++; + + if (rates_idx != -1) + sta->tx_stats.last_rate = info->status.rates[rates_idx]; + + sta->status_stats.retry_count += retry_count; + + if (ieee80211_hw_check(hw, REPORTS_TX_ACK_STATUS)) { + if (acked && vif->type == NL80211_IFTYPE_STATION) + ieee80211_sta_reset_conn_monitor(sdata); + + sta->status_stats.last_ack = jiffies; + if (info->flags & IEEE80211_TX_STAT_ACK) { + if (sta->status_stats.lost_packets) + sta->status_stats.lost_packets = 0; + + if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) + sta->status_stats.last_tdls_pkt_time = jiffies; + } else { + ieee80211_lost_packet(sta, info); + } + } + +counters_update: + rcu_read_unlock(); + ieee80211_led_tx(local); + + if (!(info->flags & IEEE80211_TX_STAT_ACK) && + !(info->flags & IEEE80211_TX_STAT_NOACK_TRANSMITTED)) + goto skip_stats_update; + + I802_DEBUG_INC(local->dot11TransmittedFrameCount); + if (is_multicast_ether_addr(skb->data)) + I802_DEBUG_INC(local->dot11MulticastTransmittedFrameCount); + if (retry_count > 0) + I802_DEBUG_INC(local->dot11RetryCount); + if (retry_count > 1) + I802_DEBUG_INC(local->dot11MultipleRetryCount); + +skip_stats_update: + ieee80211_report_used_skb(local, skb, false); + dev_kfree_skb(skb); +} +EXPORT_SYMBOL(ieee80211_tx_status_8023); + void ieee80211_report_low_ack(struct ieee80211_sta *pubsta, u32 num_packets) { struct sta_info *sta = container_of(pubsta, struct sta_info, sta); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b696b9136f4c..b31b5078f656 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1250,7 +1250,8 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local, (info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE)) return NULL; - if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) { + if (!(info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) && + unlikely(!ieee80211_is_data_present(hdr->frame_control))) { if ((!ieee80211_is_mgmt(hdr->frame_control) || ieee80211_is_bufferable_mmpdu(hdr->frame_control) || vif->type == NL80211_IFTYPE_STATION) && @@ -2351,9 +2352,9 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb) skb->data[14] == WLAN_TDLS_SNAP_RFTYPE; } -static int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, - struct sk_buff *skb, - struct sta_info **sta_out) +int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct sta_info **sta_out) { struct sta_info *sta; @@ -3607,6 +3608,9 @@ begin: else info->flags &= ~IEEE80211_TX_CTL_AMPDU; + if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) + goto encap_out; + if (info->control.flags & IEEE80211_TX_CTRL_FAST_XMIT) { struct sta_info *sta = container_of(txq->sta, struct sta_info, sta); @@ -3666,6 +3670,7 @@ begin: break; } +encap_out: IEEE80211_SKB_CB(skb)->control.vif = vif; if (local->airtime_flags & AIRTIME_USE_AQL) { @@ -4097,6 +4102,153 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, return NETDEV_TX_OK; } +static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, int led_len, + struct sta_info *sta, + bool txpending) +{ + struct ieee80211_local *local = sdata->local; + struct ieee80211_tx_control control = {}; + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_sta *pubsta = NULL; + unsigned long flags; + int q = info->hw_queue; + + if (ieee80211_queue_skb(local, sdata, sta, skb)) + return true; + + spin_lock_irqsave(&local->queue_stop_reason_lock, flags); + + if (local->queue_stop_reasons[q] || + (!txpending && !skb_queue_empty(&local->pending[q]))) { + if (txpending) + skb_queue_head(&local->pending[q], skb); + else + skb_queue_tail(&local->pending[q], skb); + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + return false; + } + + spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); + + if (sta && sta->uploaded) + pubsta = &sta->sta; + + control.sta = pubsta; + + drv_tx(local, &control, skb); + + return true; +} + +static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata, + struct net_device *dev, struct sta_info *sta, + struct sk_buff *skb) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ethhdr *ehdr = (struct ethhdr *)skb->data; + struct ieee80211_local *local = sdata->local; + bool authorized = false; + bool multicast; + unsigned char *ra = ehdr->h_dest; + + if (IS_ERR(sta) || (sta && !sta->uploaded)) + sta = NULL; + + if (sdata->vif.type == NL80211_IFTYPE_STATION && + (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER))) + ra = sdata->u.mgd.bssid; + + if (!is_valid_ether_addr(ra)) + goto out_free; + + multicast = is_multicast_ether_addr(ra); + + if (sta) + authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED); + + if (!multicast && !authorized && + (ehdr->h_proto != sdata->control_port_protocol || + !ether_addr_equal(sdata->vif.addr, ehdr->h_source))) + goto out_free; + + if (multicast && sdata->vif.type == NL80211_IFTYPE_AP && + !atomic_read(&sdata->u.ap.num_mcast_sta)) + goto out_free; + + if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)) && + test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) + goto out_free; + + if (unlikely(!multicast && skb->sk && + skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) + ieee80211_store_ack_skb(local, skb, &info->flags); + + memset(info, 0, sizeof(*info)); + + if (unlikely(sdata->control_port_protocol == ehdr->h_proto)) { + if (sdata->control_port_no_encrypt) + info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; + info->control.flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO; + } + + if (multicast) + info->flags |= IEEE80211_TX_CTL_NO_ACK; + + info->hw_queue = sdata->vif.hw_queue[skb_get_queue_mapping(skb)]; + + ieee80211_tx_stats(dev, skb->len); + + if (sta) { + sta->tx_stats.bytes[skb_get_queue_mapping(skb)] += skb->len; + sta->tx_stats.packets[skb_get_queue_mapping(skb)]++; + } + + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + sdata = container_of(sdata->bss, + struct ieee80211_sub_if_data, u.ap); + + info->control.flags |= IEEE80211_TX_CTRL_HW_80211_ENCAP; + info->control.vif = &sdata->vif; + + ieee80211_tx_8023(sdata, skb, skb->len, sta, false); + + return; + +out_free: + kfree_skb(skb); +} + +netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb, + struct net_device *dev) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct sta_info *sta; + + if (WARN_ON(!sdata->hw_80211_encap)) { + kfree_skb(skb); + return NETDEV_TX_OK; + } + + if (unlikely(skb->len < ETH_HLEN)) { + kfree_skb(skb); + return NETDEV_TX_OK; + } + + rcu_read_lock(); + + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) + kfree_skb(skb); + else + ieee80211_8023_xmit(sdata, dev, sta, skb); + + rcu_read_unlock(); + + return NETDEV_TX_OK; +} + struct sk_buff * ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u32 info_flags) @@ -4175,6 +4327,16 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, } info->band = chanctx_conf->def.chan->band; result = ieee80211_tx(sdata, NULL, skb, true, 0); + } else if (info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP) { + if (ieee80211_lookup_ra_sta(sdata, skb, &sta)) { + dev_kfree_skb(skb); + return true; + } + + if (IS_ERR(sta) || (sta && !sta->uploaded)) + sta = NULL; + + result = ieee80211_tx_8023(sdata, skb, skb->len, sta, true); } else { struct sk_buff_head skbs; -- cgit From 1ee7826ab68f7e9fa1a01533983acf6a6f62e297 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Sun, 15 Dec 2019 09:23:48 -0600 Subject: mac80211: Remove redundant assertion In wiphy_to_ieee80211_hw, the assertion to check if wiphy is NULL is repeated in wiphy_priv. The patch removes the duplicated BUG_ON check. Signed-off-by: Aditya Pakki Link: https://lore.kernel.org/r/20191215152348.20912-1-pakki001@umn.edu Signed-off-by: Johannes Berg --- net/mac80211/util.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 32a7a53833c0..780df3e9092e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -39,7 +39,6 @@ const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid; struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) { struct ieee80211_local *local; - BUG_ON(!wiphy); local = wiphy_priv(wiphy); return &local->hw; -- cgit From e322c07f8371164eaa9e76d46d70b1b88ad5d153 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Wed, 27 Nov 2019 17:36:15 +0100 Subject: mac80211: debugfs: improve airtime_flags handler readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Improve airtime_flags debugfs handler readability reporting configured airtime flags in both numeric and human readable manner Signed-off-by: Lorenzo Bianconi Acked-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/9df7e40b45e95bb0b320317831455beaed1ee3ee.1574872357.git.lorenzo@kernel.org [remove AQL since it's no longer there] Signed-off-by: Johannes Berg --- net/mac80211/debugfs.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ad41d74530c6..54080290d6e2 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -150,6 +150,59 @@ static const struct file_operations aqm_ops = { .llseek = default_llseek, }; +static ssize_t airtime_flags_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + char buf[128] = {}, *pos, *end; + + pos = buf; + end = pos + sizeof(buf) - 1; + + if (local->airtime_flags & AIRTIME_USE_TX) + pos += scnprintf(pos, end - pos, "AIRTIME_TX\t(%lx)\n", + AIRTIME_USE_TX); + if (local->airtime_flags & AIRTIME_USE_RX) + pos += scnprintf(pos, end - pos, "AIRTIME_RX\t(%lx)\n", + AIRTIME_USE_RX); + + return simple_read_from_buffer(user_buf, count, ppos, buf, + strlen(buf)); +} + +static ssize_t airtime_flags_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_local *local = file->private_data; + char buf[16]; + size_t len; + + if (count > sizeof(buf)) + return -EINVAL; + + if (copy_from_user(buf, user_buf, count)) + return -EFAULT; + + buf[sizeof(buf) - 1] = 0; + len = strlen(buf); + if (len > 0 && buf[len - 1] == '\n') + buf[len - 1] = 0; + + if (kstrtou16(buf, 0, &local->airtime_flags)) + return -EINVAL; + + return count; +} + +static const struct file_operations airtime_flags_ops = { + .write = airtime_flags_write, + .read = airtime_flags_read, + .open = simple_open, + .llseek = default_llseek, +}; + static ssize_t aql_txq_limit_read(struct file *file, char __user *user_buf, size_t count, @@ -522,8 +575,7 @@ void debugfs_hw_add(struct ieee80211_local *local) if (local->ops->wake_tx_queue) DEBUGFS_ADD_MODE(aqm, 0600); - debugfs_create_u16("airtime_flags", 0600, - phyd, &local->airtime_flags); + DEBUGFS_ADD_MODE(airtime_flags, 0600); DEBUGFS_ADD(aql_txq_limit); debugfs_create_u32("aql_threshold", 0600, -- cgit From dd56e90230334752221473c06ff40cac44563a70 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 17 Dec 2019 15:19:19 +0100 Subject: mac80211: add handling for BSS color It is now possible to propagate BSS color settings into the subsystem. Lets make mac80211 also handle them so that we can send them further down the stack into the drivers. We drop the old bss_color field and change iwlwifi to use the new he_bss_color struct. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20191217141921.8114-2-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 5 ++++- net/mac80211/mlme.c | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4fb7f1f12109..a11bd1669c13 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -981,7 +981,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, BSS_CHANGED_P2P_PS | BSS_CHANGED_TXPOWER | BSS_CHANGED_TWT | - BSS_CHANGED_HE_OBSS_PD; + BSS_CHANGED_HE_OBSS_PD | + BSS_CHANGED_HE_BSS_COLOR; int err; int prev_beacon_int; @@ -1054,6 +1055,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, sdata->vif.bss_conf.twt_responder = params->twt_responder; memcpy(&sdata->vif.bss_conf.he_obss_pd, ¶ms->he_obss_pd, sizeof(struct ieee80211_he_obss_pd)); + memcpy(&sdata->vif.bss_conf.he_bss_color, ¶ms->he_bss_color, + sizeof(struct ieee80211_he_bss_color)); sdata->vif.bss_conf.ssid_len = params->ssid_len; if (params->ssid_len) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5fa13176036f..6e4099009eab 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3368,9 +3368,16 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, } if (bss_conf->he_support) { - bss_conf->bss_color = + bss_conf->he_bss_color.color = le32_get_bits(elems->he_operation->he_oper_params, IEEE80211_HE_OPERATION_BSS_COLOR_MASK); + bss_conf->he_bss_color.partial = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_PARTIAL_BSS_COLOR); + bss_conf->he_bss_color.disabled = + le32_get_bits(elems->he_operation->he_oper_params, + IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED); + changed |= BSS_CHANGED_HE_BSS_COLOR; bss_conf->htc_trig_based_pkt_ext = le32_get_bits(elems->he_operation->he_oper_params, -- cgit From 5972fa15b923df6ccd02ae6e7095a6b08b5fca52 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 18 Dec 2019 15:27:36 +0100 Subject: mac80211: fix tx status for no ack cases Before this patch, frames which where successfully transmitted without requiring acks where accounted as lost frames. Signed-off-by: Markus Theil Link: https://lore.kernel.org/r/20191218142736.15843-1-markus.theil@tu-ilmenau.de Signed-off-by: Johannes Berg --- net/mac80211/status.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 0344b82a34f5..c9b90d38c54d 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -888,6 +888,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, int rates_idx; bool send_to_cooked; bool acked; + bool noack_success; struct ieee80211_bar *bar; int shift = 0; int tid = IEEE80211_NUM_TIDS; @@ -906,6 +907,8 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, clear_sta_flag(sta, WLAN_STA_SP); acked = !!(info->flags & IEEE80211_TX_STAT_ACK); + noack_success = !!(info->flags & + IEEE80211_TX_STAT_NOACK_TRANSMITTED); /* mesh Peer Service Period support */ if (ieee80211_vif_is_mesh(&sta->sdata->vif) && @@ -970,12 +973,12 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, ieee80211_handle_filtered_frame(local, sta, skb); return; } else { - if (!acked) + if (!acked && !noack_success) sta->status_stats.retry_failed++; sta->status_stats.retry_count += retry_count; if (ieee80211_is_data_present(fc)) { - if (!acked) + if (!acked && !noack_success) sta->status_stats.msdu_failed[tid]++; sta->status_stats.msdu_retries[tid] += @@ -1013,7 +1016,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, } if (ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { - if (info->flags & IEEE80211_TX_STAT_ACK) { + if (acked) { if (sta->status_stats.lost_packets) sta->status_stats.lost_packets = 0; @@ -1021,6 +1024,8 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) sta->status_stats.last_tdls_pkt_time = jiffies; + } else if (noack_success) { + /* nothing to do here, do not account as lost */ } else { ieee80211_lost_packet(sta, info); } @@ -1141,7 +1146,7 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, sta = container_of(pubsta, struct sta_info, sta); - if (!acked) + if (!acked && !noack_success) sta->status_stats.retry_failed++; sta->status_stats.retry_count += retry_count; @@ -1156,6 +1161,8 @@ void ieee80211_tx_status_ext(struct ieee80211_hw *hw, sta->status_stats.last_tdls_pkt_time = jiffies; } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { return; + } else if (noack_success) { + /* nothing to do here, do not account as lost */ } else { ieee80211_lost_packet(sta, info); } -- cgit From 30b2f0be23fb40e58d0ad2caf8702c2a44cda2e1 Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Mon, 13 Jan 2020 21:59:40 -0800 Subject: mac80211: add ieee80211_is_any_nullfunc() commit 08a5bdde3812 ("mac80211: consider QoS Null frames for STA_NULLFUNC_ACKED") Fixed a bug where we failed to take into account a nullfunc frame can be either non-QoS or QoS. It turns out there is at least one more bug in ieee80211_sta_tx_notify(), introduced in commit 7b6ddeaf27ec ("mac80211: use QoS NDP for AP probing"), where we forgot to check for the QoS variant and so assumed the QoS nullfunc frame never went out Fix this by adding a helper ieee80211_is_any_nullfunc() which consolidates the check for non-QoS and QoS nullfunc frames. Replace existing compound conditionals and add a couple more missing checks for QoS variant. Signed-off-by: Thomas Pedersen Link: https://lore.kernel.org/r/20200114055940.18502-3-thomas@adapt-ip.com Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 2 +- net/mac80211/rx.c | 8 +++----- net/mac80211/status.c | 5 ++--- net/mac80211/tx.c | 2 +- 4 files changed, 7 insertions(+), 10 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6e4099009eab..cb6fd0a09e07 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2460,7 +2460,7 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, if (!ieee80211_is_data(hdr->frame_control)) return; - if (ieee80211_is_nullfunc(hdr->frame_control) && + if (ieee80211_is_any_nullfunc(hdr->frame_control) && sdata->u.mgd.probe_send_count > 0) { if (ack) ieee80211_sta_reset_conn_monitor(sdata); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0e05ff037672..619c223f1cde 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1450,8 +1450,7 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) return RX_CONTINUE; if (ieee80211_is_ctl(hdr->frame_control) || - ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control) || + ieee80211_is_any_nullfunc(hdr->frame_control) || is_multicast_ether_addr(hdr->addr1)) return RX_CONTINUE; @@ -1838,8 +1837,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) * Drop (qos-)data::nullfunc frames silently, since they * are used only to control station power saving mode. */ - if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { + if (ieee80211_is_any_nullfunc(hdr->frame_control)) { I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); /* @@ -2319,7 +2317,7 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) /* Drop unencrypted frames if key is set. */ if (unlikely(!ieee80211_has_protected(fc) && - !ieee80211_is_nullfunc(fc) && + !ieee80211_is_any_nullfunc(fc) && ieee80211_is_data(fc) && rx->key)) return -EACCES; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index c9b90d38c54d..22512805eafb 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -643,8 +643,7 @@ static void ieee80211_report_ack_skb(struct ieee80211_local *local, rcu_read_lock(); sdata = ieee80211_sdata_from_skb(local, skb); if (sdata) { - if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) + if (ieee80211_is_any_nullfunc(hdr->frame_control)) cfg80211_probe_status(sdata->dev, hdr->addr1, cookie, acked, info->status.ack_signal, @@ -1061,7 +1060,7 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw, I802_DEBUG_INC(local->dot11FailedCount); } - if ((ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) && + if (ieee80211_is_any_nullfunc(fc) && ieee80211_has_pm(fc) && ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS) && !(info->flags & IEEE80211_TX_CTL_INJECTED) && diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index c56d801e708f..4296d9d71311 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -297,7 +297,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && !ieee80211_is_probe_req(hdr->frame_control) && - !ieee80211_is_nullfunc(hdr->frame_control)) + !ieee80211_is_any_nullfunc(hdr->frame_control)) /* * When software scanning only nullfunc frames (to notify * the sleep state to the AP) and probe requests (for the -- cgit From 3c706b973b51ed45e4c0f40642cfb650dfc804d7 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Mon, 3 Feb 2020 13:28:12 +0100 Subject: mac80211: fix 11w when using encapsulation offloading The 802.11 encapsulation returned early when setting up the keys in case offloading was enabled. This causes ieee802.11w to not work anymore. Fix this by moving the check for offloading into the switch/case construct and allowing CCMP/GCMP keys. With this patch applied ieee80211w works again when enabling offloading. Fixes: 50ff477a8639 ("mac80211: add 802.11 encapsulation offloading support") Reported-by: Maharaja Kennadyrajan Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20200203122812.18993-1-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/key.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 9a3a6b95fa27..54934eff4ac1 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c @@ -210,10 +210,6 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) key->conf.keyidx, sta ? sta->sta.addr : bcast_addr, ret); - /* cannot do software crypto with encapsulation offload */ - if (sdata->hw_80211_encap) - return -EINVAL; - out_unsupported: switch (key->conf.cipher) { case WLAN_CIPHER_SUITE_WEP40: @@ -221,12 +217,20 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) 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: + /* We cannot do software crypto of data frames with + * encapsulation offload enabled. However for 802.11w to + * function properly we need cmac/gmac keys. + */ + if (sdata->hw_80211_encap) + return -EINVAL; + /* Fall through */ + 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: - case WLAN_CIPHER_SUITE_GCMP: - case WLAN_CIPHER_SUITE_GCMP_256: /* all of these we can do in software - if driver can */ if (ret == 1) return 0; -- cgit From 75e296e9b22aef6fa467523ace87ef623dac1fad Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jan 2020 13:12:39 +0200 Subject: mac80211: simplify and improve HT/VHT/HE disable code Check early on that a device has support for QoS (at least 4 queues) when it supports HT/VHT/HE, so we don't have to check this while connecting. This lets us clean up the code there: move some of it into channel preparation to clean up a bit more, and then change the logic to only check the "wmm_used" flag. Additionally, disable HE consistently when VHT is disabled. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-3-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/main.c | 5 +++++ net/mac80211/mlme.c | 62 ++++++++++++++++++++++++++++------------------------- 2 files changed, 38 insertions(+), 29 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4c2b5ba3ac09..34728cf94172 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -981,6 +981,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!supp_he) supp_he = !!ieee80211_get_he_sta_cap(sband); + /* HT, VHT, HE require QoS, thus >= 4 queues */ + if (WARN_ON(local->hw.queues < IEEE80211_NUM_ACS && + (supp_ht || supp_vht || supp_he))) + return -EINVAL; + if (!sband->ht_cap.ht_supported) continue; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cb6fd0a09e07..f076e73314a6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -164,7 +164,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, chandef->center_freq1 = channel->center_freq; if (!ht_oper || !sta_ht_cap.ht_supported) { - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT | + IEEE80211_STA_DISABLE_HE; goto out; } @@ -185,7 +187,9 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata, "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n", channel->center_freq, ht_cfreq, ht_oper->primary_chan, channel->band); - ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT; + ret = IEEE80211_STA_DISABLE_HT | + IEEE80211_STA_DISABLE_VHT | + IEEE80211_STA_DISABLE_HE; goto out; } @@ -301,7 +305,8 @@ out: IEEE80211_CHAN_DISABLED)) { if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) { ret = IEEE80211_STA_DISABLE_HT | - IEEE80211_STA_DISABLE_VHT; + IEEE80211_STA_DISABLE_VHT | + IEEE80211_STA_DISABLE_HE; break; } @@ -393,6 +398,7 @@ static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata, if (flags != (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT | + IEEE80211_STA_DISABLE_HE | IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_80P80MHZ | IEEE80211_STA_DISABLE_160MHZ)) || @@ -4760,10 +4766,22 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, IEEE80211_STA_DISABLE_80P80MHZ | IEEE80211_STA_DISABLE_160MHZ); + /* disable HT/VHT/HE if we don't support them */ + if (!sband->ht_cap.ht_supported) { + ifmgd->flags |= IEEE80211_STA_DISABLE_HT; + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + ifmgd->flags |= IEEE80211_STA_DISABLE_HE; + } + + if (!sband->vht_cap.vht_supported) + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + + if (!ieee80211_get_he_sta_cap(sband)) + ifmgd->flags |= IEEE80211_STA_DISABLE_HE; + rcu_read_lock(); - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) && - sband->ht_cap.ht_supported) { + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { const u8 *ht_oper_ie, *ht_cap_ie; ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION); @@ -4780,8 +4798,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, } } - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && - sband->vht_cap.vht_supported) { + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { const u8 *vht_oper_ie, *vht_cap; vht_oper_ie = ieee80211_bss_get_ie(cbss, @@ -4791,9 +4808,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, if (vht_oper && !ht_oper) { vht_oper = NULL; sdata_info(sdata, - "AP advertised VHT without HT, disabling both\n"); + "AP advertised VHT without HT, disabling HT/VHT/HE\n"); ifmgd->flags |= IEEE80211_STA_DISABLE_HT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + ifmgd->flags |= IEEE80211_STA_DISABLE_HE; } vht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_VHT_CAPABILITY); @@ -4803,9 +4821,6 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, } } - if (!ieee80211_get_he_sta_cap(sband)) - ifmgd->flags |= IEEE80211_STA_DISABLE_HE; - if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) { const struct cfg80211_bss_ies *ies; const u8 *he_oper_ie; @@ -5304,27 +5319,15 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, } } - /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; - if (!sband->ht_cap.ht_supported || - local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || - ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { - ifmgd->flags |= IEEE80211_STA_DISABLE_HT; - if (!bss->wmm_used && - !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) - netdev_info(sdata->dev, - "disabling HT as WMM/QoS is not supported by the AP\n"); - } - /* disable VHT if we don't support it or the AP doesn't use WMM */ - if (!sband->vht_cap.vht_supported || - local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used || - ifmgd->flags & IEEE80211_STA_DISABLE_WMM) { + /* also disable HT/VHT/HE if the AP doesn't use WMM */ + if (!bss->wmm_used) { + ifmgd->flags |= IEEE80211_STA_DISABLE_HT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; - if (!bss->wmm_used && - !(ifmgd->flags & IEEE80211_STA_DISABLE_WMM)) - netdev_info(sdata->dev, - "disabling VHT as WMM/QoS is not supported by the AP\n"); + ifmgd->flags |= IEEE80211_STA_DISABLE_HE; + netdev_info(sdata->dev, + "disabling HT/VHT/HE as WMM/QoS is not supported by the AP\n"); } memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); @@ -5456,6 +5459,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (req->flags & ASSOC_REQ_DISABLE_HT) { ifmgd->flags |= IEEE80211_STA_DISABLE_HT; ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + ifmgd->flags |= IEEE80211_STA_DISABLE_HE; } if (req->flags & ASSOC_REQ_DISABLE_VHT) -- cgit From e4d005b80deeb053526ca089510bf2e20473ef62 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jan 2020 13:12:40 +0200 Subject: mac80211: refactor extended element parsing This code was really ugly, refactor it a bit to make it more readable. While at it, use sizeof() and fix the UORA element length check bug. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-4-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/util.c | 75 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 27 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 780df3e9092e..72039c8dbc38 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -890,6 +890,51 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_queue_delayed_work); +static void ieee80211_parse_extension_element(u32 *crc, + const struct element *elem, + struct ieee802_11_elems *elems) +{ + const void *data = elem->data + 1; + u8 len = elem->datalen - 1; + + switch (elem->data[0]) { + case WLAN_EID_EXT_HE_MU_EDCA: + if (len == sizeof(*elems->mu_edca_param_set)) { + elems->mu_edca_param_set = data; + if (crc) + *crc = crc32_be(*crc, (void *)elem, + elem->datalen + 2); + } + break; + case WLAN_EID_EXT_HE_CAPABILITY: + elems->he_cap = data; + elems->he_cap_len = len; + break; + case WLAN_EID_EXT_HE_OPERATION: + if (len >= sizeof(*elems->he_operation) && + len == ieee80211_he_oper_size(data) - 1) + elems->he_operation = data; + break; + case WLAN_EID_EXT_UORA: + if (len == 1) + elems->uora_element = data; + break; + case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME: + if (len == 3) + elems->max_channel_switch_time = data; + break; + case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION: + if (len == sizeof(*elems->mbssid_config_ie)) + elems->mbssid_config_ie = data; + break; + case WLAN_EID_EXT_HE_SPR: + if (len >= sizeof(*elems->he_spr) && + len >= ieee80211_he_spr_size(data)) + elems->he_spr = data; + break; + } +} + static u32 _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, struct ieee802_11_elems *elems, @@ -1220,33 +1265,9 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elems->max_idle_period_ie = (void *)pos; break; case WLAN_EID_EXTENSION: - if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA && - elen >= (sizeof(*elems->mu_edca_param_set) + 1)) { - elems->mu_edca_param_set = (void *)&pos[1]; - if (calc_crc) - crc = crc32_be(crc, pos - 2, elen + 2); - } else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) { - elems->he_cap = (void *)&pos[1]; - elems->he_cap_len = elen - 1; - } else if (pos[0] == WLAN_EID_EXT_HE_OPERATION && - elen >= sizeof(*elems->he_operation) && - elen >= ieee80211_he_oper_size(&pos[1])) { - elems->he_operation = (void *)&pos[1]; - } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) { - elems->uora_element = (void *)&pos[1]; - } else if (pos[0] == - WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME && - elen == 4) { - elems->max_channel_switch_time = pos + 1; - } else if (pos[0] == - WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION && - elen == 3) { - elems->mbssid_config_ie = (void *)&pos[1]; - } else if (pos[0] == WLAN_EID_EXT_HE_SPR && - elen >= sizeof(*elems->he_spr) && - elen >= ieee80211_he_spr_size(&pos[1])) { - elems->he_spr = (void *)&pos[1]; - } + ieee80211_parse_extension_element(calc_crc ? + &crc : NULL, + elem, elems); break; default: break; -- cgit From b5db1acab19b99da5b30042133734b01f65b5900 Mon Sep 17 00:00:00 2001 From: Haim Dreyfuss Date: Fri, 31 Jan 2020 13:12:44 +0200 Subject: mac80211: check whether HE connection is allowed by the reg domain The wireless device might be capable to connect HE as well as the AP. However, the regulatory domain might forbid it. Check whether the regulatory domain allows HE connection when considering if HE IE should be added. Also, add it when setting our peer capability. Signed-off-by: Haim Dreyfuss Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-8-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index f076e73314a6..152577cc2213 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -313,6 +313,10 @@ out: ret |= ieee80211_chandef_downgrade(chandef); } + if (!cfg80211_chandef_usable(sdata->wdev.wiphy, chandef, + IEEE80211_CHAN_NO_HE)) + ret |= IEEE80211_STA_DISABLE_HE; + if (chandef->width != vht_chandef.width && !tracking) sdata_info(sdata, "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n"); @@ -622,10 +626,21 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, { u8 *pos; const struct ieee80211_sta_he_cap *he_cap = NULL; + struct ieee80211_chanctx_conf *chanctx_conf; u8 he_cap_size; + bool reg_cap = false; + + rcu_read_lock(); + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); + if (!WARN_ON_ONCE(!chanctx_conf)) + reg_cap = cfg80211_chandef_usable(sdata->wdev.wiphy, + &chanctx_conf->def, + IEEE80211_CHAN_NO_HE); + + rcu_read_unlock(); he_cap = ieee80211_get_he_sta_cap(sband); - if (!he_cap) + if (!he_cap || !reg_cap) return; /* -- cgit From 07b83d2ecd2f812c32d1f852f853375f50e1ccf2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jan 2020 13:12:46 +0200 Subject: mac80211: allow changing TX-related netdev features Set ndev->hw_features as well as ndev->features to allow changing the TX-related features with ethtool. We cannot (yet) change RX-related features since that requires telling the driver about it and we have no API for that yet. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-10-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 7 +++++++ net/mac80211/iface.c | 4 +++- net/mac80211/main.c | 6 +----- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index e3cf24cb4615..b89543269f51 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1729,6 +1729,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_csa_settings *params); /* interface handling */ +#define MAC80211_SUPPORTED_FEATURES_TX (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | \ + NETIF_F_HW_CSUM | NETIF_F_SG | \ + NETIF_F_HIGHDMA | NETIF_F_GSO_SOFTWARE) +#define MAC80211_SUPPORTED_FEATURES_RX (NETIF_F_RXCSUM) +#define MAC80211_SUPPORTED_FEATURES (MAC80211_SUPPORTED_FEATURES_TX | \ + MAC80211_SUPPORTED_FEATURES_RX) + int ieee80211_iface_init(void); void ieee80211_iface_exit(void); int ieee80211_if_add(struct ieee80211_local *local, const char *name, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 9b833e170c20..99d913a6e651 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -8,7 +8,7 @@ * Copyright 2008, Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018-2019 Intel Corporation */ #include #include @@ -1938,6 +1938,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, sdata->u.mgd.use_4addr = params->use_4addr; ndev->features |= local->hw.netdev_features; + ndev->hw_features |= ndev->features & + MAC80211_SUPPORTED_FEATURES_TX; netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 34728cf94172..287dd0588476 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -872,7 +872,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) enum nl80211_band band; int channels, max_bitrates; bool supp_ht, supp_vht, supp_he; - netdev_features_t feature_whitelist; struct cfg80211_chan_def dflt_chandef = {}; if (ieee80211_hw_check(hw, QUEUE_CONTROL) && @@ -931,10 +930,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) } /* Only HW csum features are currently compatible with mac80211 */ - feature_whitelist = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_HW_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA | - NETIF_F_GSO_SOFTWARE | NETIF_F_RXCSUM; - if (WARN_ON(hw->netdev_features & ~feature_whitelist)) + if (WARN_ON(hw->netdev_features & ~MAC80211_SUPPORTED_FEATURES)) return -EINVAL; if (hw->max_report_rates == 0) -- cgit From 4a65cc2437ce4a643c24b357d849e3ff773efed1 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 31 Jan 2020 13:12:47 +0200 Subject: mac80211: make ieee80211_wep_init() return void This function always returns 0, so there's no point in returning int. Make it void and remove the impossible error-path when calling it. Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-11-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/main.c | 5 +---- net/mac80211/wep.c | 4 +--- net/mac80211/wep.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 287dd0588476..d91bcef738dc 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1185,10 +1185,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (!local->hw.weight_multiplier) local->hw.weight_multiplier = 1; - result = ieee80211_wep_init(local); - if (result < 0) - wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", - result); + ieee80211_wep_init(local); local->hw.conf.flags = IEEE80211_CONF_IDLE; diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index b75c2c54e665..9a6e11d7b4db 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -22,12 +22,10 @@ #include "wep.h" -int ieee80211_wep_init(struct ieee80211_local *local) +void ieee80211_wep_init(struct ieee80211_local *local) { /* start WEP IV from a random value */ get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN); - - return 0; } static inline bool ieee80211_wep_weak_iv(u32 iv, int keylen) diff --git a/net/mac80211/wep.h b/net/mac80211/wep.h index 997a034233c2..4ffe83554c67 100644 --- a/net/mac80211/wep.h +++ b/net/mac80211/wep.h @@ -13,7 +13,7 @@ #include "ieee80211_i.h" #include "key.h" -int ieee80211_wep_init(struct ieee80211_local *local); +void ieee80211_wep_init(struct ieee80211_local *local); int ieee80211_wep_encrypt_data(struct arc4_ctx *ctx, u8 *rc4key, size_t klen, u8 *data, size_t data_len); int ieee80211_wep_encrypt(struct ieee80211_local *local, -- cgit From 8cadb207145c7e2fa45bbec2319cb84aec5da988 Mon Sep 17 00:00:00 2001 From: Daniel Gabay Date: Fri, 31 Jan 2020 13:12:52 +0200 Subject: mac80211: update condition for HE disablement Disable HE if the beacon does not contain an HE operation IE. Signed-off-by: Daniel Gabay Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-16-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 152577cc2213..16b678bea106 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -313,8 +313,8 @@ out: ret |= ieee80211_chandef_downgrade(chandef); } - if (!cfg80211_chandef_usable(sdata->wdev.wiphy, chandef, - IEEE80211_CHAN_NO_HE)) + if (!he_oper || !cfg80211_chandef_usable(sdata->wdev.wiphy, chandef, + IEEE80211_CHAN_NO_HE)) ret |= IEEE80211_STA_DISABLE_HE; if (chandef->width != vht_chandef.width && !tracking) -- cgit From 2ff69b0e25f4faa442f28b652a909f1b75206803 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jan 2020 13:31:11 +0200 Subject: mac80211: remove supported channels element in 6 GHz if ECSA support We should not include the supported channels element if we have (advertise) support for extended channel switching. To avoid any interop issues because we always added it in the past, obey this restriction only in the (new) 6 GHz band. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131113111.893106-1-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 16b678bea106..2733555a5f3b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -671,6 +671,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *chan; u32 rates = 0; + struct element *ext_capa = NULL; + + /* we know it's writable, cast away the const */ + if (assoc_data->ie_len) + ext_capa = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, + assoc_data->ie, + assoc_data->ie_len); sdata_assert_lock(sdata); @@ -821,7 +828,15 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) *pos++ = ieee80211_chandef_max_power(&chanctx_conf->def); } - if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { + /* + * Per spec, we shouldn't include the list of channels if we advertise + * support for extended channel switching, but we've always done that; + * (for now?) apply this restriction only on the (new) 6 GHz band. + */ + if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT && + (sband->band != NL80211_BAND_6GHZ || + !ext_capa || ext_capa->datalen < 1 || + !(ext_capa->data[0] & WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING))) { /* TODO: get this in reg domain format */ pos = skb_put(skb, 2 * sband->n_channels + 2); *pos++ = WLAN_EID_SUPPORTED_CHANNELS; @@ -835,18 +850,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) /* Set MBSSID support for HE AP if needed */ if (ieee80211_hw_check(&local->hw, SUPPORTS_ONLY_HE_MULTI_BSSID) && - !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len) { - struct element *elem; - - /* we know it's writable, cast away the const */ - elem = (void *)cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, - assoc_data->ie, - assoc_data->ie_len); - - /* We can probably assume both always true */ - if (elem && elem->datalen >= 3) - elem->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT; - } + !(ifmgd->flags & IEEE80211_STA_DISABLE_HE) && assoc_data->ie_len && + ext_capa && ext_capa->datalen >= 3) + ext_capa->data[2] |= WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT; /* if present, add any custom IEs that go before HT */ if (assoc_data->ie_len) { -- cgit From cf2c9cc3980fb2aa5a71ebbe982739987100db76 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 31 Jan 2020 13:12:41 +0200 Subject: mac80211: set station bandwidth from HE capability Set the station bandwidth in HE capability parsing and from HE capability as the HT/VHT information will not be present on the 6 GHz band. Signed-off-by: Johannes Berg Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-5-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/he.c | 4 ++++ net/mac80211/vht.c | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/he.c b/net/mac80211/he.c index 736da0035135..5245c19f39bf 100644 --- a/net/mac80211/he.c +++ b/net/mac80211/he.c @@ -3,6 +3,7 @@ * HE handling * * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2019 Intel Corporation */ #include "ieee80211_i.h" @@ -49,6 +50,9 @@ ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, he_ppe_size); he_cap->has_he = true; + + sta->cur_max_bandwidth = ieee80211_sta_cap_rx_bw(sta); + sta->sta.bandwidth = ieee80211_sta_cur_vht_bw(sta); } void diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index ccdcb9ad9ac7..a7cd22594a14 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -333,11 +333,33 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, } } +/* FIXME: move this to some better location - parses HE now */ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cap_rx_bw(struct sta_info *sta) { struct ieee80211_sta_vht_cap *vht_cap = &sta->sta.vht_cap; + struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; u32 cap_width; + if (he_cap->has_he) { + u8 info = he_cap->he_cap_elem.phy_cap_info[0]; + + if (sta->sdata->vif.bss_conf.chandef.chan->band == + NL80211_BAND_2GHZ) { + if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_IN_2G) + return IEEE80211_STA_RX_BW_40; + else + return IEEE80211_STA_RX_BW_20; + } + + if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G || + info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) + return IEEE80211_STA_RX_BW_160; + else if (info & IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G) + return IEEE80211_STA_RX_BW_80; + + return IEEE80211_STA_RX_BW_20; + } + if (!vht_cap->vht_supported) return sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? IEEE80211_STA_RX_BW_40 : @@ -433,6 +455,7 @@ ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width) } } +/* FIXME: rename/move - this deals with everything not just VHT */ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; -- cgit From f46209b9ff76e7a4194c40a2994c9f115d2227b5 Mon Sep 17 00:00:00 2001 From: Tova Mussai Date: Fri, 31 Jan 2020 13:12:45 +0200 Subject: mac80211: HE: set RX NSS In case of HE, the RX NSS is taken from the HE capabilities. If the supported NSS capabilities that are reported by AP for HE mode in the HE Capabilities element are different from the NSS capabilities that are reported by AP for the VHT mode in the VHT Capabilities element, use the lowest supported NSS to not get all the values confused. Signed-off-by: Tova Mussai Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-9-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/vht.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index a7cd22594a14..632f07401850 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c @@ -481,12 +481,40 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta) void ieee80211_sta_set_rx_nss(struct sta_info *sta) { - u8 ht_rx_nss = 0, vht_rx_nss = 0; + u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss; /* if we received a notification already don't overwrite it */ if (sta->sta.rx_nss) return; + if (sta->sta.he_cap.has_he) { + int i; + u8 rx_mcs_80 = 0, rx_mcs_160 = 0; + const struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; + u16 mcs_160_map = + le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_160); + u16 mcs_80_map = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); + + for (i = 7; i >= 0; i--) { + u8 mcs_160 = (mcs_160_map >> (2 * i)) & 3; + + if (mcs_160 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + rx_mcs_160 = i + 1; + break; + } + } + for (i = 7; i >= 0; i--) { + u8 mcs_80 = (mcs_80_map >> (2 * i)) & 3; + + if (mcs_80 != IEEE80211_VHT_MCS_NOT_SUPPORTED) { + rx_mcs_80 = i + 1; + break; + } + } + + he_rx_nss = min(rx_mcs_80, rx_mcs_160); + } + if (sta->sta.ht_cap.ht_supported) { if (sta->sta.ht_cap.mcs.rx_mask[0]) ht_rx_nss++; @@ -516,8 +544,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) /* FIXME: consider rx_highest? */ } - ht_rx_nss = max(ht_rx_nss, vht_rx_nss); - sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); + rx_nss = max(vht_rx_nss, ht_rx_nss); + rx_nss = max(he_rx_nss, rx_nss); + sta->sta.rx_nss = max_t(u8, 1, rx_nss); } u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, -- cgit From 85b27ef73419db8d59a5d685bc62113883ca9330 Mon Sep 17 00:00:00 2001 From: Andrei Otcheretianski Date: Fri, 31 Jan 2020 13:12:50 +0200 Subject: mac80211: Accept broadcast probe responses on 6GHz band An AP that operates on 6GHz may respond with a broadcast probe response. Don't ignore such frames. Signed-off-by: Andrei Otcheretianski Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-14-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2733555a5f3b..320a2b3b0f5a 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3683,13 +3683,28 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt = (void *)skb->data; struct ieee80211_if_managed *ifmgd; struct ieee80211_rx_status *rx_status = (void *) skb->cb; + struct ieee80211_channel *channel; size_t baselen, len = skb->len; ifmgd = &sdata->u.mgd; sdata_assert_lock(sdata); - if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) + /* + * According to Draft P802.11ax D6.0 clause 26.17.2.3.2: + * "If a 6 GHz AP receives a Probe Request frame and responds with + * a Probe Response frame [..], the Address 1 field of the Probe + * Response frame shall be set to the broadcast address [..]" + * So, on 6GHz band we should also accept broadcast responses. + */ + channel = ieee80211_get_channel(sdata->local->hw.wiphy, + rx_status->freq); + if (!channel) + return; + + if (!ether_addr_equal(mgmt->da, sdata->vif.addr) && + (channel->band != NL80211_BAND_6GHZ || + !is_broadcast_ether_addr(mgmt->da))) return; /* ignore ProbeResp to foreign address */ baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; -- cgit From c4d800dcc7c57837cca66638b54b1d8a09949f79 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Fri, 31 Jan 2020 13:12:53 +0200 Subject: mac80211: Handle SMPS mode changes only in AP mode According to IEEE802.11 specifications the SM power save field in the HT capability IE and the HE extended capability IE is valid only in (re)association frames and should be ignored otherwise. Remove code paths that handled this also for non AP modes. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-17-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/he.c | 2 +- net/mac80211/ht.c | 42 ++++++++++++++++++++++++------------------ net/mac80211/rx.c | 6 +++++- 3 files changed, 30 insertions(+), 20 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/he.c b/net/mac80211/he.c index 5245c19f39bf..1087f715338b 100644 --- a/net/mac80211/he.c +++ b/net/mac80211/he.c @@ -3,7 +3,7 @@ * HE handling * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2019 Intel Corporation + * Copyright(c) 2019 - 2020 Intel Corporation */ #include "ieee80211_i.h" diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a2e4d6b8fd98..a8e144fd02f1 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -9,6 +9,7 @@ * Copyright 2007, Michael Wu * Copyright 2007-2010, Intel Corporation * Copyright 2017 Intel Deutschland GmbH + * Copyright(c) 2020 Intel Corporation */ #include @@ -144,7 +145,6 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, int i, max_tx_streams; bool changed; enum ieee80211_sta_rx_bandwidth bw; - enum ieee80211_smps_mode smps_mode; memset(&ht_cap, 0, sizeof(ht_cap)); @@ -270,24 +270,30 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ? IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20; - switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS) - >> IEEE80211_HT_CAP_SM_PS_SHIFT) { - case WLAN_HT_CAP_SM_PS_INVALID: - case WLAN_HT_CAP_SM_PS_STATIC: - smps_mode = IEEE80211_SMPS_STATIC; - break; - case WLAN_HT_CAP_SM_PS_DYNAMIC: - smps_mode = IEEE80211_SMPS_DYNAMIC; - break; - case WLAN_HT_CAP_SM_PS_DISABLED: - smps_mode = IEEE80211_SMPS_OFF; - break; - } - - if (smps_mode != sta->sta.smps_mode) - changed = true; - sta->sta.smps_mode = smps_mode; + if (sta->sdata->vif.type == NL80211_IFTYPE_AP || + sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + enum ieee80211_smps_mode smps_mode; + + switch ((ht_cap.cap & IEEE80211_HT_CAP_SM_PS) + >> IEEE80211_HT_CAP_SM_PS_SHIFT) { + case WLAN_HT_CAP_SM_PS_INVALID: + case WLAN_HT_CAP_SM_PS_STATIC: + smps_mode = IEEE80211_SMPS_STATIC; + break; + case WLAN_HT_CAP_SM_PS_DYNAMIC: + smps_mode = IEEE80211_SMPS_DYNAMIC; + break; + case WLAN_HT_CAP_SM_PS_DISABLED: + smps_mode = IEEE80211_SMPS_OFF; + break; + } + if (smps_mode != sta->sta.smps_mode) + changed = true; + sta->sta.smps_mode = smps_mode; + } else { + sta->sta.smps_mode = IEEE80211_SMPS_OFF; + } return changed; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 619c223f1cde..ec3a04a1db20 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -6,7 +6,7 @@ * Copyright 2007-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation */ #include @@ -3082,6 +3082,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) enum ieee80211_smps_mode smps_mode; struct sta_opmode_info sta_opmode = {}; + if (sdata->vif.type != NL80211_IFTYPE_AP && + sdata->vif.type != NL80211_IFTYPE_AP_VLAN) + goto handled; + /* convert to HT capability */ switch (mgmt->u.action.u.ht_smps.smps_control) { case WLAN_HT_SMPS_CONTROL_DISABLED: -- cgit From 52b4810bed836929d73e1ff419a8d3f1eb1b4c4b Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Fri, 31 Jan 2020 13:12:56 +0200 Subject: mac80211: Remove support for changing AP SMPS mode The SMPS feature is defined in the specification only to be used by non-AP stations and not by APs, so remove the support for changing the AP's SMPS mode dynamically. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-20-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 101 ++---------------------------------------- net/mac80211/debugfs_netdev.c | 13 ++---- net/mac80211/ht.c | 22 --------- net/mac80211/ieee80211_i.h | 7 +-- net/mac80211/iface.c | 8 +--- net/mac80211/sta_info.c | 16 +------ 6 files changed, 10 insertions(+), 157 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a11bd1669c13..eb7a84150817 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -990,20 +990,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, if (old) return -EALREADY; - switch (params->smps_mode) { - case NL80211_SMPS_OFF: - sdata->smps_mode = IEEE80211_SMPS_OFF; - break; - case NL80211_SMPS_STATIC: - sdata->smps_mode = IEEE80211_SMPS_STATIC; - break; - case NL80211_SMPS_DYNAMIC: - sdata->smps_mode = IEEE80211_SMPS_DYNAMIC; - break; - default: - return -EINVAL; - } - sdata->u.ap.req_smps = sdata->smps_mode; + if (params->smps_mode != NL80211_SMPS_OFF) + return -ENOTSUPP; + + sdata->smps_mode = IEEE80211_SMPS_OFF; sdata->needed_rx_chains = sdata->local->rx_chains; @@ -1169,7 +1159,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) kfree_rcu(old_beacon, rcu_head); if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); - sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF; kfree(sdata->vif.bss_conf.ftmr_params); sdata->vif.bss_conf.ftmr_params = NULL; @@ -1694,20 +1683,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, mutex_unlock(&local->sta_mtx); - if ((sdata->vif.type == NL80211_IFTYPE_AP || - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && - sta->known_smps_mode != sta->sdata->bss->req_smps && - test_sta_flag(sta, WLAN_STA_AUTHORIZED) && - sta_info_tx_streams(sta) != 1) { - ht_dbg(sta->sdata, - "%pM just authorized and MIMO capable - update SMPS\n", - sta->sta.addr); - ieee80211_send_smps_action(sta->sdata, - sta->sdata->bss->req_smps, - sta->sta.addr, - sta->sdata->vif.bss_conf.bssid); - } - if (sdata->vif.type == NL80211_IFTYPE_STATION && params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { ieee80211_recalc_ps(local); @@ -2639,74 +2614,6 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy, } #endif -int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, - enum ieee80211_smps_mode smps_mode) -{ - struct sta_info *sta; - enum ieee80211_smps_mode old_req; - - if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP)) - return -EINVAL; - - if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) - return 0; - - old_req = sdata->u.ap.req_smps; - sdata->u.ap.req_smps = smps_mode; - - /* AUTOMATIC doesn't mean much for AP - don't allow it */ - if (old_req == smps_mode || - smps_mode == IEEE80211_SMPS_AUTOMATIC) - return 0; - - ht_dbg(sdata, - "SMPS %d requested in AP mode, sending Action frame to %d stations\n", - smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta)); - - mutex_lock(&sdata->local->sta_mtx); - list_for_each_entry(sta, &sdata->local->sta_list, list) { - /* - * Only stations associated to our AP and - * associated VLANs - */ - if (sta->sdata->bss != &sdata->u.ap) - continue; - - /* This station doesn't support MIMO - skip it */ - if (sta_info_tx_streams(sta) == 1) - continue; - - /* - * Don't wake up a STA just to send the action frame - * unless we are getting more restrictive. - */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) && - !ieee80211_smps_is_restrictive(sta->known_smps_mode, - smps_mode)) { - ht_dbg(sdata, "Won't send SMPS to sleeping STA %pM\n", - sta->sta.addr); - continue; - } - - /* - * If the STA is not authorized, wait until it gets - * authorized and the action frame will be sent then. - */ - if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED)) - continue; - - ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr); - ieee80211_send_smps_action(sdata, smps_mode, sta->sta.addr, - sdata->vif.bss_conf.bssid); - } - mutex_unlock(&sdata->local->sta_mtx); - - sdata->smps_mode = smps_mode; - ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); - - return 0; -} - int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode) { diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 64b544ae9966..3dbe7c5cefd1 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2006 Jiri Benc * Copyright 2007 Johannes Berg + * Copyright (C) 2020 Intel Corporation */ #include @@ -254,15 +255,11 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, smps_mode == IEEE80211_SMPS_AUTOMATIC)) return -EINVAL; - if (sdata->vif.type != NL80211_IFTYPE_STATION && - sdata->vif.type != NL80211_IFTYPE_AP) + if (sdata->vif.type != NL80211_IFTYPE_STATION) return -EOPNOTSUPP; sdata_lock(sdata); - if (sdata->vif.type == NL80211_IFTYPE_STATION) - err = __ieee80211_request_smps_mgd(sdata, smps_mode); - else - err = __ieee80211_request_smps_ap(sdata, smps_mode); + err = __ieee80211_request_smps_mgd(sdata, smps_mode); sdata_unlock(sdata); return err; @@ -282,10 +279,6 @@ static ssize_t ieee80211_if_fmt_smps(const struct ieee80211_sub_if_data *sdata, return snprintf(buf, buflen, "request: %s\nused: %s\n", smps_modes[sdata->u.mgd.req_smps], smps_modes[sdata->smps_mode]); - if (sdata->vif.type == NL80211_IFTYPE_AP) - return snprintf(buf, buflen, "request: %s\nused: %s\n", - smps_modes[sdata->u.ap.req_smps], - smps_modes[sdata->smps_mode]); return -EINVAL; } diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a8e144fd02f1..e32906202575 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -550,19 +550,6 @@ void ieee80211_request_smps_mgd_work(struct work_struct *work) sdata_unlock(sdata); } -void ieee80211_request_smps_ap_work(struct work_struct *work) -{ - struct ieee80211_sub_if_data *sdata = - container_of(work, struct ieee80211_sub_if_data, - u.ap.request_smps_work); - - sdata_lock(sdata); - if (sdata_dereference(sdata->u.ap.beacon, sdata)) - __ieee80211_request_smps_ap(sdata, - sdata->u.ap.driver_smps_mode); - sdata_unlock(sdata); -} - void ieee80211_request_smps(struct ieee80211_vif *vif, enum ieee80211_smps_mode smps_mode) { @@ -578,15 +565,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, sdata->u.mgd.driver_smps_mode = smps_mode; ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.request_smps_work); - } else { - /* AUTOMATIC is meaningless in AP mode */ - if (WARN_ON_ONCE(smps_mode == IEEE80211_SMPS_AUTOMATIC)) - return; - if (sdata->u.ap.driver_smps_mode == smps_mode) - return; - sdata->u.ap.driver_smps_mode = smps_mode; - ieee80211_queue_work(&sdata->local->hw, - &sdata->u.ap.request_smps_work); } } /* this might change ... don't want non-open drivers using it */ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b89543269f51..7074af92b536 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -5,7 +5,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2007-2010 Johannes Berg * Copyright 2013-2015 Intel Mobile Communications GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation */ #ifndef IEEE80211_I_H @@ -292,10 +292,7 @@ struct ieee80211_if_ap { struct ps_data ps; atomic_t num_mcast_sta; /* number of stations receiving multicast */ - enum ieee80211_smps_mode req_smps, /* requested smps mode */ - driver_smps_mode; /* smps mode request */ - struct work_struct request_smps_work; bool multicast_to_unicast; }; @@ -2148,8 +2145,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, enum nl80211_band band, u32 *basic_rates); int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata, enum ieee80211_smps_mode smps_mode); -int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, - enum ieee80211_smps_mode smps_mode); void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata); void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 99d913a6e651..2fb26bc105f8 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -8,7 +8,7 @@ * Copyright 2008, Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation */ #include #include @@ -824,9 +824,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_ADHOC: ieee80211_ibss_stop(sdata); break; - case NL80211_IFTYPE_AP: - cancel_work_sync(&sdata->u.ap.request_smps_work); - break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) break; @@ -1494,10 +1491,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, case NL80211_IFTYPE_AP: skb_queue_head_init(&sdata->u.ap.ps.bc_buf); INIT_LIST_HEAD(&sdata->u.ap.vlans); - INIT_WORK(&sdata->u.ap.request_smps_work, - ieee80211_request_smps_ap_work); sdata->vif.bss_conf.bssid = sdata->vif.addr; - sdata->u.ap.req_smps = IEEE80211_SMPS_OFF; break; case NL80211_IFTYPE_P2P_CLIENT: type = NL80211_IFTYPE_STATION; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0f5f40678885..f357156b86ee 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -4,7 +4,7 @@ * Copyright 2006-2007 Jiri Benc * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation */ #include @@ -1351,20 +1351,6 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) atomic_dec(&ps->num_sta_ps); - /* This station just woke up and isn't aware of our SMPS state */ - if (!ieee80211_vif_is_mesh(&sdata->vif) && - !ieee80211_smps_is_restrictive(sta->known_smps_mode, - sdata->smps_mode) && - sta->known_smps_mode != sdata->bss->req_smps && - sta_info_tx_streams(sta) != 1) { - ht_dbg(sdata, - "%pM just woke up and MIMO capable - update SMPS\n", - sta->sta.addr); - ieee80211_send_smps_action(sdata, sdata->bss->req_smps, - sta->sta.addr, - sdata->vif.bss_conf.bssid); - } - local->total_ps_buffered -= buffered; sta_info_recalc_tim(sta); -- cgit From ff74c51e8f4c543ed2bd3bf1c2f3287b098660df Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Fri, 31 Jan 2020 13:45:29 +0200 Subject: cfg80211/mac80211: Allow user space to register for station Rx authentication To support Pre Association Security Negotiation (PASN) while already associated to one AP, allow user space to register to Rx authentication frames, so that the user space logic would be able to receive/handle authentication frames from a different AP as part of PASN. Note that it is expected that user space would intelligently register for Rx authentication frames, i.e., only when PASN is used and configure a match filter only for PASN authentication algorithm, as otherwise the MLME functionality of mac80211 would be broken. Additionally, since some versions of the user space daemons wrongly register to all types of authentication frames (which might result in unexpected behavior) allow such registration if the request is for a specific authentication algorithm number. Signed-off-by: Ilan Peer Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131114529.894206-1-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d91bcef738dc..9dd3c9e3731f 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -416,7 +416,20 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_STATION] = { .tx = 0xffff, + /* + * To support Pre Association Security Negotiation (PASN) while + * already associated to one AP, allow user space to register to + * Rx authentication frames, so that the user space logic would + * be able to receive/handle authentication frames from a + * different AP as part of PASN. + * It is expected that user space would intelligently register + * for Rx authentication frames, i.e., only when PASN is used + * and configure a match filter only for PASN authentication + * algorithm, as otherwise the MLME functionality of mac80211 + * would be broken. + */ .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), }, [NL80211_IFTYPE_AP] = { -- cgit From c0058df73309906ef4d5383fbaa10c43ebddc48a Mon Sep 17 00:00:00 2001 From: Shaul Triebitz Date: Fri, 31 Jan 2020 13:12:57 +0200 Subject: mac80211: parse also the RSNXE IE Parse also the RSN Extension IE when parsing the rest of the IEs. It will be used in a later patch. Signed-off-by: Shaul Triebitz Signed-off-by: Luca Coelho Link: https://lore.kernel.org/r/20200131111300.891737-21-luca@coelho.fi Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 2 ++ net/mac80211/util.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7074af92b536..8a49d78ad7c9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1472,6 +1472,7 @@ struct ieee802_11_elems { const struct ieee80211_tim_ie *tim; const u8 *challenge; const u8 *rsn; + const u8 *rsnx; const u8 *erp_info; const u8 *ext_supp_rates; const u8 *wmm_info; @@ -1519,6 +1520,7 @@ struct ieee802_11_elems { u8 tim_len; u8 challenge_len; u8 rsn_len; + u8 rsnx_len; u8 ext_supp_rates_len; u8 wmm_info_len; u8 wmm_param_len; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 72039c8dbc38..7ddf0508779f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -6,7 +6,7 @@ * Copyright 2007 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * utilities for mac80211 */ @@ -994,6 +994,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, case WLAN_EID_CHAN_SWITCH_TIMING: case WLAN_EID_LINK_ID: case WLAN_EID_BSS_MAX_IDLE_PERIOD: + case WLAN_EID_RSNX: /* * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible * that if the content gets bigger it might be needed more than once @@ -1264,6 +1265,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, if (elen >= sizeof(*elems->max_idle_period_ie)) elems->max_idle_period_ie = (void *)pos; break; + case WLAN_EID_RSNX: + elems->rsnx = pos; + elems->rsnx_len = elen; + break; case WLAN_EID_EXTENSION: ieee80211_parse_extension_element(calc_crc ? &crc : NULL, -- cgit From 8c3ed7aa2b9ef666195b789e9b02e28383243fa8 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Wed, 15 Jan 2020 13:55:22 +0100 Subject: nl80211: add src and dst addr attributes for control port tx/rx When using control port over nl80211 in AP mode with pre-authentication, APs need to forward frames to other APs defined by their MAC address. Before this patch, pre-auth frames reaching user space over nl80211 control port have no longer any information about the dest attached, which can be used for forwarding to a controller or injecting the frame back to a ethernet interface over a AF_PACKET socket. Analog problems exist, when forwarding pre-auth frames from AP -> STA. This patch therefore adds the NL80211_ATTR_DST_MAC and NL80211_ATTR_SRC_MAC attributes to provide more context information when forwarding. The respective arguments are optional on tx and included on rx. Therefore unaware existing software is not affected. Software which wants to detect this feature, can do so by checking against: NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS Signed-off-by: Markus Theil Link: https://lore.kernel.org/r/20200115125522.3755-1-markus.theil@tu-ilmenau.de [split into separate cfg80211/mac80211 patches] Signed-off-by: Johannes Berg --- net/mac80211/ieee80211_i.h | 3 ++- net/mac80211/tx.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'net/mac80211') diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8a49d78ad7c9..da9eaa9ee37e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1792,7 +1792,8 @@ void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata); void ieee80211_clear_fast_xmit(struct sta_info *sta); int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len, - const u8 *dest, __be16 proto, bool unencrypted); + const u8 *dest, const u8 *src, __be16 proto, + bool unencrypted); int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4296d9d71311..059c66b6bb5c 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -5285,7 +5285,8 @@ void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata, int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, const u8 *buf, size_t len, - const u8 *dest, __be16 proto, bool unencrypted) + const u8 *dest, const u8 *src, __be16 proto, + bool unencrypted) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; -- cgit From 9b125c27998719288e4dcf2faf54511039526692 Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Fri, 7 Feb 2020 12:58:57 +0100 Subject: mac80211: support NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS This is now a trivial patch, but for seeing the actual changes I (Johannes) split it out from the original. Signed-off-by: Markus Theil Link: https://lore.kernel.org/r/20200115125522.3755-1-markus.theil@tu-ilmenau.de [split into separate cfg80211/mac80211 patches] Signed-off-by: Johannes Berg --- net/mac80211/main.c | 2 ++ net/mac80211/tx.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'net/mac80211') diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 9dd3c9e3731f..265a31a8104d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -587,6 +587,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_FILS_STA); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211); + wiphy_ext_feature_set(wiphy, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_MAC_ADDRS); if (!ops->hw_scan) { wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN | diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 059c66b6bb5c..a447d258fea3 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -5317,7 +5317,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev, ehdr = skb_push(skb, sizeof(struct ethhdr)); memcpy(ehdr->h_dest, dest, ETH_ALEN); - memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN); + memcpy(ehdr->h_source, src, ETH_ALEN); ehdr->h_proto = proto; skb->dev = dev; -- cgit From db6d9e9e8b48b7ab68c61553eb5fa68534dd0fde Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 17 Dec 2019 10:30:57 -0800 Subject: mac80211: Fix setting txpower to zero With multiple VIFS ath10k, and probably others, tries to find the minimum txpower for all vifs and uses that when setting txpower in the firmware. If a second vif is added and starts to scan, it's txpower is not initialized yet and it set to zero. ath10k had a patch to ignore zero values, but then it is impossible to actually set txpower to zero. So, instead initialize the txpower to INT_MIN in mac80211, and let drivers know that means the power has not been set and so should be ignored. This should fix regression in: commit 88407beb1b1462f706a1950a355fd086e1c450b6 Author: Ryan Hsu Date: Tue Dec 13 14:55:19 2016 -0800 ath10k: fix incorrect txpower set by P2P_DEVICE interface Tested on ath10k 9984 with ath10k-ct firmware. Signed-off-by: Ben Greear Link: https://lore.kernel.org/r/20191217183057.24586-1-greearb@candelatech.com Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 1 + net/mac80211/main.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 2fb26bc105f8..3c00408e9c8c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1465,6 +1465,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, sdata->control_port_no_encrypt = false; sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; sdata->vif.bss_conf.idle = true; + sdata->vif.bss_conf.txpower = INT_MIN; /* unset */ sdata->noack_map = 0; sdata->hw_80211_encap = false; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 265a31a8104d..cae3a34d3503 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -146,6 +146,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) continue; if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) continue; + if (sdata->vif.bss_conf.txpower == INT_MIN) + continue; power = min(power, sdata->vif.bss_conf.txpower); } rcu_read_unlock(); -- cgit From 1f6e0baa703d31002c312c3e423c108b04325df0 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 11 Feb 2020 13:26:04 +0100 Subject: mac80211: allow setting queue_len for drivers not using wake_tx_queue Currently a mac80211 driver can only set the txq_limit when using wake_tx_queue. Not all drivers use wake_tx_queue. This patch adds a new element to wiphy allowing a driver to set a custom tx_queue_len and the code that will apply it in case it is set. The current default is 1000 which is too low for ath11k when doing HE rates. Signed-off-by: John Crispin Link: https://lore.kernel.org/r/20200211122605.13002-1-john@phrozen.org Signed-off-by: Johannes Berg --- net/mac80211/iface.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/mac80211') diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 3c00408e9c8c..128b3468d13e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1834,6 +1834,10 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, if_setup, txqs, 1); if (!ndev) return -ENOMEM; + + if (!local->ops->wake_tx_queue && local->hw.wiphy->tx_queue_len) + ndev->tx_queue_len = local->hw.wiphy->tx_queue_len; + dev_net_set(ndev, wiphy_net(local->hw.wiphy)); ndev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); -- cgit