]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
nl80211: Refactor i802_bss to support multiple links
authorIlan Peer <ilan.peer@intel.com>
Wed, 15 Feb 2023 23:08:15 +0000 (01:08 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 7 Mar 2023 19:06:25 +0000 (21:06 +0200)
Refactor struct i802_bss to support multiple links as a
preparation to support MLD AP.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
src/drivers/driver_nl80211.c
src/drivers/driver_nl80211.h
src/drivers/driver_nl80211_event.c

index 75825bd94adde3358994ea1270532069c6c8dd9e..4786b29a5b58afabacb6d31f4dfae88792ff539a 100644 (file)
@@ -275,7 +275,7 @@ void nl80211_mark_disconnected(struct wpa_driver_nl80211_data *drv)
        drv->associated = 0;
        os_memset(&drv->sta_mlo_info, 0, sizeof(drv->sta_mlo_info));
        os_memset(drv->bssid, 0, ETH_ALEN);
-       drv->first_bss->freq = 0;
+       drv->first_bss->flink->freq = 0;
 #ifdef CONFIG_DRIVER_NL80211_QCA
        os_free(drv->pending_roam_data);
        drv->pending_roam_data = NULL;
@@ -913,7 +913,7 @@ nl80211_get_wiphy_data_ap(struct i802_bss *bss)
        dl_list_init(&w->drvs);
 
        /* 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) {
                w->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
                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 i802_bss *bss;
+       unsigned int i;
 
        if (global_priv == NULL)
                return NULL;
@@ -2310,6 +2311,17 @@ skip_wifi_status:
                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;
 
 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)",
                   drv->ifindex);
-       bss->beacon_set = 0;
-       bss->freq = 0;
+       bss->flink->beacon_set = 0;
+       bss->flink->freq = 0;
        nl80211_put_wiphy_data_ap(bss);
        msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
        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 (freq == 0) {
                        wpa_printf(MSG_DEBUG, "nl80211: Use bss->freq=%d",
-                                  bss->freq);
-                       freq = bss->freq;
+                                  bss->flink->freq);
+                       freq = bss->flink->freq;
                }
-               if ((int) freq == bss->freq)
+               if ((int) freq == bss->flink->freq)
                        wait_time = 0;
                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) {
                wpa_printf(MSG_DEBUG, "nl80211: send_mlme - Use bss->freq=%u",
-                          bss->freq);
-               freq = bss->freq;
+                          bss->flink->freq);
+               freq = bss->flink->freq;
        }
 
        if (drv->use_monitor && is_ap_interface(drv->nlmode)) {
                wpa_printf(MSG_DEBUG,
                           "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,
                                            noack);
        }
@@ -4696,7 +4708,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
        struct wpa_driver_mesh_bss_params mesh_params;
 #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)",
                   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)",
                           ret, strerror(-ret));
        } else {
-               bss->beacon_set = 1;
+               bss->flink->beacon_set = 1;
                nl80211_set_bss(bss, params->cts_protect, params->preamble,
                                params->short_slot_time, params->ht_opmode,
                                params->isolate, params->basic_rates);
                nl80211_set_multicast_to_unicast(bss,
                                                 params->multicast_to_unicast);
                if (beacon_set && params->freq &&
-                   params->freq->bandwidth != bss->bandwidth) {
+                   params->freq->bandwidth != bss->flink->bandwidth) {
                        wpa_printf(MSG_DEBUG,
                                   "nl80211: Update BSS %s bandwidth: %d -> %d",
-                                  bss->ifname, bss->bandwidth,
+                                  bss->ifname, bss->flink->bandwidth,
                                   params->freq->bandwidth);
                        ret = nl80211_set_channel(bss, params->freq, 1);
                        if (ret) {
@@ -5019,7 +5031,7 @@ static int wpa_driver_nl80211_set_ap(void *priv,
                        } else {
                                wpa_printf(MSG_DEBUG,
                                           "nl80211: Frequency set succeeded for ht2040 coex");
-                               bss->bandwidth = params->freq->bandwidth;
+                               bss->flink->bandwidth = params->freq->bandwidth;
                        }
                } 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
                         * 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);
        if (ret == 0) {
-               bss->freq = freq->freq;
+               bss->flink->freq = freq->freq;
                return 0;
        }
        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_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;
        u8 channel;
 
-       if (ieee80211_freq_to_chan(bss->freq, &channel) ==
+       if (ieee80211_freq_to_chan(bss->flink->freq, &channel) ==
            HOSTAPD_MODE_IEEE80211AD) {
                /* Deauthentication is not used in DMG/IEEE 802.11ad;
                 * 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) {
                struct i802_bss *new_bss = os_zalloc(sizeof(*new_bss));
+               unsigned int i;
+
                if (new_bss == NULL) {
                        if (added)
                                nl80211_remove_iface(drv, ifidx);
                        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 &&
                    i802_check_bridge(drv, new_bss, bridge, ifname) < 0) {
                        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->drv = drv;
                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->added_if = added;
                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;
        int offchanok = 1;
 
-       if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq &&
-           bss->beacon_set)
+       if (is_ap_interface(drv->nlmode) && (int) freq == bss->flink->freq &&
+           bss->flink->beacon_set)
                offchanok = 0;
 
        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,
                                                    &flags, &dfs_domain);
                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;
                if (modes) {
                        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) &&
            (!(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))
                ret = wpa_driver_nl80211_send_mlme(bss, buf, 24 + data_len,
                                                   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->brname,
                          MAC2STR(bss->addr),
-                         bss->freq,
-                         bss->beacon_set ? "beacon_set=1\n" : "",
+                         bss->flink->freq,
+                         bss->flink->beacon_set ? "beacon_set=1\n" : "",
                          bss->added_if_into_bridge ?
                          "added_if_into_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;
        }
        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");
 
 fail:
@@ -11374,7 +11396,7 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
        } else {
                wpa_printf(MSG_DEBUG,
                           "nl80211: mesh leave request send successfully");
-               drv->first_bss->freq = 0;
+               drv->first_bss->flink->freq = 0;
        }
 
        if (drv->start_mode_sta &&
index a6cb14c5ac883e0b7070835634993122dabdf195..2c4faa373c9bd955b1078cff17673818a55e129a 100644 (file)
@@ -49,15 +49,31 @@ struct nl80211_wiphy_data {
        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 wpa_driver_nl80211_data *drv;
        struct i802_bss *next;
+
+       size_t n_links;
+       struct i802_link links[MAX_NUM_MLD_LINKS];
+       struct i802_link *flink;
+
        int ifindex;
        int br_ifindex;
        u64 wdev_id;
        char ifname[IFNAMSIZ + 1];
        char brname[IFNAMSIZ];
-       unsigned int beacon_set:1;
        unsigned int added_if_into_bridge:1;
        unsigned int already_in_bridge:1;
        unsigned int added_bridge:1;
@@ -70,8 +86,6 @@ struct i802_bss {
        u8 addr[ETH_ALEN];
        u8 prev_addr[ETH_ALEN];
 
-       int freq;
-       int bandwidth;
        int if_dynamic;
 
        void *ctx;
index cf31552c02f8d99c748370c98e33380f3d926754..a0015f28f58afb8bfaf7e38bea55e1eff01f144a 100644 (file)
@@ -327,7 +327,7 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv,
        }
 
        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);
 
@@ -852,7 +852,7 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *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) &&
            (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);
 
        if (finished)
-               bss->freq = data.ch_switch.freq;
+               bss->flink->freq = data.ch_switch.freq;
 
        if (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) {
                wpa_printf(MSG_DEBUG, "nl80211: IBSS on frequency %u MHz",
                           freq);
-               drv->first_bss->freq = freq;
+               drv->first_bss->flink->freq = freq;
        }
 
        os_memset(&event, 0, sizeof(event));