nl80211: Refactor i802_bss to support multiple links

Refactor struct i802_bss to support multiple links as a
preparation to support MLD AP.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2023-02-16 01:08:15 +02:00 committed by Jouni Malinen
parent eb146ee804
commit 47269be36e
3 changed files with 71 additions and 35 deletions

View file

@ -275,7 +275,7 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
drv->associated = 0; drv->associated = 0;
os_memset(&drv->sta_mlo_info, 0, sizeof(drv->sta_mlo_info)); os_memset(&drv->sta_mlo_info, 0, sizeof(drv->sta_mlo_info));
os_memset(drv->bssid, 0, ETH_ALEN); os_memset(drv->bssid, 0, ETH_ALEN);
drv->first_bss->freq = 0; drv->first_bss->flink->freq = 0;
#ifdef CONFIG_DRIVER_NL80211_QCA #ifdef CONFIG_DRIVER_NL80211_QCA
os_free(drv->pending_roam_data); os_free(drv->pending_roam_data);
drv->pending_roam_data = NULL; drv->pending_roam_data = NULL;
@ -913,7 +913,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss)
dl_list_init(&w->drvs); dl_list_init(&w->drvs);
/* Beacon frames not supported in IEEE 802.11ad */ /* Beacon frames not supported in IEEE 802.11ad */
if (ieee80211_freq_to_chan(bss->freq, &channel) != if (ieee80211_freq_to_chan(bss->flink->freq, &channel) !=
HOSTAPD_MODE_IEEE80211AD) { HOSTAPD_MODE_IEEE80211AD) {
w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!w->nl_cb) { if (!w->nl_cb) {
@ -2232,6 +2232,7 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname,
{ {
struct wpa_driver_nl80211_data *drv; struct wpa_driver_nl80211_data *drv;
struct i802_bss *bss; struct i802_bss *bss;
unsigned int i;
if (global_priv == NULL) if (global_priv == NULL)
return NULL; return NULL;
@ -2310,6 +2311,17 @@ skip_wifi_status:
drv->in_interface_list = 1; drv->in_interface_list = 1;
} }
/*
* Set the default link to be the first one, and set its address to that
* of the interface.
*/
bss->flink = &bss->links[0];
bss->n_links = 1;
os_memcpy(bss->flink->addr, bss->addr, ETH_ALEN);
for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
bss->links[i].link_id = NL80211_DRV_LINK_ID_NA;
return bss; return bss;
failed: failed:
@ -2984,8 +2996,8 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss)
wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
drv->ifindex); drv->ifindex);
bss->beacon_set = 0; bss->flink->beacon_set = 0;
bss->freq = 0; bss->flink->freq = 0;
nl80211_put_wiphy_data_ap(bss); nl80211_put_wiphy_data_ap(bss);
msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
@ -4111,10 +4123,10 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) { if (drv->device_ap_sme && is_ap_interface(drv->nlmode)) {
if (freq == 0) { if (freq == 0) {
wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d", wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
bss->freq); bss->flink->freq);
freq = bss->freq; freq = bss->flink->freq;
} }
if ((int) freq == bss->freq) if ((int) freq == bss->flink->freq)
wait_time = 0; wait_time = 0;
goto send_frame_cmd; goto send_frame_cmd;
} }
@ -4176,14 +4188,14 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data,
} }
if (freq == 0) { if (freq == 0) {
wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u", wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u",
bss->freq); bss->flink->freq);
freq = bss->freq; freq = bss->flink->freq;
} }
if (drv->use_monitor && is_ap_interface(drv->nlmode)) { if (drv->use_monitor && is_ap_interface(drv->nlmode)) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor", "nl80211: send_frame(freq=%u bss->freq=%u) -> send_monitor",
freq, bss->freq); freq, bss->flink->freq);
return nl80211_send_monitor(drv, data, data_len, encrypt, return nl80211_send_monitor(drv, data, data_len, encrypt,
noack); noack);
} }
@ -4696,7 +4708,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
struct wpa_driver_mesh_bss_params mesh_params; struct wpa_driver_mesh_bss_params mesh_params;
#endif /* CONFIG_MESH */ #endif /* CONFIG_MESH */
beacon_set = params->reenable ? 0 : bss->beacon_set; beacon_set = params->reenable ? 0 : bss->flink->beacon_set;
wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)", wpa_printf(MSG_DEBUG, "nl80211: Set beacon (beacon_set=%d)",
beacon_set); beacon_set);
@ -4999,17 +5011,17 @@ static int wpa_driver_nl80211_set_ap(void *priv,
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
ret, strerror(-ret)); ret, strerror(-ret));
} else { } else {
bss->beacon_set = 1; bss->flink->beacon_set = 1;
nl80211_set_bss(bss, params->cts_protect, params->preamble, nl80211_set_bss(bss, params->cts_protect, params->preamble,
params->short_slot_time, params->ht_opmode, params->short_slot_time, params->ht_opmode,
params->isolate, params->basic_rates); params->isolate, params->basic_rates);
nl80211_set_multicast_to_unicast(bss, nl80211_set_multicast_to_unicast(bss,
params->multicast_to_unicast); params->multicast_to_unicast);
if (beacon_set && params->freq && if (beacon_set && params->freq &&
params->freq->bandwidth != bss->bandwidth) { params->freq->bandwidth != bss->flink->bandwidth) {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: Update BSS %s bandwidth: %d -> %d", "nl80211: Update BSS %s bandwidth: %d -> %d",
bss->ifname, bss->bandwidth, bss->ifname, bss->flink->bandwidth,
params->freq->bandwidth); params->freq->bandwidth);
ret = nl80211_set_channel(bss, params->freq, 1); ret = nl80211_set_channel(bss, params->freq, 1);
if (ret) { if (ret) {
@ -5019,7 +5031,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
} else { } else {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: Frequency set succeeded for ht2040 coex"); "nl80211: Frequency set succeeded for ht2040 coex");
bss->bandwidth = params->freq->bandwidth; bss->flink->bandwidth = params->freq->bandwidth;
} }
} else if (!beacon_set && params->freq) { } else if (!beacon_set && params->freq) {
/* /*
@ -5027,7 +5039,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
* mode only at the point when beaconing is started, so * mode only at the point when beaconing is started, so
* set the initial value here. * set the initial value here.
*/ */
bss->bandwidth = params->freq->bandwidth; bss->flink->bandwidth = params->freq->bandwidth;
} }
} }
@ -5177,7 +5189,7 @@ static int nl80211_set_channel(struct i802_bss *bss,
ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
if (ret == 0) { if (ret == 0) {
bss->freq = freq->freq; bss->flink->freq = freq->freq;
return 0; return 0;
} }
wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): " wpa_printf(MSG_DEBUG, "nl80211: Failed to set channel (freq=%d): "
@ -5805,7 +5817,7 @@ static void nl80211_teardown_ap(struct i802_bss *bss)
nl80211_mgmt_unsubscribe(bss, "AP teardown"); nl80211_mgmt_unsubscribe(bss, "AP teardown");
nl80211_put_wiphy_data_ap(bss); nl80211_put_wiphy_data_ap(bss);
bss->beacon_set = 0; bss->flink->beacon_set = 0;
} }
@ -7791,7 +7803,7 @@ static int i802_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
struct ieee80211_mgmt mgmt; struct ieee80211_mgmt mgmt;
u8 channel; u8 channel;
if (ieee80211_freq_to_chan(bss->freq, &channel) == if (ieee80211_freq_to_chan(bss->flink->freq, &channel) ==
HOSTAPD_MODE_IEEE80211AD) { HOSTAPD_MODE_IEEE80211AD) {
/* Deauthentication is not used in DMG/IEEE 802.11ad; /* Deauthentication is not used in DMG/IEEE 802.11ad;
* disassociate the STA instead. */ * disassociate the STA instead. */
@ -8412,12 +8424,18 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
if (type == WPA_IF_AP_BSS && setup_ap) { if (type == WPA_IF_AP_BSS && setup_ap) {
struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss)); struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
unsigned int i;
if (new_bss == NULL) { if (new_bss == NULL) {
if (added) if (added)
nl80211_remove_iface(drv, ifidx); nl80211_remove_iface(drv, ifidx);
return -1; return -1;
} }
/* Initialize here before any failure path */
for (i = 0; i < MAX_NUM_MLD_LINKS; i++)
new_bss->links[i].link_id = NL80211_DRV_LINK_ID_NA;
if (bridge && if (bridge &&
i802_check_bridge(drv, new_bss, bridge, ifname) < 0) { i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
wpa_printf(MSG_ERROR, "nl80211: Failed to add the new " wpa_printf(MSG_ERROR, "nl80211: Failed to add the new "
@ -8441,7 +8459,11 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
new_bss->ifindex = ifidx; new_bss->ifindex = ifidx;
new_bss->drv = drv; new_bss->drv = drv;
new_bss->next = drv->first_bss->next; new_bss->next = drv->first_bss->next;
new_bss->freq = drv->first_bss->freq; new_bss->flink = &new_bss->links[0];
new_bss->n_links = 1;
os_memcpy(new_bss->flink->addr, new_bss->addr, ETH_ALEN);
new_bss->flink->freq = drv->first_bss->flink->freq;
new_bss->ctx = bss_ctx; new_bss->ctx = bss_ctx;
new_bss->added_if = added; new_bss->added_if = added;
drv->first_bss->next = new_bss; drv->first_bss->next = new_bss;
@ -8648,8 +8670,8 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
int offchanok = 1; int offchanok = 1;
if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq && if (is_ap_interface(drv->nlmode) && (int) freq == bss->flink->freq &&
bss->beacon_set) bss->flink->beacon_set)
offchanok = 0; offchanok = 0;
wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, "
@ -8685,7 +8707,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
modes = nl80211_get_hw_feature_data(bss, &num_modes, modes = nl80211_get_hw_feature_data(bss, &num_modes,
&flags, &dfs_domain); &flags, &dfs_domain);
if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && if (dfs_domain != HOSTAPD_DFS_REGION_ETSI &&
ieee80211_is_dfs(bss->freq, modes, num_modes)) ieee80211_is_dfs(bss->flink->freq, modes, num_modes))
offchanok = 0; offchanok = 0;
if (modes) { if (modes) {
for (i = 0; i < num_modes; i++) { for (i = 0; i < num_modes; i++) {
@ -8699,7 +8721,7 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss,
if (is_ap_interface(drv->nlmode) && if (is_ap_interface(drv->nlmode) &&
(!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) ||
(int) freq == bss->freq || drv->device_ap_sme || (int) freq == bss->flink->freq || drv->device_ap_sme ||
!drv->use_monitor)) !drv->use_monitor))
ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len, ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
0, freq, no_cck, offchanok, 0, freq, no_cck, offchanok,
@ -10256,8 +10278,8 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
bss->ifname, bss->ifname,
bss->brname, bss->brname,
MAC2STR(bss->addr), MAC2STR(bss->addr),
bss->freq, bss->flink->freq,
bss->beacon_set ? "beacon_set=1\n" : "", bss->flink->beacon_set ? "beacon_set=1\n" : "",
bss->added_if_into_bridge ? bss->added_if_into_bridge ?
"added_if_into_bridge=1\n" : "", "added_if_into_bridge=1\n" : "",
bss->already_in_bridge ? "already_in_bridge=1\n" : "", bss->already_in_bridge ? "already_in_bridge=1\n" : "",
@ -11318,7 +11340,7 @@ static int nl80211_join_mesh(struct i802_bss *bss,
goto fail; goto fail;
} }
ret = 0; ret = 0;
drv->assoc_freq = bss->freq = params->freq.freq; drv->assoc_freq = bss->flink->freq = params->freq.freq;
wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully"); wpa_printf(MSG_DEBUG, "nl80211: mesh join request send successfully");
fail: fail:
@ -11374,7 +11396,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
} else { } else {
wpa_printf(MSG_DEBUG, wpa_printf(MSG_DEBUG,
"nl80211: mesh leave request send successfully"); "nl80211: mesh leave request send successfully");
drv->first_bss->freq = 0; drv->first_bss->flink->freq = 0;
} }
if (drv->start_mode_sta && if (drv->start_mode_sta &&

View file

@ -49,15 +49,31 @@ struct nl80211_wiphy_data {
int wiphy_idx; int wiphy_idx;
}; };
#define NL80211_DRV_LINK_ID_NA (-1)
struct i802_link {
unsigned int beacon_set:1;
s8 link_id;
int freq;
int bandwidth;
u8 addr[ETH_ALEN];
void *ctx;
};
struct i802_bss { struct i802_bss {
struct wpa_driver_nl80211_data *drv; struct wpa_driver_nl80211_data *drv;
struct i802_bss *next; struct i802_bss *next;
size_t n_links;
struct i802_link links[MAX_NUM_MLD_LINKS];
struct i802_link *flink;
int ifindex; int ifindex;
int br_ifindex; int br_ifindex;
u64 wdev_id; u64 wdev_id;
char ifname[IFNAMSIZ + 1]; char ifname[IFNAMSIZ + 1];
char brname[IFNAMSIZ]; char brname[IFNAMSIZ];
unsigned int beacon_set:1;
unsigned int added_if_into_bridge:1; unsigned int added_if_into_bridge:1;
unsigned int already_in_bridge:1; unsigned int already_in_bridge:1;
unsigned int added_bridge:1; unsigned int added_bridge:1;
@ -70,8 +86,6 @@ struct i802_bss {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
u8 prev_addr[ETH_ALEN]; u8 prev_addr[ETH_ALEN];
int freq;
int bandwidth;
int if_dynamic; int if_dynamic;
void *ctx; void *ctx;

View file

@ -327,7 +327,7 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
} }
event.assoc_info.freq = drv->assoc_freq; event.assoc_info.freq = drv->assoc_freq;
drv->first_bss->freq = drv->assoc_freq; drv->first_bss->flink->freq = drv->assoc_freq;
nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params); nl80211_parse_wmm_params(wmm, &event.assoc_info.wmm_params);
@ -852,7 +852,7 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv,
} }
event.assoc_info.freq = nl80211_get_assoc_freq(drv); event.assoc_info.freq = nl80211_get_assoc_freq(drv);
drv->first_bss->freq = drv->assoc_freq; drv->first_bss->flink->freq = drv->assoc_freq;
if ((!ssid || ssid[1] == 0 || ssid[1] > 32) && if ((!ssid || ssid[1] == 0 || ssid[1] > 32) &&
(ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) { (ssid_len = nl80211_get_assoc_ssid(drv, drv->ssid)) > 0) {
@ -1057,7 +1057,7 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
data.ch_switch.cf2 = nla_get_u32(cf2); data.ch_switch.cf2 = nla_get_u32(cf2);
if (finished) if (finished)
bss->freq = data.ch_switch.freq; bss->flink->freq = data.ch_switch.freq;
if (link) { if (link) {
u8 link_id = nla_get_u8(link); u8 link_id = nla_get_u8(link);
@ -1569,7 +1569,7 @@ static void mlme_event_join_ibss(struct wpa_driver_nl80211_data *drv,
if (freq) { if (freq) {
wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz", wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
freq); freq);
drv->first_bss->freq = freq; drv->first_bss->flink->freq = freq;
} }
os_memset(&event, 0, sizeof(event)); os_memset(&event, 0, sizeof(event));