wifi: mac80211: add support for tearing down negotiated TTLM
authorAyala Beker <ayala.beker@intel.com>
Mon, 18 Mar 2024 16:53:31 +0000 (18:53 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Mar 2024 14:38:15 +0000 (15:38 +0100)
In order to activate a link that is currently inactive due to
a negotiated TTLM request, need to first tear down the negotiated
TTLM request.
Add support for sending TTLM teardown request and update the links
state accordingly.

Signed-off-by: Ayala Beker <ayala.beker@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240318184907.d480cbf46fcf.Idedad472469d2c27dd2a088cf80a13a1e1cf9b78@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/status.c

index 88bb781f33f6f31ad31157cdbde41210377e9c86..f57c29de3a91a8164b1c4fde2275a9ed24d3535d 100644 (file)
@@ -7591,6 +7591,15 @@ int ieee80211_set_active_links(struct ieee80211_vif *vif, u16 active_links);
 void ieee80211_set_active_links_async(struct ieee80211_vif *vif,
                                      u16 active_links);
 
+/**
+ * ieee80211_send_teardown_neg_ttlm - tear down a negotiated TTLM request
+ * @vif: the interface on which the tear down request should be sent.
+ *
+ * This function can be used to tear down a previously accepted negotiated
+ * TTLM request.
+ */
+void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif);
+
 /* for older drivers - let's not document these ... */
 int ieee80211_emulate_add_chanctx(struct ieee80211_hw *hw,
                                  struct ieee80211_chanctx_conf *ctx);
index b6fead612b66b51df10c52e0dad6a3ed05aaabbf..925e875f9b9631fff94e6ec63a4731c59c2cb4bb 100644 (file)
@@ -89,6 +89,7 @@ enum ieee80211_status_data {
        IEEE80211_STATUS_TYPE_MASK      = 0x00f,
        IEEE80211_STATUS_TYPE_INVALID   = 0,
        IEEE80211_STATUS_TYPE_SMPS      = 1,
+       IEEE80211_STATUS_TYPE_NEG_TTLM  = 2,
        IEEE80211_STATUS_SUBDATA_MASK   = 0xff0,
 };
 
@@ -595,6 +596,7 @@ struct ieee80211_if_managed {
        /* TID-to-link mapping support */
        struct wiphy_delayed_work ttlm_work;
        struct ieee80211_adv_ttlm_info ttlm_info;
+       struct wiphy_work teardown_ttlm_work;
 
        /* dialog token enumerator for neg TTLM request */
        u8 dialog_token_alloc;
index 2d73f0f4dd2d68aa2b5dcf09ff90ef5cca06040f..b653c7d5025f15facdbe45eb32de912d039d22bd 100644 (file)
@@ -6790,6 +6790,60 @@ void ieee80211_process_neg_ttlm_res(struct ieee80211_sub_if_data *sdata,
                __ieee80211_disconnect(sdata);
 }
 
+static void ieee80211_teardown_ttlm_work(struct wiphy *wiphy,
+                                        struct wiphy_work *work)
+{
+       u16 new_dormant_links;
+       struct ieee80211_sub_if_data *sdata =
+               container_of(work, struct ieee80211_sub_if_data,
+                            u.mgd.neg_ttlm_timeout_work.work);
+
+       if (!sdata->vif.neg_ttlm.valid)
+               return;
+
+       memset(&sdata->vif.neg_ttlm, 0, sizeof(sdata->vif.neg_ttlm));
+       new_dormant_links =
+               sdata->vif.dormant_links & ~sdata->vif.suspended_links;
+       sdata->vif.suspended_links = 0;
+       ieee80211_vif_set_links(sdata, sdata->vif.valid_links,
+                               new_dormant_links);
+       ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_MLD_TTLM |
+                                              BSS_CHANGED_MLD_VALID_LINKS);
+}
+
+void ieee80211_send_teardown_neg_ttlm(struct ieee80211_vif *vif)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_mgmt *mgmt;
+       struct sk_buff *skb;
+       int frame_len = offsetofend(struct ieee80211_mgmt,
+                                 u.action.u.ttlm_tear_down);
+       struct ieee80211_tx_info *info;
+
+       skb = dev_alloc_skb(local->hw.extra_tx_headroom + frame_len);
+       if (!skb)
+               return;
+
+       skb_reserve(skb, local->hw.extra_tx_headroom);
+       mgmt = skb_put_zero(skb, frame_len);
+       mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+                                         IEEE80211_STYPE_ACTION);
+       memcpy(mgmt->da, sdata->vif.cfg.ap_addr, ETH_ALEN);
+       memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+       memcpy(mgmt->bssid, sdata->vif.cfg.ap_addr, ETH_ALEN);
+
+       mgmt->u.action.category = WLAN_CATEGORY_PROTECTED_EHT;
+       mgmt->u.action.u.ttlm_tear_down.action_code =
+               WLAN_PROTECTED_EHT_ACTION_TTLM_TEARDOWN;
+
+       info = IEEE80211_SKB_CB(skb);
+       info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+       info->status_data = IEEE80211_STATUS_TYPE_NEG_TTLM;
+       ieee80211_tx_skb(sdata, skb);
+}
+EXPORT_SYMBOL(ieee80211_send_teardown_neg_ttlm);
+
 void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata,
                                 struct sk_buff *skb)
 {
@@ -7421,6 +7475,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
                                ieee80211_tid_to_link_map_work);
        wiphy_delayed_work_init(&ifmgd->neg_ttlm_timeout_work,
                                ieee80211_neg_ttlm_timeout_work);
