From e3605e8093074a679e1a790ec7eda69a5b057fc2 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 22 May 2023 22:33:34 +0300 Subject: [PATCH] driver: Allow to provide a link ID when setting a channel This includes: - Modifications of the driver API, to include the link ID as part of 'struct hostapd_freq_params'. - Modifications to nl80211 driver. - Modifications for the driver wrappers. Signed-off-by: Ilan Peer Signed-off-by: Andrei Otcheretianski --- src/ap/ap_drv_ops.c | 11 +++++++ src/drivers/driver.h | 5 ++++ src/drivers/driver_nl80211.c | 56 +++++++++++++++++++++++++++++++++++- wpa_supplicant/driver_i.h | 7 +++++ 4 files changed, 78 insertions(+), 1 deletion(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 46c989a85..a67a6a296 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -584,6 +584,17 @@ int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, return 0; if (hapd->driver->set_freq == NULL) return 0; + + data.link_id = -1; + +#ifdef CONFIG_IEEE80211BE + if (hapd->conf->mld_ap) { + data.link_id = hapd->mld_link_id; + wpa_printf(MSG_DEBUG, + "hostapd_set_freq: link_id=%d", data.link_id); + } +#endif /* CONFIG_IEEE80211BE */ + return hapd->driver->set_freq(hapd->drv_priv, &data); } diff --git a/src/drivers/driver.h b/src/drivers/driver.h index b4c306e5f..6ee1932c7 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -841,6 +841,11 @@ struct hostapd_freq_params { * eht_enabled - Whether EHT is enabled */ bool eht_enabled; + + /** + * link_id: If >=0 indicates the link of the AP MLD to configure + */ + int link_id; }; /** diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index dfc192f61..2df140cb1 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4120,6 +4120,29 @@ int wpa_driver_nl80211_authenticate_retry(struct wpa_driver_nl80211_data *drv) } +static struct i802_link * nl80211_get_link(struct i802_bss *bss, s8 link_id) +{ + unsigned int i; + + for (i = 0; i < bss->n_links; i++) { + if (bss->links[i].link_id != link_id) + continue; + + return &bss->links[i]; + } + + return bss->flink; +} + + +static void nl80211_link_set_freq(struct i802_bss *bss, s8 link_id, int freq) +{ + struct i802_link *link = nl80211_get_link(bss, link_id); + + link->freq = freq; +} + + static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, size_t data_len, int noack, unsigned int freq, int no_cck, @@ -5292,6 +5315,27 @@ static int nl80211_put_freq_params(struct nl_msg *msg, } +static bool nl80211_link_valid(struct i802_bss *bss, s8 link_id) +{ + unsigned int i; + + if (link_id < 0) + return false; + + for (i = 0; i < bss->n_links; i++) { + wpa_printf(MSG_DEBUG, "nl80211: %s - i=%u, link_id=%u", + __func__, i, bss->links[i].link_id); + if (bss->links[i].link_id == NL80211_DRV_LINK_ID_NA) + continue; + + if (bss->links[i].link_id == link_id) + return true; + } + + return false; +} + + static int nl80211_set_channel(struct i802_bss *bss, struct hostapd_freq_params *freq, int set_chan) { @@ -5312,9 +5356,19 @@ static int nl80211_set_channel(struct i802_bss *bss, return -1; } + if (nl80211_link_valid(bss, freq->link_id)) { + wpa_printf(MSG_DEBUG, "nl80211: Set link_id=%u for freq", + freq->link_id); + + if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, freq->link_id)) { + nlmsg_free(msg); + return -ENOBUFS; + } + } + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) { - bss->flink->freq = freq->freq; + nl80211_link_set_freq(bss, freq->link_id, freq->freq); return 0; } wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d707cf556..d5ec22cee 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -60,6 +60,9 @@ static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s, struct wpa_driver_associate_params *params) { if (wpa_s->driver->associate) { + if (params) + params->freq.link_id = -1; + return wpa_s->driver->associate(wpa_s->drv_priv, params); } return -1; @@ -1098,6 +1101,10 @@ static inline int wpa_drv_update_connect_params( { if (!wpa_s->driver->update_connect_params) return -1; + + if (params) + params->freq.link_id = -1; + return wpa_s->driver->update_connect_params(wpa_s->drv_priv, params, mask); }