Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mac80211: correct MU-MIMO monitor follow functionality

The MU-MIMO monitor follow functionality is broken because it
doesn't clear the MU-MIMO owner even if both follow features
are disabled. Fix that, and while at it move the code into a
new helper function. Call this also when creating a new monitor
interface to prepare for an upcoming cfg80211 change allowing
that.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>

+58 -20
+58 -20
net/mac80211/cfg.c
··· 22 22 #include "mesh.h" 23 23 #include "wme.h" 24 24 25 + static int ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata, 26 + struct vif_params *params) 27 + { 28 + struct ieee80211_local *local = sdata->local; 29 + struct ieee80211_sub_if_data *monitor_sdata; 30 + bool mu_mimo_groups = false; 31 + bool mu_mimo_follow = false; 32 + 33 + monitor_sdata = rtnl_dereference(local->monitor_sdata); 34 + 35 + if (!monitor_sdata) 36 + return -EOPNOTSUPP; 37 + 38 + if (params->vht_mumimo_groups) { 39 + u64 membership; 40 + 41 + BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN); 42 + 43 + memcpy(monitor_sdata->vif.bss_conf.mu_group.membership, 44 + params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN); 45 + memcpy(monitor_sdata->vif.bss_conf.mu_group.position, 46 + params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN, 47 + WLAN_USER_POSITION_LEN); 48 + ieee80211_bss_info_change_notify(monitor_sdata, 49 + BSS_CHANGED_MU_GROUPS); 50 + /* don't care about endianness - just check for 0 */ 51 + memcpy(&membership, params->vht_mumimo_groups, 52 + WLAN_MEMBERSHIP_LEN); 53 + mu_mimo_groups = membership != 0; 54 + } 55 + 56 + if (params->vht_mumimo_follow_addr) { 57 + mu_mimo_follow = 58 + is_valid_ether_addr(params->vht_mumimo_follow_addr); 59 + ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr, 60 + params->vht_mumimo_follow_addr); 61 + } 62 + 63 + monitor_sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow; 64 + 65 + return 0; 66 + } 67 + 25 68 static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, 26 69 const char *name, 27 70 unsigned char name_assign_type, ··· 81 38 if (err) 82 39 return ERR_PTR(err); 83 40 84 - if (type == NL80211_IFTYPE_MONITOR && flags) { 85 - sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); 86 - sdata->u.mntr.flags = *flags; 41 + sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); 42 + 43 + if (type == NL80211_IFTYPE_MONITOR) { 44 + err = ieee80211_set_mu_mimo_follow(sdata, params); 45 + if (err) { 46 + ieee80211_if_remove(sdata); 47 + return NULL; 48 + } 49 + 50 + if (flags) 51 + sdata->u.mntr.flags = *flags; 87 52 } 88 53 89 54 return wdev; ··· 127 76 128 77 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { 129 78 struct ieee80211_local *local = sdata->local; 130 - struct ieee80211_sub_if_data *monitor_sdata; 131 - u32 mu_mntr_cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; 79 + int err; 132 80 133 - monitor_sdata = rtnl_dereference(local->monitor_sdata); 134 - if (monitor_sdata && params->vht_mumimo_groups) { 135 - memcpy(monitor_sdata->vif.bss_conf.mu_group.membership, 136 - params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN); 137 - memcpy(monitor_sdata->vif.bss_conf.mu_group.position, 138 - params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN, 139 - WLAN_USER_POSITION_LEN); 140 - monitor_sdata->vif.mu_mimo_owner = true; 141 - ieee80211_bss_info_change_notify(monitor_sdata, 142 - BSS_CHANGED_MU_GROUPS); 143 - } 144 - 145 - if (monitor_sdata && params->vht_mumimo_follow_addr) 146 - ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr, 147 - params->vht_mumimo_follow_addr); 81 + err = ieee80211_set_mu_mimo_follow(sdata, params); 82 + if (err) 83 + return err; 148 84 149 85 if (!flags) 150 86 return 0;