wifi: mac80211_hwsim: send a beacon per link
authorShaul Triebitz <shaul.triebitz@intel.com>
Mon, 6 Jun 2022 17:03:17 +0000 (20:03 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 20 Jun 2022 10:57:08 +0000 (12:57 +0200)
Add to hwsim a link_data structure.
For now, move the beacon interval and beacon timer to
the link_data structure (making them per link).
Set a beacon timer for each link and transmit a per
link beacon (pass the link_id to ieee80211_beacon_get).

Signed-off-by: Shaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/mac80211_hwsim.c

index 44174a4..513e929 100644 (file)
@@ -623,6 +623,12 @@ static struct platform_driver mac80211_hwsim_driver = {
        },
 };
 
+struct mac80211_hwsim_link_data {
+       u32 link_id;
+       u64 beacon_int  /* beacon interval in us */;
+       struct hrtimer beacon_timer;
+};
+
 struct mac80211_hwsim_data {
        struct list_head list;
        struct rhash_head rht;
@@ -668,11 +674,9 @@ struct mac80211_hwsim_data {
 
        struct ieee80211_channel *channel;
        enum nl80211_chan_width bw;
-       u64 beacon_int  /* beacon interval in us */;
        unsigned int rx_filter;
        bool started, idle, scanning;
        struct mutex mutex;
-       struct hrtimer beacon_timer;
        enum ps_mode {
                PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
        } ps;
@@ -709,6 +713,8 @@ struct mac80211_hwsim_data {
 
        /* RSSI in rx status of the receiver */
        int rx_rssi;
+
+       struct mac80211_hwsim_link_data link_data[IEEE80211_MLD_MAX_NUM_LINKS];
 };
 
 static const struct rhashtable_params hwsim_rht_params = {
@@ -1071,7 +1077,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
 {
        struct mac80211_hwsim_data *data = hw->priv;
        u64 now = mac80211_hwsim_get_tsf(hw, vif);
-       u32 bcn_int = data->beacon_int;
+       /* MLD not supported here */
+       u32 bcn_int = data->link_data[0].beacon_int;
        u64 delta = abs(tsf - now);
 
        /* adjust after beaconing with new timestamp at old TBTT */
@@ -1798,9 +1805,12 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw)
 static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
 {
        struct mac80211_hwsim_data *data = hw->priv;
+       int i;
 
        data->started = false;
-       hrtimer_cancel(&data->beacon_timer);
+
+       for (i = 0; i < ARRAY_SIZE(data->link_data); i++)
+               hrtimer_cancel(&data->link_data[i].beacon_timer);
 
        while (!skb_queue_empty(&data->pending))
                ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
@@ -1891,7 +1901,12 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
                                     struct ieee80211_vif *vif)
 {
-       struct mac80211_hwsim_data *data = arg;
+       struct mac80211_hwsim_link_data *link_data = arg;
+       u32 link_id = link_data->link_id;
+       struct ieee80211_bss_conf *link_conf = vif->link_conf[link_id];
+       struct mac80211_hwsim_data *data =
+               container_of(link_data, struct mac80211_hwsim_data,
+                            link_data[link_id]);
        struct ieee80211_hw *hw = data->hw;
        struct ieee80211_tx_info *info;
        struct ieee80211_rate *txrate;
@@ -1908,7 +1923,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
            vif->type != NL80211_IFTYPE_OCB)
                return;
 
-       skb = ieee80211_beacon_get(hw, vif, 0);
+       skb = ieee80211_beacon_get(hw, vif, link_data->link_id);
        if (skb == NULL)
                return;
        info = IEEE80211_SKB_CB(skb);
@@ -1939,38 +1954,41 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
        }
 
        mac80211_hwsim_tx_frame(hw, skb,
-                               rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan);
+                       rcu_dereference(link_conf->chanctx_conf)->def.chan);
 
        while ((skb = ieee80211_get_buffered_bc(hw, vif)) != NULL) {
                mac80211_hwsim_tx_frame(hw, skb,
-                               rcu_dereference(vif->bss_conf.chanctx_conf)->def.chan);
+                       rcu_dereference(link_conf->chanctx_conf)->def.chan);
        }
 
