Skip to content

Commit 702e804

Browse files
AyalaBkrjmberg-intel
authored andcommitted
wifi: mac80211: support handling of advertised TID-to-link mapping
Support handling of advertised TID-to-link mapping elements received in a beacon. These elements are used by AP MLD to disable specific links and force all clients to stop using these links. By default if no TID-to-link mapping is advertised, all TIDs shall be mapped to all links. Signed-off-by: Ayala Beker <ayala.beker@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230920211508.623c4b692ff9.Iab0a6f561d85b8ab6efe541590985a2b6e9e74aa@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 62e9c64 commit 702e804

File tree

2 files changed

+211
-0
lines changed

2 files changed

+211
-0
lines changed

net/mac80211/ieee80211_i.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,17 @@ struct ieee80211_sta_tx_tspec {
467467
bool downgraded;
468468
};
469469

470+
/* Advertised TID-to-link mapping info */
471+
struct ieee80211_adv_ttlm_info {
472+
/* time in TUs at which the new mapping is established, or 0 if there is
473+
* no planned advertised TID-to-link mapping
474+
*/
475+
u16 switch_time;
476+
u32 duration; /* duration of the planned T2L map in TUs */
477+
u16 map; /* map of usable links for all TIDs */
478+
bool active; /* whether the advertised mapping is active or not */
479+
};
480+
470481
DECLARE_EWMA(beacon_signal, 4, 4)
471482

472483
struct ieee80211_if_managed {
@@ -560,6 +571,10 @@ struct ieee80211_if_managed {
560571

561572
struct wiphy_delayed_work ml_reconf_work;
562573
u16 removed_links;
574+
575+
/* TID-to-link mapping support */
576+
struct wiphy_delayed_work ttlm_work;
577+
struct ieee80211_adv_ttlm_info ttlm_info;
563578
};
564579

565580
struct ieee80211_if_ibss {

net/mac80211/mlme.c

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
30533053
memset(sdata->vif.bss_conf.tx_pwr_env, 0,
30543054
sizeof(sdata->vif.bss_conf.tx_pwr_env));
30553055

3056+
memset(&sdata->u.mgd.ttlm_info, 0,
3057+
sizeof(sdata->u.mgd.ttlm_info));
3058+
wiphy_delayed_work_cancel(sdata->local->hw.wiphy, &ifmgd->ttlm_work);
30563059
ieee80211_vif_set_links(sdata, 0, 0);
30573060
}
30583061

@@ -5821,6 +5824,194 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata,
58215824
TU_TO_JIFFIES(delay));
58225825
}
58235826

