[RFC] mac80211: fix A-MSDU outer SA/DA
According to IEEE 802.11-2012 section 8.3.2 table 8-19, the outer SA/DA of A-MSDU frames need to be changed depending on FromDS/ToDS values. Signed-off-by: Michael Braun --- net/mac80211/tx.c | 24 +++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5023966..87670b7 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3050,7 +3050,7 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header); int subframe_len = skb->len - hdr_len; void *data; - u8 *qc; + u8 *qc, *bssid; if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) return false; @@ -3062,10 +3062,32 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata, &subframe_len)) return false; + switch (sdata->vif.type) { + case NL80211_IFTYPE_STATION: + bssid = sdata->u.mgd.bssid; + break; + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + bssid = sdata->vif.addr; + break; + default: + bssid = NULL; + } + amsdu_hdr.h_proto = cpu_to_be16(subframe_len); memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN); memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN); + /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA +* fields needs to be changed to BSSID for A-MSDU frames depending +* on FromDS/ToDS values. +*/ + hdr = data; + if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS))) + memcpy(amsdu_hdr.h_source, bssid, ETH_ALEN); + if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS))) + memcpy(amsdu_hdr.h_dest, bssid, ETH_ALEN); + data = skb_push(skb, sizeof(amsdu_hdr)); memmove(data, data + sizeof(amsdu_hdr), hdr_len); memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr)); -- 2.1.4
[PATCH] mac80211: enable to inject a-msdu frames using monitor interface
Problem: When injecting an A-MSDU using a PF_PACKET socket, the qos flag IEEE80211_QOS_CTL_A_MSDU_PRESENT is cleared. How to reproduce: Inject a frame on a mac80211 hwsim monitor interface and have tshark sniffing on this monitor interface. You'll see the packet twice: Once with correct flag and once with flag cleared. On hwsim0, you'll only see the packet with a cleared flag. I guess the same is needed for packets with IEEE80211_TX_CTRL_AMSDU set. Signed-off-by: Michael Braun --- net/mac80211/wme.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 9eb0aee..3faa972 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -248,6 +248,13 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, /* preserve EOSP bit */ ack_policy = *p & IEEE80211_QOS_CTL_EOSP; + /* preserve A-MSDU bit for MONITOR interfaces to allow injecting +* A-MSDU frames +*/ + if (info->flags & IEEE80211_TX_CTL_INJECTED || + info->control.flags & IEEE80211_TX_CTRL_AMSDU) + ack_policy |= *p & IEEE80211_QOS_CTL_A_MSDU_PRESENT; + if (is_multicast_ether_addr(hdr->addr1) || sdata->noack_map & BIT(tid)) { ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; -- 2.1.4
[PATCH v5 3/4] cfg80211: configure multicast to unicast for AP interfaces
This add a userspace toggle to configure multicast to unicast. Signed-off-by: Michael Braun --- include/net/cfg80211.h | 6 ++ include/uapi/linux/nl80211.h | 10 ++ net/wireless/nl80211.c | 36 net/wireless/rdev-ops.h | 12 net/wireless/trace.h | 19 +++ 5 files changed, 83 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 7ce6223..7b0941d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2460,6 +2460,8 @@ struct cfg80211_qos_map { * * @set_wds_peer: set the WDS peer for a WDS interface * + * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS + * * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting * functions to adjust rfkill hw state * @@ -2722,6 +2724,10 @@ struct cfg80211_ops { int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, const u8 *addr); + int (*set_multicast_to_unicast)(struct wiphy *wiphy, + struct net_device *dev, + const bool enabled); + void(*rfkill_poll)(struct wiphy *wiphy); #ifdef CONFIG_NL80211_TESTMODE diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 2206941..1b9e87b 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -599,6 +599,9 @@ * * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. * + * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if AP interface should + * perform multicast to unicast conversion (per-BSS). + * * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial * mesh config parameters may be given. * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the @@ -1026,6 +1029,8 @@ enum nl80211_commands { NL80211_CMD_ABORT_SCAN, + NL80211_CMD_SET_MULTICAST_TO_UNICAST, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1867,6 +1872,9 @@ enum nl80211_commands { * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is * used to pull the stored data for mesh peer in power save state. * + * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Multicast packets should be + * send out as unicast to all stations. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2261,6 +2269,8 @@ enum nl80211_attrs { NL80211_ATTR_MESH_PEER_AID, + NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f02653a..57b5d70 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -409,6 +409,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { .len = VHT_MUMIMO_GROUPS_DATA_LEN }, [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN }, + [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_U8, }, }; /* policy for the key attributes */ @@ -1538,6 +1539,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, goto nla_put_failure; } CMD(set_wds_peer, SET_WDS_PEER); + CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { CMD(tdls_mgmt, TDLS_MGMT); CMD(tdls_oper, TDLS_OPER); @@ -2164,6 +2166,32 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) return rdev_set_wds_peer(rdev, dev, bssid); } +static int nl80211_set_multicast_to_unicast(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + const struct nlattr *nla; + bool enabled; + + if (!info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED]) + return -EINVAL; + + if (netif_running(dev)) + return -EBUSY; + + if (!rdev->ops->set_multicast_to_unicast) + return -EOPNOTSUPP; + + if (wdev->iftype != NL80211_IFTYPE_AP) + return -EOPNOTSUPP; + + nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED]; + enabled = nla_get_flag(nla); + return rdev_set_multicast_to_unicast(rdev, dev, enabled); +} + static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) { str
[PATCH v5 2/4] mac80211: filter multicast data packets on AP / AP_VLAN
This patch adds filtering for multicast data packets on AP_VLAN interfaces that have no authorized station connected and changes filtering on AP interfaces to not count stations assigned to AP_VLAN interfaces. This saves airtime and avoids waking up other stations currently authorized in this BSS. When using WPA, the packets dropped could not be decrypted by any station. The behaviour when there are no AP_VLAN interfaces is left unchanged. When there are AP_VLAN interfaces, this patch 1. adds filtering multicast data packets sent on AP_VLAN interfaces that have no authorized station connected. No filtering happens on 4addr AP_VLAN interfaces. 2. makes filtering of multicast data packets sent on AP interfaces depend on the number of authorized stations in this bss not assigned to an AP_VLAN interface. Therefore, a new num_mcast_sta counter is added for AP_VLAN interfaces. The existing one for AP interfaces is altered to not track stations assigned to an AP_VLAN interface. The new counter is exposed in debugfs. Signed-off-by: Michael Braun -- v4: - update description v3: - reuse existing num_mcast_sta v2: - use separate function to inc/dec mcast_sta counters - do not filter in 4addr mode - change description - change filtering on AP interface (do not count AP_VLAN sta) - use new counters regardless of 4addr or not - simplify cfg.c:change_station - remove no-op change in __cleanup_single_sta --- net/mac80211/cfg.c| 20 ++-- net/mac80211/debugfs_netdev.c | 11 +++ net/mac80211/ieee80211_i.h| 33 + net/mac80211/rx.c | 5 +++-- net/mac80211/sta_info.c | 10 ++ net/mac80211/tx.c | 5 ++--- 6 files changed, 57 insertions(+), 27 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 24133f5..1edb017 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1357,9 +1357,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, goto out_err; if (params->vlan && params->vlan != sta->sdata->dev) { - bool prev_4addr = false; - bool new_4addr = false; - vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); if (params->vlan->ieee80211_ptr->use_4addr) { @@ -1369,26 +1366,21 @@ static int ieee80211_change_station(struct wiphy *wiphy, } rcu_assign_pointer(vlansdata->u.vlan.sta, sta); - new_4addr = true; __ieee80211_check_fast_rx_iface(vlansdata); } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - sta->sdata->u.vlan.sta) { + sta->sdata->u.vlan.sta) RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL); - prev_4addr = true; - } + + if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + ieee80211_vif_dec_num_mcast(sta->sdata); sta->sdata = vlansdata; ieee80211_check_fast_xmit(sta); - if (sta->sta_state == IEEE80211_STA_AUTHORIZED && - prev_4addr != new_4addr) { - if (new_4addr) - atomic_dec(&sta->sdata->bss->num_mcast_sta); - else - atomic_inc(&sta->sdata->bss->num_mcast_sta); - } + if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + ieee80211_vif_inc_num_mcast(sta->sdata); ieee80211_send_layer2_update(sta); } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index a5ba739..ed7bff4 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw); IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC); +IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC); static ssize_t ieee80211_if_fmt_num_buffered_multicast( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -643,6 +644,13 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD_MODE(tkip_mic_test, 0200); } +static void add_vlan_files(struct ieee80211_sub_if_data *sdata) +{ + /* add num_mcast_sta_vlan using name num_mcast_sta */ + debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir, + sdata, &num_mcast_sta_vlan_ops); +} + static void add_ibss_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD_MODE(tsf, 0600); @@ -746,6 +754,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) case NL80211_IFTYPE_AP: add_ap_files(sdata); break; + c
[PATCH v5 4/4] mac80211: multicast to unicast conversion
This patch adds support for sending multicast data packets with ARP, IPv4 and IPv6 payload (possible 802.1q tagged) as 802.11 unicast frames to all stations. IEEE 802.11 multicast has well known issues, among them: 1. packets are not acked and hence not retransmitted, resulting in decreased reliablity 2. packets are send at low rate, increasing time required on air When used with AP_VLAN, there is another disadvantage: 3. all stations in the BSS are woken up, regardsless of their AP_VLAN assignment. By doing multicast to unicast conversion, all three issus are solved. IEEE802.11-2012 proposes directed multicast service (DMS) using A-MSDU frames and a station initiated control protocol. It has the advantage that the station can recover the destination multicast mac address, but it is not backward compatible with non QOS stations and does not enable the administrator of a BSS to force this mode of operation within a BSS. Additionally, it would require both the ap and the station to implement the control protocol, which is optional on both ends. Furthermore, I've seen a few mobile phone stations locally that indicate qos support but won't complete DHCP if their broadcasts are encapsulated as A-MSDU. Though they work fine with this series approach. This patch therefore does not opt to implement DMS but instead just replicates the packet and changes the destination address. As this works fine with ARP, IPv4 and IPv6, it is limited to these protocols and normal 802.11 multicast frames are send out for all other payload protocols. There is a runtime toggle to enable multicast conversion in a per-bss fashion. When there is only a single station assigned to the AP_VLAN interface, no packet replication will occur. 4addr mode of operation is unchanged. This change opts for iterating all BSS stations for finding the stations assigned to this AP/AP_VLAN interface, as there currently is no per AP_VLAN list to iterate and multicast packets are expected to be few. If needed, such a list could be added later. Signed-off-by: Michael Braun -- v5: - rename bss->unicast to bss->multicast_to_unicast - access sdata->bss only after checking iftype v4: - rename MULTICAST_TO_UNICAST to MULTICAST_TO_UNICAST v3: fix compile error for trace.h v2: add nl80211 toggle rename tx_dnat to change_da change int to bool unicast --- net/mac80211/cfg.c| 15 +++ net/mac80211/debugfs_netdev.c | 3 ++ net/mac80211/ieee80211_i.h| 1 + net/mac80211/tx.c | 101 ++ 4 files changed, 120 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1edb017..1db4c3e 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2242,6 +2242,20 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy, + struct net_device *dev, + const bool enabled) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != NL80211_IFTYPE_AP) + return -1; + + sdata->u.ap.multicast_to_unicast = enabled; + + return 0; +} + static void ieee80211_rfkill_poll(struct wiphy *wiphy) { struct ieee80211_local *local = wiphy_priv(wiphy); @@ -3400,6 +3414,7 @@ const struct cfg80211_ops mac80211_config_ops = { .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, .set_wds_peer = ieee80211_set_wds_peer, + .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, .rfkill_poll = ieee80211_rfkill_poll, CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ed7bff4..509c6c3 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -487,6 +487,8 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( } IEEE80211_IF_FILE_R(num_buffered_multicast); +IEEE80211_IF_FILE(multicast_to_unicast, u.ap.multicast_to_unicast, HEX); + /* IBSS attributes */ static ssize_t ieee80211_if_fmt_tsf( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -642,6 +644,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(dtim_count); DEBUGFS_ADD(num_buffered_multicast); DEBUGFS_ADD_MODE(tkip_mic_test, 0200); + DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); } static void add_vlan_files(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 70c0963..84374ed 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -293,6 +293,7 @@ struct ieee80211_if_ap { driver_smps_mode; /* smps mode request */
[PATCH v5 1/4] mac80211: remove unnecessary num_mcast_sta user
Checking for num_mcast_sta in __ieee80211_request_smps_ap() is unnecessary, as sta list will be empty in this case anyway, so list_for_each_entry(sta, ...) will exit immediately. Signed-off-by: Michael Braun --- net/mac80211/cfg.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 543b1d4..24133f5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2313,13 +2313,6 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, smps_mode == IEEE80211_SMPS_AUTOMATIC) return 0; -/* If no associated stations, there's no need to do anything */ - if (!atomic_read(&sdata->u.ap.num_mcast_sta)) { - sdata->smps_mode = smps_mode; - ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); - 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)); -- 2.1.4
[PATCH] wlcore: Allow scans when in AP mode
From: James Minor When in AP mode, scans can be done without changing firmware to the multi-role firmware. Allow the interface to scan if forced in the scan request. Signed-off-by: James Minor Signed-off-by: Xander Huff Reviewed-by: Ben Shelton Reviewed-by: Jaeden Amero --- drivers/net/wireless/ti/wlcore/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 471521a..01ca370 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -6120,6 +6120,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) WIPHY_FLAG_SUPPORTS_SCHED_SCAN | WIPHY_FLAG_HAS_CHANNEL_SWITCH; + wl->hw->wiphy->features |= NL80211_FEATURE_AP_SCAN; + /* make sure all our channels fit in the scanned_ch bitmask */ BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) + ARRAY_SIZE(wl1271_channels_5ghz) > -- 1.9.1
[PATCH 2/2] ath10k: add support for per sta tx bitrate
From: Anilkumar Kolli Per STA tx bitrate info is filled from peer stats. Export per sta txrate info to cfg80211/nl80211 Signed-off-by: Anilkumar Kolli --- drivers/net/wireless/ath/ath10k/debugfs_sta.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 9955fea0802a..7daf9927a1ef 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -77,6 +77,19 @@ void ath10k_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, sinfo->rx_duration = arsta->rx_duration; sinfo->filled |= 1ULL << NL80211_STA_INFO_RX_DURATION; + + if (!arsta->txrate.legacy && !arsta->txrate.nss) + return; + + if(arsta->txrate.legacy) { + sinfo->txrate.legacy = arsta->txrate.legacy; + } else { + sinfo->txrate.mcs = arsta->txrate.mcs; + sinfo->txrate.nss = arsta->txrate.nss; + sinfo->txrate.bw = arsta->txrate.bw; + } + sinfo->txrate.flags = arsta->txrate.flags; + sinfo->filled |= 1ULL << NL80211_STA_INFO_TX_BITRATE; } static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file, -- 1.7.9.5
[PATCH 1/2] ath10k: add per peer htt tx stats support for 10.4
From: Anilkumar Kolli Per peer tx stats are part of 'HTT_10_4_T2H_MSG_TYPE_PEER_STATS' event, Firmware sends one HTT event for every four PPDUs. HTT payload has success pkts/bytes, failed pkts/bytes, retry pkts/bytes and rate info per ppdu. Peer stats are enabled through 'WMI_SERVICE_PEER_STATS', which are nowadays enabled by default. Parse peer stats and update the tx rate information per STA. tx rate, Peer stats are tested on QCA4019 with Firmware version 10.4-3.2.1-00028. Signed-off-by: Anilkumar Kolli --- drivers/net/wireless/ath/ath10k/core.h | 17 drivers/net/wireless/ath/ath10k/htt.c|2 + drivers/net/wireless/ath/ath10k/htt.h| 25 ++ drivers/net/wireless/ath/ath10k/htt_rx.c | 125 ++ drivers/net/wireless/ath/ath10k/wmi.h| 10 ++- 5 files changed, 178 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index dda49af1eb74..fc3d3bded265 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -337,6 +337,7 @@ struct ath10k_sta { u32 nss; u32 smps; u16 peer_id; + struct rate_info txrate; struct work_struct update_wk; @@ -694,6 +695,21 @@ struct ath10k_fw_components { struct ath10k_fw_file fw_file; }; +struct ath10k_per_peer_tx_stats { + u32 succ_bytes; + u32 retry_bytes; + u32 failed_bytes; + u8 ratecode; + u8 flags; + u16 peer_id; + u16 succ_pkts; + u16 retry_pkts; + u16 failed_pkts; + u16 duration; + u32 reserved1; + u32 reserved2; +}; + struct ath10k { struct ath_common ath_common; struct ieee80211_hw *hw; @@ -906,6 +922,7 @@ struct ath10k { struct ath10k_thermal thermal; struct ath10k_wow wow; + struct ath10k_per_peer_tx_stats peer_tx_stats; /* NAPI */ struct net_device napi_dev; diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c index 130cd9502021..cd160b16db1e 100644 --- a/drivers/net/wireless/ath/ath10k/htt.c +++ b/drivers/net/wireless/ath/ath10k/htt.c @@ -137,6 +137,8 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = { HTT_T2H_MSG_TYPE_STATS_NOUPLOAD, [HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] = HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, + [HTT_10_4_T2H_MSG_TYPE_PEER_STATS] = + HTT_T2H_MSG_TYPE_PEER_STATS, }; int ath10k_htt_connect(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 0d2ed09f202b..164eb3a10566 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -419,6 +419,7 @@ enum htt_10_4_t2h_msg_type { HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18, /* 0x19 to 0x2f are reserved */ HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30, + HTT_10_4_T2H_MSG_TYPE_PEER_STATS = 0x31, /* keep this last */ HTT_10_4_T2H_NUM_MSGS }; @@ -453,6 +454,7 @@ enum htt_t2h_msg_type { HTT_T2H_MSG_TYPE_TX_FETCH_IND, HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM, HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND, + HTT_T2H_MSG_TYPE_PEER_STATS, /* keep this last */ HTT_T2H_NUM_MSGS }; @@ -1470,6 +1472,28 @@ struct htt_channel_change { __le32 phymode; } __packed; +struct htt_per_peer_tx_stats_ind { + __le32 succ_bytes; + __le32 retry_bytes; + __le32 failed_bytes; + u8 ratecode; + u8 flags; + __le16 peer_id; + __le16 succ_pkts; + __le16 retry_pkts; + __le16 failed_pkts; + __le16 tx_duration; + __le32 reserved1; + __le32 reserved2; +} __packed; + +struct htt_peer_tx_stats { + u8 num_ppdu; + u8 ppdu_len; + u8 version; + u8 payload[0]; +} __packed; + union htt_rx_pn_t { /* WEP: 24-bit PN */ u32 pn24; @@ -1521,6 +1545,7 @@ struct htt_resp { struct htt_tx_fetch_confirm tx_fetch_confirm; struct htt_tx_mode_switch_ind tx_mode_switch_ind; struct htt_channel_change chan_change; + struct htt_peer_tx_stats peer_tx_stats; }; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 0b4c1562420f..eab719d9729b 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -2194,6 +2194,128 @@ void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) dev_kfree_skb_any(skb); } +static inline bool is_valid_legacy_rate(u8 rate) +{ + static const u8 legacy_rates[] = {1, 2, 5, 11, 6, 9, 12, +
[PATCH 0/2] ath10k: add support for tx bitrate
From: Anilkumar Kolli This patch series adds support for tx bitrate using .sta_statistics callback. tx bitrate tested on QCA4019 using iw. Anilkumar Kolli (2): ath10k: add per peer htt tx stats support for 10.4 ath10k: add support for per sta tx bitrate drivers/net/wireless/ath/ath10k/core.h| 17 drivers/net/wireless/ath/ath10k/debugfs_sta.c | 13 +++ drivers/net/wireless/ath/ath10k/htt.c |2 + drivers/net/wireless/ath/ath10k/htt.h | 25 + drivers/net/wireless/ath/ath10k/htt_rx.c | 125 + drivers/net/wireless/ath/ath10k/wmi.h | 10 +- 6 files changed, 191 insertions(+), 1 deletion(-) -- 1.7.9.5
Re: bcmdhd: Strange Power Save messages
On Thu, Oct 6, 2016 at 10:25 AM, Arend Van Spriel wrote: > On 6-10-2016 10:07, Gucea Doru wrote: >> On Wed, Oct 5, 2016 at 11:12 AM, Arend Van Spriel >> wrote: >>> On 4-10-2016 13:39, Gucea Doru wrote: On Sat, Oct 1, 2016 at 2:52 PM, Arend van Spriel > wrote: >> >> >> On 29-09-16 13:32, Gucea Doru wrote: >>> On Tue, Sep 27, 2016 at 12:03 PM, Gucea Doru >>> wrote: What is the decision triggering the exit from the PS mode immediately after the ping request? I am asking this because 802.11 PS legacy specifies that the client should wait for a beacon with TIM set in order to wake up: in my case, there is no beacon between the ping request message and the Null frame that announces the exit from the PS mode. >>> >>> >>> Any help would be highly appreciated :) >> >> Actually though I already sent you are reply, but alas here it is. >> >> bcmdhd is our aosp driver. I am maintaining the upstream brcm80211 >> drivers. Regardless your question is more for firmware running on the >> device. So like the same behavior would be observed when using brcmfmac >> with same firmware. >> >>> IEEE Std 802.11-2012, section 10.2.1.8 specifies that "when the STA >>> detects that the bit corresponding to its AID is 1 i the TIM, the STA >>> shall issue a PS Poll". In my capture there are cases when the STA >>> exits the PS mode without waiting for a beacon. >> >> It is a bit tricky, but the standard does not explicitly say the STA >> should be in power-save at any other time. So it is difficult to say >> what event occurred on the STA side to exit PS mode. Also STA means >> P2P-Client as you say. That means that you have multiple interfaces: >> regular STA and P2P-Client. So is the STA connected to some other AP or >> just not connected. wpa_supplicant will do intermittent scan or initiate >> scheduled scan by which firmware will scan at a certain interval. That >> is just some things I can come up with and I am sure there are more. I agree that there may be some events belonging to the regular STA interface that could trigger the Null Frame (which includes the exit from PS Mode). However, I would expect to see some management frames in the air before/after the Null Packet (e.g.: a Probe request in case of a scheduled scan). But in my case the trigger for the Null frame seems to be the ping request packet, the scenario is the same every time: ping request -> Block ACK -> Null Frame (Wireshark trace confirms this behavior). I thought that you had a power save optimization algorithm that keeps the card on a few milliseconds just to see if we can have a fast reply from the peer. Does this ring a bell? :) >>> >>> It does not. That would be implemented in firmware. As said I am working >>> on brcmfmac/brcmsmac. So bcmdhd and firmware are not my expertise. >>> >> >> Arend, could you please redirect me to a Broadcom firmware maintainer? > > Can you please elaborate on your platform, broadcom chipset, and what > version of bcmdhd you are using. > Platform: Nexus 5 running CM13 (Android 6.0.1) Broadcom chipset: BCM4339 Wi-Fi Chipset bcmdhd version:Dongle Host Driver, version 1.88.45 (r) Do you need more information? Thank you, Doru
[PATCH v4 4/4] mac80211: multicast to unicast conversion
This patch adds support for sending multicast data packets with ARP, IPv4 and IPv6 payload (possible 802.1q tagged) as 802.11 unicast frames to all stations. IEEE 802.11 multicast has well known issues, among them: 1. packets are not acked and hence not retransmitted, resulting in decreased reliablity 2. packets are send at low rate, increasing time required on air When used with AP_VLAN, there is another disadvantage: 3. all stations in the BSS are woken up, regardsless of their AP_VLAN assignment. By doing multicast to unicast conversion, all three issus are solved. IEEE802.11-2012 proposes directed multicast service (DMS) using A-MSDU frames and a station initiated control protocol. It has the advantage that the station can recover the destination multicast mac address, but it is not backward compatible with non QOS stations and does not enable the administrator of a BSS to force this mode of operation within a BSS. Additionally, it would require both the ap and the station to implement the control protocol, which is optional on both ends. Furthermore, I've seen a few mobile phone stations locally that indicate qos support but won't complete DHCP if their broadcasts are encapsulated as A-MSDU. Though they work fine with this series approach. This patch therefore does not opt to implement DMS but instead just replicates the packet and changes the destination address. As this works fine with ARP, IPv4 and IPv6, it is limited to these protocols and normal 802.11 multicast frames are send out for all other payload protocols. There is a runtime toggle to enable multicast conversion in a per-bss fashion. When there is only a single station assigned to the AP_VLAN interface, no packet replication will occur. 4addr mode of operation is unchanged. This change opts for iterating all BSS stations for finding the stations assigned to this AP/AP_VLAN interface, as there currently is no per AP_VLAN list to iterate and multicast packets are expected to be few. If needed, such a list could be added later. Signed-off-by: Michael Braun -- v4: - rename MULTICAST_TO_UNICAST to MULTICAST_TO_UNICAST v3: fix compile error for trace.h v2: add nl80211 toggle rename tx_dnat to change_da change int to bool unicast --- net/mac80211/cfg.c| 15 +++ net/mac80211/debugfs_netdev.c | 3 ++ net/mac80211/ieee80211_i.h| 1 + net/mac80211/tx.c | 101 ++ 4 files changed, 120 insertions(+) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 1edb017..23f711a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2242,6 +2242,20 @@ static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev, return 0; } +static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy, + struct net_device *dev, + const bool enabled) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + if (sdata->vif.type != NL80211_IFTYPE_AP) + return -1; + + sdata->u.ap.unicast = enabled; + + return 0; +} + static void ieee80211_rfkill_poll(struct wiphy *wiphy) { struct ieee80211_local *local = wiphy_priv(wiphy); @@ -3400,6 +3414,7 @@ const struct cfg80211_ops mac80211_config_ops = { .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, .set_wds_peer = ieee80211_set_wds_peer, + .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast, .rfkill_poll = ieee80211_rfkill_poll, CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump) diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ed7bff4..a5554cc 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -487,6 +487,8 @@ static ssize_t ieee80211_if_fmt_num_buffered_multicast( } IEEE80211_IF_FILE_R(num_buffered_multicast); +IEEE80211_IF_FILE(multicast_to_unicast, u.ap.unicast, HEX); + /* IBSS attributes */ static ssize_t ieee80211_if_fmt_tsf( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -642,6 +644,7 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD(dtim_count); DEBUGFS_ADD(num_buffered_multicast); DEBUGFS_ADD_MODE(tkip_mic_test, 0200); + DEBUGFS_ADD_MODE(multicast_to_unicast, 0600); } static void add_vlan_files(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 70c0963..b23bc21 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -293,6 +293,7 @@ struct ieee80211_if_ap { driver_smps_mode; /* smps mode request */ struct work_struct request_smps_work; + bool unicast; }; struct ieee80211_if_wds { diff --git a/net/mac80211/tx.
[PATCH v4 3/4] cfg80211: configure multicast to unicast for AP interfaces
This add a userspace toggle to configure multicast to unicast. Signed-off-by: Michael Braun --- include/net/cfg80211.h | 6 ++ include/uapi/linux/nl80211.h | 10 ++ net/wireless/nl80211.c | 36 net/wireless/rdev-ops.h | 12 net/wireless/trace.h | 19 +++ 5 files changed, 83 insertions(+) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b550314..6ab8940 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2460,6 +2460,8 @@ struct cfg80211_qos_map { * * @set_wds_peer: set the WDS peer for a WDS interface * + * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS + * * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting * functions to adjust rfkill hw state * @@ -2722,6 +2724,10 @@ struct cfg80211_ops { int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev, const u8 *addr); + int (*set_multicast_to_unicast)(struct wiphy *wiphy, + struct net_device *dev, + const bool enabled); + void(*rfkill_poll)(struct wiphy *wiphy); #ifdef CONFIG_NL80211_TESTMODE diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 2206941..1b9e87b 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -599,6 +599,9 @@ * * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. * + * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if AP interface should + * perform multicast to unicast conversion (per-BSS). + * * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial * mesh config parameters may be given. * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the @@ -1026,6 +1029,8 @@ enum nl80211_commands { NL80211_CMD_ABORT_SCAN, + NL80211_CMD_SET_MULTICAST_TO_UNICAST, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1867,6 +1872,9 @@ enum nl80211_commands { * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is * used to pull the stored data for mesh peer in power save state. * + * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Multicast packets should be + * send out as unicast to all stations. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2261,6 +2269,8 @@ enum nl80211_attrs { NL80211_ATTR_MESH_PEER_AID, + NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f02653a..57b5d70 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -409,6 +409,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { .len = VHT_MUMIMO_GROUPS_DATA_LEN }, [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN }, + [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type = NLA_U8, }, }; /* policy for the key attributes */ @@ -1538,6 +1539,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, goto nla_put_failure; } CMD(set_wds_peer, SET_WDS_PEER); + CMD(set_multicast_to_unicast, SET_MULTICAST_TO_UNICAST); if (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) { CMD(tdls_mgmt, TDLS_MGMT); CMD(tdls_oper, TDLS_OPER); @@ -2164,6 +2166,32 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info) return rdev_set_wds_peer(rdev, dev, bssid); } +static int nl80211_set_multicast_to_unicast(struct sk_buff *skb, + struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + const struct nlattr *nla; + bool enabled; + + if (!info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED]) + return -EINVAL; + + if (netif_running(dev)) + return -EBUSY; + + if (!rdev->ops->set_multicast_to_unicast) + return -EOPNOTSUPP; + + if (wdev->iftype != NL80211_IFTYPE_AP) + return -EOPNOTSUPP; + + nla = info->attrs[NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED]; + enabled = nla_get_flag(nla); + return rdev_set_multicast_to_unicast(rdev, dev, enabled); +} + static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) { str
[PATCH v4 2/4] mac80211: filter multicast data packets on AP / AP_VLAN
This patch adds filtering for multicast data packets on AP_VLAN interfaces that have no authorized station connected and changes filtering on AP interfaces to not count stations assigned to AP_VLAN interfaces. This saves airtime and avoids waking up other stations currently authorized in this BSS. When using WPA, the packets dropped could not be decrypted by any station. The behaviour when there are no AP_VLAN interfaces is left unchanged. When there are AP_VLAN interfaces, this patch 1. adds filtering multicast data packets sent on AP_VLAN interfaces that have no authorized station connected. No filtering happens on 4addr AP_VLAN interfaces. 2. makes filtering of multicast data packets sent on AP interfaces depend on the number of authorized stations in this bss not assigned to an AP_VLAN interface. Therefore, a new num_mcast_sta counter is added for AP_VLAN interfaces. The existing one for AP interfaces is altered to not track stations assigned to an AP_VLAN interface. The new counter is exposed in debugfs. Signed-off-by: Michael Braun -- v4: - update description v3: - reuse existing num_mcast_sta v2: - use separate function to inc/dec mcast_sta counters - do not filter in 4addr mode - change description - change filtering on AP interface (do not count AP_VLAN sta) - use new counters regardless of 4addr or not - simplify cfg.c:change_station - remove no-op change in __cleanup_single_sta --- net/mac80211/cfg.c| 20 ++-- net/mac80211/debugfs_netdev.c | 11 +++ net/mac80211/ieee80211_i.h| 33 + net/mac80211/rx.c | 5 +++-- net/mac80211/sta_info.c | 10 ++ net/mac80211/tx.c | 5 ++--- 6 files changed, 57 insertions(+), 27 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 24133f5..1edb017 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1357,9 +1357,6 @@ static int ieee80211_change_station(struct wiphy *wiphy, goto out_err; if (params->vlan && params->vlan != sta->sdata->dev) { - bool prev_4addr = false; - bool new_4addr = false; - vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); if (params->vlan->ieee80211_ptr->use_4addr) { @@ -1369,26 +1366,21 @@ static int ieee80211_change_station(struct wiphy *wiphy, } rcu_assign_pointer(vlansdata->u.vlan.sta, sta); - new_4addr = true; __ieee80211_check_fast_rx_iface(vlansdata); } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - sta->sdata->u.vlan.sta) { + sta->sdata->u.vlan.sta) RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL); - prev_4addr = true; - } + + if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + ieee80211_vif_dec_num_mcast(sta->sdata); sta->sdata = vlansdata; ieee80211_check_fast_xmit(sta); - if (sta->sta_state == IEEE80211_STA_AUTHORIZED && - prev_4addr != new_4addr) { - if (new_4addr) - atomic_dec(&sta->sdata->bss->num_mcast_sta); - else - atomic_inc(&sta->sdata->bss->num_mcast_sta); - } + if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) + ieee80211_vif_inc_num_mcast(sta->sdata); ieee80211_send_layer2_update(sta); } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index a5ba739..ed7bff4 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -477,6 +477,7 @@ IEEE80211_IF_FILE_RW(tdls_wider_bw); IEEE80211_IF_FILE(num_mcast_sta, u.ap.num_mcast_sta, ATOMIC); IEEE80211_IF_FILE(num_sta_ps, u.ap.ps.num_sta_ps, ATOMIC); IEEE80211_IF_FILE(dtim_count, u.ap.ps.dtim_count, DEC); +IEEE80211_IF_FILE(num_mcast_sta_vlan, u.vlan.num_mcast_sta, ATOMIC); static ssize_t ieee80211_if_fmt_num_buffered_multicast( const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) @@ -643,6 +644,13 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) DEBUGFS_ADD_MODE(tkip_mic_test, 0200); } +static void add_vlan_files(struct ieee80211_sub_if_data *sdata) +{ + /* add num_mcast_sta_vlan using name num_mcast_sta */ + debugfs_create_file("num_mcast_sta", 0400, sdata->vif.debugfs_dir, + sdata, &num_mcast_sta_vlan_ops); +} + static void add_ibss_files(struct ieee80211_sub_if_data *sdata) { DEBUGFS_ADD_MODE(tsf, 0600); @@ -746,6 +754,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata) case NL80211_IFTYPE_AP: add_ap_files(sdata); break; + c
[PATCH v4 1/4] mac80211: remove unnecessary num_mcast_sta user
Checking for num_mcast_sta in __ieee80211_request_smps_ap() is unnecessary, as sta list will be empty in this case anyway, so list_for_each_entry(sta, ...) will exit immediately. Signed-off-by: Michael Braun --- net/mac80211/cfg.c | 7 --- 1 file changed, 7 deletions(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 543b1d4..24133f5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2313,13 +2313,6 @@ int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata, smps_mode == IEEE80211_SMPS_AUTOMATIC) return 0; -/* If no associated stations, there's no need to do anything */ - if (!atomic_read(&sdata->u.ap.num_mcast_sta)) { - sdata->smps_mode = smps_mode; - ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps); - 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)); -- 2.1.4
Re: [v7, 1/3] Documentation: dt: net: add ath9k wireless device binding
Martin Blumenstingl wrote: > Add documentation how devicetree can be used to configure ath9k based > devices. > > Signed-off-by: Martin Blumenstingl Looks good to me but missing the ack from DT maintainers, will wait for that. 3 patches set to Deferred. 9359805 [v7,1/3] Documentation: dt: net: add ath9k wireless device binding 9359801 [v7,2/3] ath9k: add a helper to get the string representation of ath_bus_type 9359803 [v7,3/3] ath9k: parse the device configuration from an OF node -- https://patchwork.kernel.org/patch/9359805/ Documentation about submitting wireless patches and checking status from patchwork: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [v5] ath9k: Switch to using mac80211 intermediate software queues.
Toke Høiland-Jørgensen wrote: > This switches ath9k over to using the mac80211 intermediate software > queueing mechanism for data packets. It removes the queueing inside the > driver, except for the retry queue, and instead pulls from mac80211 when > a packet is needed. The retry queue is used to store a packet that was > pulled but can't be sent immediately. > > The old code path in ath_tx_start that would queue packets has been > removed completely, as has the qlen limit tunables (since there's no > longer a queue in the driver to limit). > > Based on Tim's original patch set, but reworked quite thoroughly. > > Cc: Tim Shepard > Cc: Felix Fietkau > Signed-off-by: Toke Høiland-Jørgensen > Signed-off-by: Felix Fietkau Depends on: bb42f2d13ffc mac80211: Move reorder-sensitive TX handlers to after TXQ dequeue Patch set to Awaiting Upstream. -- https://patchwork.kernel.org/patch/9311037/ Documentation about submitting wireless patches and checking status from patchwork: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [1/2] rtl8xxxu: Fix rtl8723bu driver reload issue
Jes Sorensen wrote: > From: Jes Sorensen > > The generic disable_rf() function clears bits 22 and 23 in > REG_RX_WAIT_CCA, however we did not re-enable them again in > rtl8723b_enable_rf() > > This resolves the problem for me with 8723bu devices not working again > after reloading the driver. > > Signed-off-by: Jes Sorensen > Cc: sta...@vger.kernel.org # 4.7+ 2 patches applied to wireless-drivers.git, thanks. ab05e5ec81c7 rtl8xxxu: Fix rtl8723bu driver reload issue 29d5e6fbd65b rtl8xxxu: Fix rtl8192eu driver reload issue -- https://patchwork.kernel.org/patch/9359015/ Documentation about submitting wireless patches and checking status from patchwork: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [1/2] rtl8xxxu: Fix memory leak in handling rxdesc16 packets
Jes Sorensen wrote: > From: Jes Sorensen > > A device running without RX package aggregation could return more data > in the USB packet than the actual network packet. In this case we > could would clone the skb but then determine that that there was no > packet to handle and exit without freeing the cloned skb first. > > This has so far only been observed with 8188eu devices, but could > affect others. > > Signed-off-by: Jes Sorensen > Cc: sta...@vger.kernel.org # 4.8+ 2 patches applied to wireless-drivers.git, thanks. 1e54134ccad0 rtl8xxxu: Fix memory leak in handling rxdesc16 packets 8a55698f2f29 rtl8xxxu: Fix big-endian problem reporting mactime -- https://patchwork.kernel.org/patch/9356961/ Documentation about submitting wireless patches and checking status from patchwork: https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
[PATCH 3/3] mac80211: validate DA/SA during A-MSDU decapsulation
From: Johannes Berg As pointed out by Michael Braun, we don't check inner L2 addresses during A-MSDU decapsulation, leading to the possibility that, for example, a station associated to an AP sends frames as though they came from somewhere else. Fix this problem by letting cfg80211 validate the addresses, as indicated by passing in the ones that need to be validated. Reported-by: Michael Braun Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index cf53fe1a0aa2..a47bbc973f2d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2299,6 +2299,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) struct sk_buff_head frame_list; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); struct ethhdr ethhdr; + const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; if (unlikely(!ieee80211_is_data(fc))) return RX_CONTINUE; @@ -2322,6 +2323,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) default: return RX_DROP_UNUSABLE; } + check_da = NULL; + check_sa = NULL; + } else switch (rx->sdata->vif.type) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + check_da = NULL; + break; + case NL80211_IFTYPE_STATION: + if (!rx->sta || + !test_sta_flag(rx->sta, WLAN_STA_TDLS_PEER)) + check_sa = NULL; + break; + case NL80211_IFTYPE_MESH_POINT: + check_sa = NULL; + break; + default: + break; } if (is_multicast_ether_addr(hdr->addr1)) @@ -2338,7 +2356,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, rx->sdata->vif.type, rx->local->hw.extra_tx_headroom, -NULL, NULL); +check_da, check_sa); while (!skb_queue_empty(&frame_list)) { rx->skb = __skb_dequeue(&frame_list); -- 2.8.1
[PATCH 2/3] cfg80211: add ability to check DA/SA in A-MSDU decapsulation
From: Johannes Berg We should not accept arbitrary DA/SA inside A-MSDUs, it could be used to circumvent protections, like allowing a station to send frames and make them seem to come from somewhere else. Add the necessary infrastructure in cfg80211 to allow such checks, in further patches we'll start using them. Signed-off-by: Johannes Berg --- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- include/net/cfg80211.h | 5 - net/mac80211/rx.c| 3 ++- net/wireless/util.c | 14 -- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index e9f462e3730b..274dd5a1574a 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, -priv->wdev.iftype, 0); +priv->wdev.iftype, 0, NULL, NULL); while (!skb_queue_empty(&list)) { struct rx_packet_hdr *rx_hdr; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f372eadd1963..7df600c463eb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4090,10 +4090,13 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, * @addr: The device MAC address. * @iftype: The device interface type. * @extra_headroom: The hardware extra headroom for SKBs in the @list. + * @check_da: DA to check in the inner ethernet header, or NULL + * @check_sa: SA to check in the inner ethernet header, or NULL */ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom); + const unsigned int extra_headroom, + const u8 *check_da, const u8 *check_sa); /** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index de2d75fa5c51..cf53fe1a0aa2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2337,7 +2337,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, rx->sdata->vif.type, -rx->local->hw.extra_tx_headroom); +rx->local->hw.extra_tx_headroom, +NULL, NULL); while (!skb_queue_empty(&frame_list)) { rx->skb = __skb_dequeue(&frame_list); diff --git a/net/wireless/util.c b/net/wireless/util.c index e36ede840b88..5ea12afc7706 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -739,7 +739,8 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen, void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom) + const unsigned int extra_headroom, + const u8 *check_da, const u8 *check_sa) { unsigned int hlen = ALIGN(extra_headroom, 4); struct sk_buff *frame = NULL; @@ -767,8 +768,17 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, goto purge; offset += sizeof(struct ethhdr); - /* reuse skb for the last subframe */ last = remaining <= subframe_len + padding; + + /* FIXME: should we really accept multicast DA? */ + if ((check_da && !is_multicast_ether_addr(eth.h_dest) && +!ether_addr_equal(check_da, eth.h_dest)) || + (check_sa && !ether_addr_equal(check_sa, eth.h_source))) { + offset += len + padding; + continue; + } + + /* reuse skb for the last subframe */ if (!skb_is_nonlinear(skb) && !reuse_frag && last) { skb_pull(skb, offset); frame = skb; -- 2.8.1
[PATCH 1/3] cfg80211: let ieee80211_amsdu_to_8023s() take only header-less SKB
From: Johannes Berg There's only a single case where has_80211_header is passed as true, which is in mac80211. Given that there's only simple code that needs to be done before calling it, export that function from cfg80211 instead and let mac80211 call it itself. Signed-off-by: Johannes Berg --- .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- include/net/cfg80211.h | 31 +++--- net/mac80211/rx.c | 8 +- net/wireless/util.c| 24 - 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c index 94480123efa3..e9f462e3730b 100644 --- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c @@ -45,7 +45,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, -priv->wdev.iftype, 0, false); +priv->wdev.iftype, 0); while (!skb_queue_empty(&list)) { struct rx_packet_hdr *rx_hdr; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index fe78f02a242e..f372eadd1963 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4040,14 +4040,29 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); */ /** + * ieee80211_data_to_8023_exthdr - convert an 802.11 data frame to 802.3 + * @skb: the 802.11 data frame + * @ehdr: pointer to a &struct ethhdr that will get the header, instead + * of it being pushed into the SKB + * @addr: the device MAC address + * @iftype: the virtual interface type + * Return: 0 on success. Non-zero on error. + */ +int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, + const u8 *addr, enum nl80211_iftype iftype); + +/** * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 * @skb: the 802.11 data frame * @addr: the device MAC address * @iftype: the virtual interface type * Return: 0 on success. Non-zero on error. */ -int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, - enum nl80211_iftype iftype); +static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, +enum nl80211_iftype iftype) +{ + return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype); +} /** * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11 @@ -4065,22 +4080,20 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, /** * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame * - * Decode an IEEE 802.11n A-MSDU frame and convert it to a list of - * 802.3 frames. The @list will be empty if the decode fails. The - * @skb is consumed after the function returns. + * Decode an IEEE 802.11 A-MSDU and convert it to a list of 802.3 frames. + * The @list will be empty if the decode fails. The @skb must be fully + * header-less before being passed in here; it is freed in this function. * - * @skb: The input IEEE 802.11n A-MSDU frame. + * @skb: The input A-MSDU frame without any headers. * @list: The output list of 802.3 frames. It must be allocated and * initialized by by the caller. * @addr: The device MAC address. * @iftype: The device interface type. * @extra_headroom: The hardware extra headroom for SKBs in the @list. - * @has_80211_header: Set it true if SKB is with IEEE 802.11 header. */ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, - const unsigned int extra_headroom, - bool has_80211_header); + const unsigned int extra_headroom); /** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3ac2f1cba317..de2d75fa5c51 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2298,6 +2298,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) __le16 fc = hdr->frame_control; struct sk_buff_head frame_list; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + struct ethhdr ethhdr; if (unlikely(!ieee80211_is_data(fc))) return RX_CONTINUE; @@ -2329,9 +2330,14 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) skb->dev = dev; __skb_queue_head_init(&frame_list); + if (ieee80211_data_to_8023_exthdr(skb, ðhdr, + rx->sdata->vif.addr, +
Re: [PATCH v8] cfg80211: Provision to allow the support for different beacon intervals
On Fri, 2016-10-07 at 07:42 +, Kushwaha, Purushottam wrote: > > > > However, it seems pretty easy to solve by passing another bool that > > indicates "all the same"? > Yes . Thanks . > We are planning to get the following changes in 2 commits . Let me > know your consent . > 1. cfg80211: Provision to allow the support for different beacon > intervals. ( Would like to go with this in a separate commit as the > current infrastructure also does not support the validation of > radar_detect / num_different_channel ) . > 2. cfg80211 : Check radar_detect and num_different_channels with > beacon interface combinations. > Seems fine, no driver will be able to advertise the different BIs inbetween the two patches anyway. I think we might want to add another patch before or inbetween, that converts the far-too-long argument list of the combination iter/validation functions to a structure? johannes
RE: [PATCH v8] cfg80211: Provision to allow the support for different beacon intervals
> However, it seems pretty easy to solve by passing another bool that indicates > "all the same"? Yes . Thanks . We are planning to get the following changes in 2 commits . Let me know your consent . 1. cfg80211: Provision to allow the support for different beacon intervals. ( Would like to go with this in a separate commit as the current infrastructure also does not support the validation of radar_detect / num_different_channel ) . 2. cfg80211 : Check radar_detect and num_different_channels with beacon interface combinations. Regards, Purushottam -Original Message- From: Johannes Berg [mailto:johan...@sipsolutions.net] Sent: Wednesday, September 28, 2016 4:51 PM To: Undekari, Sunil Dutt ; Kushwaha, Purushottam Cc: linux-wireless@vger.kernel.org; Malinen, Jouni ; Hullur Subramanyam, Amarnath Subject: Re: [PATCH v8] cfg80211: Provision to allow the support for different beacon intervals Hi, > In PATCH v8 , cfg80211_validate_beacon_int -> > cfg80211_iter_combinations carries the argument iftype_num , which > also considers the "new interface" that is getting added. Ah, right, I remember now, sorry. > Thus , in the example you have quoted above , the iftype_num shall > represent 2 ( AP + AP ) , and thus the min_gcd obtained out of > cfg80211_iter_combinations (cfg80211_get_beacon_int_min_gcd) shall be > 50 for the example 1 and 200 for the example 2 . Thus , considering > the two examples mentioned above , the second AP should succeed for > "example 1" vs failure for "example 2" with patch > V8 , isn't ? Yeah, I tried to simplify and did so too much. I believe you are, for this purpose, ignoring for example radar detection. Since you're passing 0 for num_different_channels and radar_detect, you might find a combination isn't actually currently usable, but that allows the new beacon interval configuration. So I think overall this will only work right if it's done with all necessary information, no? Trying to construct another example ... let's say permitted combinations are * go = 3, channels = 1, min_bcn_gcd = 50 * go = 3, channels = 2, min_bcn_gcd = 100 (which isn't actually all that far-fetched, since channel hopping takes time) For simplification, say you already have two GOs active on different channels (with BI 100), and want to add another one - with beacon interval 50 - this isn't possible, but I don't think your code would detect it? Or, perhaps I'm reading this wrong, if your code *does* detect it then changing the scenario a bit to have just a single channel, your code would prevent it even though it's allowed? > The current behavior of the kernel is to not allow the configuration > of different beacon intervals and our expectation is that this new > patch should be backward compatible with the existing behavior. Correct, and I agree, we shouldn't break that. > Now , if we go with this approach of "introducing a new argument to > cfg80211_iter_combinations which shall be the GCD of all the existing > combinations to check against the respective > "diff_beacon_int_gcd_min"" , consider the case ( same one which is > mentioned above ) that we have a single AP interface ( beacon interval > = 300 ) , and a new AP is getting added ( beacon interval = > 150 ), with the following allowed combinations: > > 1) * ap = 2 > diff_beacon_int_gcd_min = 0 ( rather not specified ) > 2) * ap = 2 > diff_beacon_int_gcd_min = 100 > > The GCD calculated is 150 . cfg80211_iter_combinations shall return > success for both the scenarios ( 1 and 2 ) (The intention here is to > compare with only the nonzero " diff_beacon_int_gcd_min" ) > > This success from "cfg80211_iter_combinations" does not represent if > the GCD passed is compared against a 0 / non zero > "diff_beacon_int_gcd_min" , isn't ? > > Thus , we are trying to solve this problem , by getting the > "diff_beacon_int_gcd_min" for the respective interface combination , > before comparing it with the calculated GCD. Oh. I think I finally understand your concern - good point! Let me see if I understand correctly - you're saying that if I first calculate g = GCD(all BIs, including the new one) and then do cfg80211_iter_combinations(... existing variables ..., g) then I cannot accurately determine whether or not I can use a combination that doesn't specify a min_beacon_interval_gcd, you can't know if the "all BIs" were the same, or not. That's actually a very good point. However, it seems pretty easy to solve by passing another bool that indicates "all the same"? johannes
Re: [PATCH] wl18xx: Handle kfree() in better way when kzalloc fails
On Fri, Oct 7, 2016 at 12:36 PM, Johannes Berg wrote: > > On Fri, 2016-10-07 at 12:19 +0530, Souptick Joarder wrote: > > This patch is added to handle kfree and return error in a better way > > What's "better" about this? > > kfree(NULL) is perfectly valid, adding another label makes the code > harder to read, I agree with you. when kzalloc(sizeof(*cmd), GFP_KERNEL) fails, try to avoid extra kfree(cmd_channel) function call, cause anyway it will call kfree with NULL. I thought from that point of view. > > > - struct wl18xx_cmd_scan_params *cmd; > > + struct wl18xx_cmd_scan_params *cmd = NULL; > > that new initialization is actually *completely* pointless since it's > overwritten immediately here: > > > struct wlcore_scan_channels *cmd_channels = NULL; > > int ret; > > > > cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); > > if (!cmd) { > > - ret = -ENOMEM; > > - goto out; > > + return -ENOMEM; > > } > > > ... > > what gives? > > johannes Ok, I will drop this patch. -Souptick
Re: [PATCH] wl18xx: Handle kfree() in better way when kzalloc fails
On Fri, 2016-10-07 at 12:19 +0530, Souptick Joarder wrote: > This patch is added to handle kfree and return error in a better way What's "better" about this? kfree(NULL) is perfectly valid, adding another label makes the code harder to read, > - struct wl18xx_cmd_scan_params *cmd; > + struct wl18xx_cmd_scan_params *cmd = NULL; that new initialization is actually *completely* pointless since it's overwritten immediately here: > struct wlcore_scan_channels *cmd_channels = NULL; > int ret; > > cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); > if (!cmd) { > - ret = -ENOMEM; > - goto out; > + return -ENOMEM; > } > ... what gives? johannes