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

mac80211: MBSSID support in interface handling

Configure multiple BSSID and enhanced multi-BSSID advertisement (EMA)
parameters in mac80211 for AP mode.

For each interface, 'mbssid_tx_vif' points to the transmitting interface of
the MBSSID set. The pointer is set to NULL if MBSSID is disabled.

Function ieee80211_stop() is modified to always bring down all the
non-transmitting interfaces first and the transmitting interface last.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
Link: https://lore.kernel.org/r/20210916025437.29138-3-alokad@codeaurora.org
[slightly change logic to be more obvious]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>

authored by

John Crispin and committed by
Johannes Berg
17196425 dc1e3cb8

+71 -1
+3
include/net/mac80211.h
··· 1723 1723 * write-protected by sdata_lock and local->mtx so holding either is fine 1724 1724 * for read access. 1725 1725 * @color_change_color: the bss color that will be used after the change. 1726 + * @mbssid_tx_vif: Pointer to the transmitting interface if MBSSID is enabled. 1726 1727 */ 1727 1728 struct ieee80211_vif { 1728 1729 enum nl80211_iftype type; ··· 1754 1753 1755 1754 bool color_change_active; 1756 1755 u8 color_change_color; 1756 + 1757 + struct ieee80211_vif *mbssid_tx_vif; 1757 1758 1758 1759 /* must be last */ 1759 1760 u8 drv_priv[] __aligned(sizeof(void *));
+38
net/mac80211/cfg.c
··· 111 111 return 0; 112 112 } 113 113 114 + static int ieee80211_set_ap_mbssid_options(struct ieee80211_sub_if_data *sdata, 115 + struct cfg80211_mbssid_config params) 116 + { 117 + struct ieee80211_sub_if_data *tx_sdata; 118 + 119 + sdata->vif.mbssid_tx_vif = NULL; 120 + sdata->vif.bss_conf.bssid_index = 0; 121 + sdata->vif.bss_conf.nontransmitted = false; 122 + sdata->vif.bss_conf.ema_ap = false; 123 + 124 + if (sdata->vif.type != NL80211_IFTYPE_AP || !params.tx_wdev) 125 + return -EINVAL; 126 + 127 + tx_sdata = IEEE80211_WDEV_TO_SUB_IF(params.tx_wdev); 128 + if (!tx_sdata) 129 + return -EINVAL; 130 + 131 + if (tx_sdata == sdata) { 132 + sdata->vif.mbssid_tx_vif = &sdata->vif; 133 + } else { 134 + sdata->vif.mbssid_tx_vif = &tx_sdata->vif; 135 + sdata->vif.bss_conf.nontransmitted = true; 136 + sdata->vif.bss_conf.bssid_index = params.index; 137 + } 138 + if (params.ema) 139 + sdata->vif.bss_conf.ema_ap = true; 140 + 141 + return 0; 142 + } 143 + 114 144 static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, 115 145 const char *name, 116 146 unsigned char name_assign_type, ··· 1133 1103 1134 1104 if (params->he_bss_color.enabled) 1135 1105 changed |= BSS_CHANGED_HE_BSS_COLOR; 1106 + } 1107 + 1108 + if (sdata->vif.type == NL80211_IFTYPE_AP && 1109 + params->mbssid_config.tx_wdev) { 1110 + err = ieee80211_set_ap_mbssid_options(sdata, 1111 + params->mbssid_config); 1112 + if (err) 1113 + return err; 1136 1114 } 1137 1115 1138 1116 mutex_lock(&local->mtx);
+30 -1
net/mac80211/iface.c
··· 632 632 ieee80211_add_virtual_monitor(local); 633 633 } 634 634 635 + static void ieee80211_stop_mbssid(struct ieee80211_sub_if_data *sdata) 636 + { 637 + struct ieee80211_sub_if_data *tx_sdata, *non_tx_sdata, *tmp_sdata; 638 + struct ieee80211_vif *tx_vif = sdata->vif.mbssid_tx_vif; 639 + 640 + if (!tx_vif) 641 + return; 642 + 643 + tx_sdata = vif_to_sdata(tx_vif); 644 + sdata->vif.mbssid_tx_vif = NULL; 645 + 646 + list_for_each_entry_safe(non_tx_sdata, tmp_sdata, 647 + &tx_sdata->local->interfaces, list) { 648 + if (non_tx_sdata != sdata && non_tx_sdata != tx_sdata && 649 + non_tx_sdata->vif.mbssid_tx_vif == tx_vif && 650 + ieee80211_sdata_running(non_tx_sdata)) { 651 + non_tx_sdata->vif.mbssid_tx_vif = NULL; 652 + dev_close(non_tx_sdata->wdev.netdev); 653 + } 654 + } 655 + 656 + if (sdata != tx_sdata && ieee80211_sdata_running(tx_sdata)) { 657 + tx_sdata->vif.mbssid_tx_vif = NULL; 658 + dev_close(tx_sdata->wdev.netdev); 659 + } 660 + } 661 + 635 662 static int ieee80211_stop(struct net_device *dev) 636 663 { 637 664 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 638 665 639 - /* close all dependent VLAN interfaces before locking wiphy */ 666 + /* close dependent VLAN and MBSSID interfaces before locking wiphy */ 640 667 if (sdata->vif.type == NL80211_IFTYPE_AP) { 641 668 struct ieee80211_sub_if_data *vlan, *tmpsdata; 642 669 643 670 list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, 644 671 u.vlan.list) 645 672 dev_close(vlan->dev); 673 + 674 + ieee80211_stop_mbssid(sdata); 646 675 } 647 676 648 677 wiphy_lock(sdata->local->hw.wiphy);