mac80211: add multiple bssid support
[openwrt/staging/blogic.git] / package / kernel / mac80211 / patches / subsys / 601-mac80211-add-multiple-bssid-support-to-interface-han.patch
diff --git a/package/kernel/mac80211/patches/subsys/601-mac80211-add-multiple-bssid-support-to-interface-han.patch b/package/kernel/mac80211/patches/subsys/601-mac80211-add-multiple-bssid-support-to-interface-han.patch
new file mode 100644 (file)
index 0000000..1065526
--- /dev/null
@@ -0,0 +1,197 @@
+From 5ec6d96689c93093f51e233da5d28c6cd49f85ae Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Tue, 6 Oct 2020 15:45:37 +0200
+Subject: [PATCH 2/4] mac80211: add multiple bssid support to interface
+ handling
+
+When bringing up multi bssid APs we need to track the parent-child relation
+of non-transmitting and transmitting VAPs. This patch checks the above by
+using a linked list to track the relations. The patch also ensures that
+when a non-transmitting interface is closed the transmitting one is also
+closed.
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ include/net/mac80211.h | 28 +++++++++++++++++++++-
+ net/mac80211/cfg.c     | 53 ++++++++++++++++++++++++++++++++++++++++++
+ net/mac80211/debugfs.c |  1 +
+ net/mac80211/iface.c   |  6 +++++
+ 4 files changed, 87 insertions(+), 1 deletion(-)
+
+Index: backports-5.8-1/include/net/mac80211.h
+===================================================================
+--- backports-5.8-1.orig/include/net/mac80211.h
++++ backports-5.8-1/include/net/mac80211.h
+@@ -674,6 +674,7 @@ struct ieee80211_bss_conf {
+       } he_oper;
+       struct ieee80211_he_obss_pd he_obss_pd;
+       struct cfg80211_he_bss_color he_bss_color;
++      struct ieee80211_multiple_bssid multiple_bssid;
+ };
+ /**
+@@ -1623,6 +1624,20 @@ enum ieee80211_offload_flags {
+ };
+ /**
++ * enum ieee80211_vif_multiple_bssid_flags - virtual interface multiple bssid flags
++ *
++ * @IEEE80211_VIF_MBSS_TRANSMITTING: this BSS is transmitting beacons
++ * @IEEE80211_VIF_MBSS_NON_TRANSMITTING: this BSS is not transmitting beacons
++ * @IEEE80211_VIF_MBSS_EMA_BEACON: beacons should be send out in EMA mode
++*/
++
++enum ieee80211_vif_multiple_bssid_flags {
++      IEEE80211_VIF_MBSS_TRANSMITTING         = BIT(1),
++      IEEE80211_VIF_MBSS_NON_TRANSMITTING     = BIT(2),
++      IEEE80211_VIF_MBSS_EMA_BEACON           = BIT(3),
++};
++
++/**
+  * struct ieee80211_vif - per-interface data
+  *
+  * Data in this structure is continually present for driver
+@@ -1693,6 +1708,10 @@ struct ieee80211_vif {
+       bool rx_mcast_action_reg;
+       bool txqs_stopped[IEEE80211_NUM_ACS];
++      struct {
++              struct ieee80211_vif *parent;
++              u32 flags;
++      } multiple_bssid;
+       /* must be last */
+       u8 drv_priv[] __aligned(sizeof(void *));
+@@ -2341,7 +2360,7 @@ struct ieee80211_txq {
+  * @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
+  *    length in tx status information
+  *
+- * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID
++ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID in STA mode
+  *
+  * @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
+  *    only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
+@@ -2353,6 +2372,8 @@ struct ieee80211_txq {
+  * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
+  *    offload
+  *
++ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP: Hardware supports multi BSSID in AP mode
++ *
+  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
+  */
+ enum ieee80211_hw_flags {
+@@ -2406,6 +2427,7 @@ enum ieee80211_hw_flags {
+       IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
+       IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
+       IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
++      IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP,
+       /* keep last, obviously */
+       NUM_IEEE80211_HW_FLAGS
+Index: backports-5.8-1/net/mac80211/cfg.c
+===================================================================
+--- backports-5.8-1.orig/net/mac80211/cfg.c
++++ backports-5.8-1/net/mac80211/cfg.c
+@@ -111,6 +111,39 @@ static int ieee80211_set_mon_options(str
+       return 0;
+ }
++static void ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata,
++                                               struct cfg80211_ap_settings *params)
++{
++      struct ieee80211_local *local = sdata->local;
++      struct wiphy *wiphy = local->hw.wiphy;
++      struct net_device *parent;
++      struct ieee80211_sub_if_data *psdata;
++
++      if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
++              return;
++
++      if (!params->multiple_bssid.count)
++              return;
++
++      if (params->multiple_bssid.parent) {
++              parent = __dev_get_by_index(wiphy_net(wiphy),
++                                          params->multiple_bssid.parent);
++              if (!parent || !parent->ieee80211_ptr)
++                      return;
++              psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr);
++              if (psdata->vif.multiple_bssid.parent)
++                      return;
++              sdata->vif.multiple_bssid.parent = &psdata->vif;
++              sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_NON_TRANSMITTING;
++      } else {
++              sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_TRANSMITTING;
++      }
++
++      if (params->multiple_bssid.ema)
++              sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_EMA_BEACON;
++      sdata->vif.bss_conf.multiple_bssid = params->multiple_bssid;
++}
++
+ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
+                                               const char *name,
+                                               unsigned char name_assign_type,
+@@ -141,6 +174,23 @@ static struct wireless_dev *ieee80211_ad
+ static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
+ {
++      struct ieee80211_sub_if_data *sdata;
++
++      sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
++      if (sdata->vif.type == NL80211_IFTYPE_AP) {
++              if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) {
++                      struct ieee80211_sub_if_data *child;
++
++                      rcu_read_lock();
++                      list_for_each_entry_rcu(child, &sdata->local->interfaces, list)
++                              if (child->vif.multiple_bssid.parent == &sdata->vif)
++                                      dev_close(child->wdev.netdev);
++                      rcu_read_unlock();
++              } else {
++                      sdata->vif.multiple_bssid.parent = NULL;
++              }
++      }
++
+       ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
+       return 0;
+@@ -1021,6 +1071,9 @@ static int ieee80211_start_ap(struct wip
+                             IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
+       }
++      if (sdata->vif.type == NL80211_IFTYPE_AP)
++              ieee80211_set_multiple_bssid_options(sdata, params);
++
+       mutex_lock(&local->mtx);
+       err = ieee80211_vif_use_channel(sdata, &params->chandef,
+                                       IEEE80211_CHANCTX_SHARED);
+Index: backports-5.8-1/net/mac80211/debugfs.c
+===================================================================
+--- backports-5.8-1.orig/net/mac80211/debugfs.c
++++ backports-5.8-1/net/mac80211/debugfs.c
+@@ -409,6 +409,7 @@ static const char *hw_flag_names[] = {
+       FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
+       FLAG(AMPDU_KEYBORDER_SUPPORT),
+       FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
++      FLAG(SUPPORTS_MULTI_BSSID_AP),
+ #undef FLAG
+ };
+Index: backports-5.8-1/net/mac80211/iface.c
+===================================================================
+--- backports-5.8-1.orig/net/mac80211/iface.c
++++ backports-5.8-1/net/mac80211/iface.c
+@@ -377,6 +377,12 @@ static void ieee80211_do_stop(struct iee
+       bool cancel_scan;
+       struct cfg80211_nan_func *func;
++      /* make sure the parent is already down */
++      if (sdata->vif.type == NL80211_IFTYPE_AP &&
++          sdata->vif.multiple_bssid.parent &&
++          ieee80211_sdata_running(vif_to_sdata(sdata->vif.multiple_bssid.parent)))
++              dev_close(vif_to_sdata(sdata->vif.multiple_bssid.parent)->wdev.netdev);
++
+       clear_bit(SDATA_STATE_RUNNING, &sdata->state);
+       cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;