mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
wifi: mac80211: synchronize valid links for WDS AP_VLAN interfaces
The current code does not provide any link-configuration support for 4-address mode WDS AP_VLAN interfaces in MLO setups, preventing MLD stations from being added correctly. Add the required handling to enable proper integration of 4-address WDS stations into an MLO environment. When a 4-address station associates with an MLO AP, compute the intersection of valid links between the master AP interface and the station's advertised capabilities. Configure the AP_VLAN interface with only these common links to ensure correct data-path operation. This update ensures AP_VLAN interfaces correctly track link-state transitions and maintain consistent addressing across all active MLO links. Co-developed-by: Muna Sinada <muna.sinada@oss.qualcomm.com> Signed-off-by: Muna Sinada <muna.sinada@oss.qualcomm.com> Signed-off-by: Tamizh Chelvam Raja <tamizh.raja@oss.qualcomm.com> Link: https://patch.msgid.link/20260326164723.553927-2-tamizh.raja@oss.qualcomm.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
b5b8e29597
commit
469d5d5a3b
|
|
@ -2527,6 +2527,65 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_set_sta_4addr(struct ieee80211_local *local,
|
||||
struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_vif *vif = &sdata->vif;
|
||||
struct wiphy *wiphy = local->hw.wiphy;
|
||||
struct ieee80211_sub_if_data *master;
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
struct wireless_dev *wdev;
|
||||
unsigned long master_iter;
|
||||
int link_id;
|
||||
int err;
|
||||
|
||||
lockdep_assert_wiphy(local->hw.wiphy);
|
||||
|
||||
if (sdata->u.vlan.sta)
|
||||
return -EBUSY;
|
||||
|
||||
wdev = &sdata->wdev;
|
||||
master = container_of(sdata->bss,
|
||||
struct ieee80211_sub_if_data,
|
||||
u.ap);
|
||||
|
||||
if (sta->sta.valid_links) {
|
||||
u16 sta_links = sta->sta.valid_links;
|
||||
u16 new_links = master->vif.valid_links & sta_links;
|
||||
u16 orig_links = wdev->valid_links;
|
||||
|
||||
wdev->valid_links = new_links;
|
||||
|
||||
err = ieee80211_vif_set_links(sdata, new_links, 0);
|
||||
if (err) {
|
||||
wdev->valid_links = orig_links;
|
||||
return err;
|
||||
}
|
||||
|
||||
master_iter = master->vif.valid_links;
|
||||
|
||||
for_each_set_bit(link_id, &master_iter,
|
||||
IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
if (!(sta_links & BIT(link_id))) {
|
||||
eth_zero_addr(wdev->links[link_id].addr);
|
||||
} else {
|
||||
link_conf = wiphy_dereference(wiphy,
|
||||
vif->link_conf[link_id]);
|
||||
|
||||
ether_addr_copy(wdev->links[link_id].addr,
|
||||
link_conf->bssid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rcu_assign_pointer(sdata->u.vlan.sta, sta);
|
||||
__ieee80211_check_fast_rx_iface(sdata);
|
||||
drv_sta_set_4addr(local, sta->sdata, &sta->sta, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ieee80211_change_station(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev, const u8 *mac,
|
||||
struct station_parameters *params)
|
||||
|
|
@ -2589,12 +2648,10 @@ static int ieee80211_change_station(struct wiphy *wiphy,
|
|||
vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
|
||||
|
||||
if (params->vlan->ieee80211_ptr->use_4addr) {
|
||||
if (vlansdata->u.vlan.sta)
|
||||
return -EBUSY;
|
||||
err = ieee80211_set_sta_4addr(local, vlansdata, sta);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
|
||||
__ieee80211_check_fast_rx_iface(vlansdata);
|
||||
drv_sta_set_4addr(local, sta->sdata, &sta->sta, true);
|
||||
}
|
||||
|
||||
if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
|
||||
|
|
|
|||
|
|
@ -1321,6 +1321,10 @@ __ieee80211_link_copy_chanctx_to_vlans(struct ieee80211_link_data *link,
|
|||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
||||
struct ieee80211_bss_conf *vlan_conf;
|
||||
|
||||
if (vlan->vif.valid_links &&
|
||||
!(vlan->vif.valid_links & BIT(link_id)))
|
||||
continue;
|
||||
|
||||
vlan_conf = wiphy_dereference(local->hw.wiphy,
|
||||
vlan->vif.link_conf[link_id]);
|
||||
if (WARN_ON(!vlan_conf))
|
||||
|
|
@ -1564,6 +1568,10 @@ ieee80211_link_update_chanreq(struct ieee80211_link_data *link,
|
|||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
||||
struct ieee80211_bss_conf *vlan_conf;
|
||||
|
||||
if (vlan->vif.valid_links &&
|
||||
!(vlan->vif.valid_links & BIT(link_id)))
|
||||
continue;
|
||||
|
||||
vlan_conf = wiphy_dereference(sdata->local->hw.wiphy,
|
||||
vlan->vif.link_conf[link_id]);
|
||||
if (WARN_ON(!vlan_conf))
|
||||
|
|
|
|||
|
|
@ -14,27 +14,39 @@
|
|||
|
||||
static void ieee80211_update_apvlan_links(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
unsigned long rem = ~sdata->vif.valid_links &
|
||||
GENMASK(IEEE80211_MLD_MAX_NUM_LINKS - 1, 0);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
unsigned long add = sdata->vif.valid_links;
|
||||
struct wiphy *wiphy = local->hw.wiphy;
|
||||
struct ieee80211_sub_if_data *vlan;
|
||||
struct ieee80211_link_data *link;
|
||||
u16 ap_bss_links = sdata->vif.valid_links;
|
||||
u16 new_links, vlan_links;
|
||||
unsigned long add;
|
||||
struct sta_info *sta;
|
||||
|
||||
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
|
||||
int link_id;
|
||||
|
||||
/* No support for 4addr with MLO yet */
|
||||
if (vlan->wdev.use_4addr)
|
||||
return;
|
||||
if (vlan->wdev.use_4addr) {
|
||||
sta = wiphy_dereference(wiphy,
|
||||
vlan->u.vlan.sta);
|
||||
if (sta)
|
||||
add = add & sta->sta.valid_links;
|
||||
}
|
||||
|
||||
vlan_links = vlan->vif.valid_links;
|
||||
|
||||
new_links = ap_bss_links;
|
||||
|
||||
add = new_links & ~vlan_links;
|
||||
if (!add)
|
||||
if (add == vlan->vif.valid_links)
|
||||
continue;
|
||||
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
vlan->wdev.valid_links |= BIT(link_id);
|
||||
ether_addr_copy(vlan->wdev.links[link_id].addr,
|
||||
sdata->wdev.links[link_id].addr);
|
||||
}
|
||||
|
||||
for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
vlan->wdev.valid_links &= ~BIT(link_id);
|
||||
eth_zero_addr(vlan->wdev.links[link_id].addr);
|
||||
}
|
||||
|
||||
ieee80211_vif_set_links(vlan, add, 0);
|
||||
|
||||
for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
|
||||
|
|
@ -96,8 +108,13 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
ap_bss = container_of(sdata->bss,
|
||||
struct ieee80211_sub_if_data, u.ap);
|
||||
ap_bss_conf = sdata_dereference(ap_bss->vif.link_conf[link_id],
|
||||
ap_bss);
|
||||
|
||||
if (deflink)
|
||||
ap_bss_conf = &ap_bss->vif.bss_conf;
|
||||
else
|
||||
ap_bss_conf = sdata_dereference(ap_bss->vif.link_conf[link_id],
|
||||
ap_bss);
|
||||
|
||||
memcpy(link_conf, ap_bss_conf, sizeof(*link_conf));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user