+       wiphy_work_init(&ifmgd->teardown_ttlm_work,
+                       ieee80211_teardown_ttlm_work);
 
        ifmgd->flags = 0;
        ifmgd->powersave = sdata->wdev.ps;
@@ -8609,6 +8665,8 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
                          &ifmgd->beacon_connection_loss_work);
        wiphy_work_cancel(sdata->local->hw.wiphy,
                          &ifmgd->csa_connection_drop_work);
+       wiphy_work_cancel(sdata->local->hw.wiphy,
+                         &ifmgd->teardown_ttlm_work);
        wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
                                  &ifmgd->tdls_peer_del_work);
        wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
index 1708b33cdc5eba258fc1a382e8b54c19af9fb4d8..dd8f857a1fbcde8fe3d02e5cc23b3b49a5132dd2 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
- * Copyright 2021-2023  Intel Corporation
+ * Copyright 2021-2024  Intel Corporation
  */
 
 #include <linux/export.h>
@@ -696,6 +696,23 @@ static void ieee80211_handle_smps_status(struct ieee80211_sub_if_data *sdata,
        wiphy_work_queue(sdata->local->hw.wiphy, &link->u.mgd.recalc_smps);
 }
 
+static void
+ieee80211_handle_teardown_ttlm_status(struct ieee80211_sub_if_data *sdata,
+                                     bool acked)
+{
+       if (!sdata || !ieee80211_sdata_running(sdata))
+               return;
+
+       if (!acked)
+               return;
+
+       if (sdata->vif.type != NL80211_IFTYPE_STATION)
+               return;
+
+       wiphy_work_queue(sdata->local->hw.wiphy,
+                        &sdata->u.mgd.teardown_ttlm_work);
+}
+
 static void ieee80211_report_used_skb(struct ieee80211_local *local,
                                      struct sk_buff *skb, bool dropped,
                                      ktime_t ack_hwtstamp)
@@ -773,6 +790,9 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
                        ieee80211_handle_smps_status(sdata, acked,
                                                     info->status_data);
                        break;
+               case IEEE80211_STATUS_TYPE_NEG_TTLM:
+                       ieee80211_handle_teardown_ttlm_status(sdata, acked);
+                       break;
                }
                rcu_read_unlock();
        }