wifi: mac80211: add support for tearing down negotiated TTLM

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>
This commit is contained in:
Ayala Beker 2024-03-18 18:53:31 +02:00 committed by Johannes Berg
parent 97f8df4db4
commit a17a58ad2f
4 changed files with 90 additions and 1 deletions

View 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);

View 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;

View 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,

View 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();
}