-       if (vif->bss_conf.csa_active && ieee80211_beacon_cntdwn_is_complete(vif))
+       if (link_conf->csa_active && ieee80211_beacon_cntdwn_is_complete(vif))
                ieee80211_csa_finish(vif);
 }
 
 static enum hrtimer_restart
 mac80211_hwsim_beacon(struct hrtimer *timer)
 {
+       struct mac80211_hwsim_link_data *link_data =
+               container_of(timer, struct mac80211_hwsim_link_data, beacon_timer);
        struct mac80211_hwsim_data *data =
-               container_of(timer, struct mac80211_hwsim_data, beacon_timer);
+               container_of(link_data, struct mac80211_hwsim_data,
+                            link_data[link_data->link_id]);
        struct ieee80211_hw *hw = data->hw;
-       u64 bcn_int = data->beacon_int;
+       u64 bcn_int = link_data->beacon_int;
 
        if (!data->started)
                return HRTIMER_NORESTART;
 
        ieee80211_iterate_active_interfaces_atomic(
                hw, IEEE80211_IFACE_ITER_NORMAL,
-               mac80211_hwsim_beacon_tx, data);
+               mac80211_hwsim_beacon_tx, link_data);
 
        /* beacon at new TBTT + beacon interval */
        if (data->bcn_delta) {
                bcn_int -= data->bcn_delta;
                data->bcn_delta = 0;
        }
-       hrtimer_forward_now(&data->beacon_timer,
+       hrtimer_forward_now(&link_data->beacon_timer,
                            ns_to_ktime(bcn_int * NSEC_PER_USEC));
        return HRTIMER_RESTART;
 }
@@ -2054,16 +2072,21 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
        }
        mutex_unlock(&data->mutex);
 
-       if (!data->started || !data->beacon_int)
-               hrtimer_cancel(&data->beacon_timer);
-       else if (!hrtimer_is_queued(&data->beacon_timer)) {
-               u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
-               u32 bcn_int = data->beacon_int;
-               u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
+       for (idx = 0; idx < ARRAY_SIZE(data->link_data); idx++) {
+               struct mac80211_hwsim_link_data *link_data =
+                       &data->link_data[idx];
+
+               if (!data->started || !link_data->beacon_int) {
+                       hrtimer_cancel(&link_data->beacon_timer);
+               } else if (!hrtimer_is_queued(&link_data->beacon_timer)) {
+                       u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
+                       u32 bcn_int = link_data->beacon_int;
+                       u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
 
-               hrtimer_start(&data->beacon_timer,
-                             ns_to_ktime(until_tbtt * NSEC_PER_USEC),
-                             HRTIMER_MODE_REL_SOFT);
+                       hrtimer_start(&link_data->beacon_timer,
+                                     ns_to_ktime(until_tbtt * NSEC_PER_USEC),
+                                     HRTIMER_MODE_REL_SOFT);
+               }
        }
 
        return 0;
@@ -2124,6 +2147,7 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
        struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
        struct mac80211_hwsim_data *data = hw->priv;
        struct ieee80211_bss_conf *info = vif->link_conf[link_id];
+       struct mac80211_hwsim_link_data *link_data = &data->link_data[link_id];
 
        hwsim_check_magic(vif);
 
@@ -2141,16 +2165,16 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
                          info->enable_beacon, info->beacon_int);
                vp->bcn_en = info->enable_beacon;
                if (data->started &&
-                   !hrtimer_is_queued(&data->beacon_timer) &&
+                   !hrtimer_is_queued(&link_data->beacon_timer) &&
                    info->enable_beacon) {
                        u64 tsf, until_tbtt;
                        u32 bcn_int;
-                       data->beacon_int = info->beacon_int * 1024;
+                       link_data->beacon_int = info->beacon_int * 1024;
                        tsf = mac80211_hwsim_get_tsf(hw, vif);
-                       bcn_int = data->beacon_int;
+                       bcn_int = link_data->beacon_int;
                        until_tbtt = bcn_int - do_div(tsf, bcn_int);
 
-                       hrtimer_start(&data->beacon_timer,
+                       hrtimer_start(&link_data->beacon_timer,
                                      ns_to_ktime(until_tbtt * NSEC_PER_USEC),
                                      HRTIMER_MODE_REL_SOFT);
                } else if (!info->enable_beacon) {
@@ -2161,8 +2185,8 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
                        wiphy_dbg(hw->wiphy, "  beaconing vifs remaining: %u",
                                  count);
                        if (count == 0) {
-                               hrtimer_cancel(&data->beacon_timer);
-                               data->beacon_int = 0;
+                               hrtimer_cancel(&link_data->beacon_timer);
+                               link_data->beacon_int = 0;
                        }
                }
        }
@@ -3875,9 +3899,13 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
 
        wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
 
-       hrtimer_init(&data->beacon_timer, CLOCK_MONOTONIC,
-                    HRTIMER_MODE_ABS_SOFT);
-       data->beacon_timer.function = mac80211_hwsim_beacon;
+       for (i = 0; i < ARRAY_SIZE(data->link_data); i++) {
+               hrtimer_init(&data->link_data[i].beacon_timer, CLOCK_MONOTONIC,
+                            HRTIMER_MODE_ABS_SOFT);
+               data->link_data[i].beacon_timer.function =
+                       mac80211_hwsim_beacon;
+               data->link_data[i].link_id = i;
+       }
 
        err = ieee80211_register_hw(hw);
        if (err < 0) {