5827+
static void ieee80211_tid_to_link_map_work(struct wiphy *wiphy,
5828+
struct wiphy_work *work)
5829+
{
5830+
u16 new_active_links, new_dormant_links;
5831+
struct ieee80211_sub_if_data *sdata =
5832+
container_of(work, struct ieee80211_sub_if_data,
5833+
u.mgd.ttlm_work.work);
5834+
int ret;
5835+
5836+
new_active_links = sdata->u.mgd.ttlm_info.map &
5837+
sdata->vif.valid_links;
5838+
new_dormant_links = ~sdata->u.mgd.ttlm_info.map &
5839+
sdata->vif.valid_links;
5840+
if (!new_active_links) {
5841+
ieee80211_disconnect(&sdata->vif, false);
5842+
return;
5843+
}
5844+
5845+
ieee80211_vif_set_links(sdata, sdata->vif.valid_links, 0);
5846+
new_active_links = BIT(ffs(new_active_links) - 1);
5847+
ieee80211_set_active_links(&sdata->vif, new_active_links);
5848+
5849+
ret = ieee80211_vif_set_links(sdata, sdata->vif.valid_links,
5850+
new_dormant_links);
5851+
5852+
sdata->u.mgd.ttlm_info.active = true;
5853+
sdata->u.mgd.ttlm_info.switch_time = 0;
5854+
5855+
if (!ret)
5856+
ieee80211_vif_cfg_change_notify(sdata,
5857+
BSS_CHANGED_MLD_VALID_LINKS);
5858+
}
5859+
5860+
static u16 ieee80211_get_ttlm(u8 bm_size, u8 *data)
5861+
{
5862+
if (bm_size == 1)
5863+
return *data;
5864+
else
5865+
return get_unaligned_le16(data);
5866+
}
5867+
5868+
static int
5869+
ieee80211_parse_adv_t2l(struct ieee80211_sub_if_data *sdata,
5870+
const struct ieee80211_ttlm_elem *ttlm,
5871+
struct ieee80211_adv_ttlm_info *ttlm_info)
5872+
{
5873+
/* The element size was already validated in
5874+
* ieee80211_tid_to_link_map_size_ok()
5875+
*/
5876+
u8 control, link_map_presence, map_size, tid;
5877+
u8 *pos;
5878+
5879+
memset(ttlm_info, 0, sizeof(*ttlm_info));
5880+
pos = (void *)ttlm->optional;
5881+
control = ttlm->control;
5882+
5883+
if ((control & IEEE80211_TTLM_CONTROL_DEF_LINK_MAP) ||
5884+
!(control & IEEE80211_TTLM_CONTROL_SWITCH_TIME_PRESENT))
5885+
return 0;
5886+
5887+
if ((control & IEEE80211_TTLM_CONTROL_DIRECTION) !=
5888+
IEEE80211_TTLM_DIRECTION_BOTH) {
5889+
sdata_info(sdata, "Invalid advertised T2L map direction\n");
5890+
return -EINVAL;
5891+
}
5892+
5893+
link_map_presence = *pos;
5894+
pos++;
5895+
5896+
ttlm_info->switch_time = get_unaligned_le16(pos);
5897+
pos += 2;
5898+
5899+
if (control & IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT) {
5900+
ttlm_info->duration = pos[0] | pos[1] << 8 | pos[2] << 16;
5901+
pos += 3;
5902+
}
5903+
5904+
if (control & IEEE80211_TTLM_CONTROL_LINK_MAP_SIZE)
5905+
map_size = 1;
5906+
else
5907+
map_size = 2;
5908+
5909+
/* According to Draft P802.11be_D3.0 clause 35.3.7.1.7, an AP MLD shall
5910+
* not advertise a TID-to-link mapping that does not map all TIDs to the
5911+
* same link set, reject frame if not all links have mapping
5912+
*/
5913+
if (link_map_presence != 0xff) {
5914+
sdata_info(sdata,
5915+
"Invalid advertised T2L mapping presence indicator\n");
5916+
return -EINVAL;
5917+
}
5918+
5919+
ttlm_info->map = ieee80211_get_ttlm(map_size, pos);
5920+
if (!ttlm_info->map) {
5921+
sdata_info(sdata,
5922+
"Invalid advertised T2L map for TID 0\n");
5923+
return -EINVAL;
5924+
}
5925+
5926+
pos += map_size;
5927+
5928+
for (tid = 1; tid < 8; tid++) {
5929+
u16 map = ieee80211_get_ttlm(map_size, pos);
5930+
5931+
if (map != ttlm_info->map) {
5932+
sdata_info(sdata, "Invalid advertised T2L map for tid %d\n",
5933+
tid);
5934+
return -EINVAL;
5935+
}
5936+
5937+
pos += map_size;
5938+
}
5939+
return 0;
5940+
}
5941+
5942+
static void ieee80211_process_adv_ttlm(struct ieee80211_sub_if_data *sdata,
5943+
struct ieee802_11_elems *elems,
5944+
u64 beacon_ts)
5945+
{
5946+
u8 i;
5947+
int ret;
5948+
5949+
if (!ieee80211_vif_is_mld(&sdata->vif))
5950+
return;
5951+
5952+
if (!elems->ttlm_num) {
5953+
if (sdata->u.mgd.ttlm_info.switch_time) {
5954+
/* if a planned TID-to-link mapping was cancelled -
5955+
* abort it
5956+
*/
5957+
wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
5958+
&sdata->u.mgd.ttlm_work);
5959+
} else if (sdata->u.mgd.ttlm_info.active) {
5960+
/* if no TID-to-link element, set to default mapping in
5961+
* which all TIDs are mapped to all setup links
5962+
*/
5963+
ret = ieee80211_vif_set_links(sdata,
5964+
sdata->vif.valid_links,
5965+
0);
5966+
if (ret) {
5967+
sdata_info(sdata, "Failed setting valid/dormant links\n");
5968+
return;
5969+
}
5970+
ieee80211_vif_cfg_change_notify(sdata,
5971+
BSS_CHANGED_MLD_VALID_LINKS);
5972+
}
5973+
memset(&sdata->u.mgd.ttlm_info, 0,
5974+
sizeof(sdata->u.mgd.ttlm_info));
5975+
return;
5976+
}
5977+
5978+
for (i = 0; i < elems->ttlm_num; i++) {
5979+
struct ieee80211_adv_ttlm_info ttlm_info;
5980+
u32 res;
5981+
5982+
res = ieee80211_parse_adv_t2l(sdata, elems->ttlm[i],
5983+
&ttlm_info);
5984+
5985+
if (res) {
5986+
__ieee80211_disconnect(sdata);
5987+
return;
5988+
}
5989+
5990+
if (ttlm_info.switch_time) {
5991+
u32 st_us, delay = 0;
5992+
u32 ts_l26 = beacon_ts & GENMASK(25, 0);
5993+
5994+
/* The t2l map switch time is indicated with a partial
5995+
* TSF value, convert it to TSF and calc the delay
5996+
* to the start time.
5997+
*/
5998+
st_us = ieee80211_tu_to_usec(ttlm_info.switch_time);
5999+
if (st_us > ts_l26)
6000+
delay = st_us - ts_l26;
6001+
else
6002+
continue;
6003+
6004+
sdata->u.mgd.ttlm_info = ttlm_info;
6005+
wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
6006+
&sdata->u.mgd.ttlm_work);
6007+
wiphy_delayed_work_queue(sdata->local->hw.wiphy,
6008+
&sdata->u.mgd.ttlm_work,
6009+
usecs_to_jiffies(delay));
6010+
return;
6011+
}
6012+
}
6013+
}
6014+
58246015
static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
58256016
struct ieee80211_hdr *hdr, size_t len,
58266017
struct ieee80211_rx_status *rx_status)
@@ -6144,6 +6335,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
61446335
}
61456336

