wifi: mac80211: Support dynamic link addition and removal

Add support for adding and removing station links:

- Adding links is done asynchronously, i.e., first
  an ML reconfiguration action frame is sent to the AP
  requesting to add links, and only when the AP replies,
  links which were added successfully by the AP are added
  locally.
- Removing links is done synchronously, i.e., the links
  are removed before sending the ML reconfiguration
  action frame to the AP (to avoid using this links after
  the AP MLD removed them but before the station got the
  ML reconfiguration response). In case the AP replies with a
  status indicating that a link removal was not successful,
  disconnect (as this should not happen an is an indication
  that something might be wrong on the AP MLD).

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20250102161730.ec0492a8dd21.I2869686642bbc0f86c40f284ebf7e6f644b551ab@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Ilan Peer
2025-01-02 16:19:58 +02:00
committed by Johannes Berg
parent fa2b73bfec
commit 36e05b0b83
6 changed files with 811 additions and 1 deletions

View File

@@ -1532,6 +1532,17 @@ struct ieee80211_mgmt {
struct {
u8 action_code;
} __packed ttlm_tear_down;
struct {
u8 action_code;
u8 dialog_token;
u8 variable[];
} __packed ml_reconf_req;
struct {
u8 action_code;
u8 dialog_token;
u8 count;
u8 variable[];
} __packed ml_reconf_resp;
} u;
} __packed action;
DECLARE_FLEX_ARRAY(u8, body); /* Generic frame body */

View File

@@ -5180,6 +5180,18 @@ ieee80211_set_ttlm(struct wiphy *wiphy, struct net_device *dev,
return ieee80211_req_neg_ttlm(sdata, params);
}
static int
ieee80211_assoc_ml_reconf(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_assoc_link *add_links,
u16 rem_links)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
lockdep_assert_wiphy(sdata->local->hw.wiphy);
return ieee80211_mgd_assoc_ml_reconf(sdata, add_links, rem_links);
}
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -5294,4 +5306,5 @@ const struct cfg80211_ops mac80211_config_ops = {
.set_hw_timestamp = ieee80211_set_hw_timestamp,
.set_ttlm = ieee80211_set_ttlm,
.get_radio_mask = ieee80211_get_radio_mask,
.assoc_ml_reconf = ieee80211_assoc_ml_reconf,
};

View File

@@ -606,6 +606,15 @@ struct ieee80211_if_managed {
/* dialog token enumerator for neg TTLM request */
u8 dialog_token_alloc;
struct wiphy_delayed_work neg_ttlm_timeout_work;
/* Locally initiated multi-link reconfiguration */
struct {
struct ieee80211_mgd_assoc_data *add_links_data;
struct wiphy_delayed_work wk;
u16 removed_links;
u16 added_links;
u8 dialog_token;
} reconf;
};
struct ieee80211_if_ibss {
@@ -2768,6 +2777,12 @@ void ieee80211_check_wbrf_support(struct ieee80211_local *local);
void ieee80211_add_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef);
void ieee80211_remove_wbrf(struct ieee80211_local *local, struct cfg80211_chan_def *chandef);
int ieee80211_mgd_assoc_ml_reconf(struct ieee80211_sub_if_data *sdata,
struct cfg80211_assoc_link *add_links,
u16 rem_links);
void ieee80211_process_ml_reconf_resp(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len);
#if IS_ENABLED(CONFIG_MAC80211_KUNIT_TEST)
#define EXPORT_SYMBOL_IF_MAC80211_KUNIT(sym) EXPORT_SYMBOL_IF_KUNIT(sym)
#define VISIBLE_IF_MAC80211_KUNIT

View File

@@ -1560,6 +1560,10 @@ static void ieee80211_iface_process_skb(struct ieee80211_local *local,
ieee80211_process_neg_ttlm_res(sdata, mgmt,
skb->len);
break;
case WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_RESP:
ieee80211_process_ml_reconf_resp(sdata, mgmt,
skb->len);
break;
default:
break;
}

File diff suppressed because it is too large Load Diff

View File

@@ -3819,6 +3819,18 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
u.action.u.ttlm_res))
goto invalid;
goto queue;
case WLAN_PROTECTED_EHT_ACTION_LINK_RECONFIG_RESP:
if (sdata->vif.type != NL80211_IFTYPE_STATION)
break;
/* The reconfiguration response action frame must
* least one 'Status Duple' entry (3 octets)
*/
if (len <
offsetofend(typeof(*mgmt),
u.action.u.ml_reconf_resp) + 3)
goto invalid;
goto queue;
default:
break;
}