61466337
ieee80211_ml_reconfiguration(sdata, elems);
6338+
ieee80211_process_adv_ttlm(sdata, elems,
6339+
le64_to_cpu(mgmt->u.beacon.timestamp));
61476340

61486341
ieee80211_link_info_change_notify(sdata, link, changed);
61496342
free:
@@ -6766,6 +6959,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
67666959
timer_setup(&ifmgd->conn_mon_timer, ieee80211_sta_conn_mon_timer, 0);
67676960
wiphy_delayed_work_init(&ifmgd->tx_tspec_wk,
67686961
ieee80211_sta_handle_tspec_ac_params_wk);
6962+
wiphy_delayed_work_init(&ifmgd->ttlm_work,
6963+
ieee80211_tid_to_link_map_work);
67696964

67706965
ifmgd->flags = 0;
67716966
ifmgd->powersave = sdata->wdev.ps;
@@ -7840,6 +8035,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
78408035
&ifmgd->tdls_peer_del_work);
78418036
wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
78428037
&ifmgd->ml_reconf_work);
8038+
wiphy_delayed_work_cancel(sdata->local->hw.wiphy, &ifmgd->ttlm_work);
78438039

78448040
if (ifmgd->assoc_data)
78458041
ieee80211_destroy_assoc_data(sdata, ASSOC_TIMEOUT);

0 commit comments

Comments
 (0)