Commit e57f8a48 authored by Shaul Triebitz's avatar Shaul Triebitz Committed by Johannes Berg

wifi: mac80211_hwsim: send a beacon per link

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: default avatarShaul Triebitz <shaul.triebitz@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 630c7e46
...@@ -623,6 +623,12 @@ static struct platform_driver mac80211_hwsim_driver = { ...@@ -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 mac80211_hwsim_data {
struct list_head list; struct list_head list;
struct rhash_head rht; struct rhash_head rht;
...@@ -668,11 +674,9 @@ struct mac80211_hwsim_data { ...@@ -668,11 +674,9 @@ struct mac80211_hwsim_data {
struct ieee80211_channel *channel; struct ieee80211_channel *channel;
enum nl80211_chan_width bw; enum nl80211_chan_width bw;
u64 beacon_int /* beacon interval in us */;
unsigned int rx_filter; unsigned int rx_filter;
bool started, idle, scanning; bool started, idle, scanning;
struct mutex mutex; struct mutex mutex;
struct hrtimer beacon_timer;
enum ps_mode { enum ps_mode {
PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
} ps; } ps;
...@@ -709,6 +713,8 @@ struct mac80211_hwsim_data { ...@@ -709,6 +713,8 @@ struct mac80211_hwsim_data {
/* RSSI in rx status of the receiver */ /* RSSI in rx status of the receiver */
int rx_rssi; int rx_rssi;
struct mac80211_hwsim_link_data link_data[IEEE80211_MLD_MAX_NUM_LINKS];
}; };
static const struct rhashtable_params hwsim_rht_params = { static const struct rhashtable_params hwsim_rht_params = {
...@@ -1071,7 +1077,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw, ...@@ -1071,7 +1077,8 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
{ {
struct mac80211_hwsim_data *data = hw->priv; struct mac80211_hwsim_data *data = hw->priv;
u64 now = mac80211_hwsim_get_tsf(hw, vif); 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); u64 delta = abs(tsf - now);
/* adjust after beaconing with new timestamp at old TBTT */ /* adjust after beaconing with new timestamp at old TBTT */
...@@ -1798,9 +1805,12 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw) ...@@ -1798,9 +1805,12 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw)
static void mac80211_hwsim_stop(struct ieee80211_hw *hw) static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
{ {
struct mac80211_hwsim_data *data = hw->priv; struct mac80211_hwsim_data *data = hw->priv;
int i;
data->started = false; 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)) while (!skb_queue_empty(&data->pending))
ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
...@@ -1891,7 +1901,12 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, ...@@ -1891,7 +1901,12 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
struct ieee80211_vif *vif) 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_hw *hw = data->hw;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ieee80211_rate *txrate; struct ieee80211_rate *txrate;
...@@ -1908,7 +1923,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, ...@@ -1908,7 +1923,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
vif->type != NL80211_IFTYPE_OCB) vif->type != NL80211_IFTYPE_OCB)
return; return;
skb = ieee80211_beacon_get(hw, vif, 0); skb = ieee80211_beacon_get(hw, vif, link_data->link_id);
if (skb == NULL) if (skb == NULL)
return; return;
info = IEEE80211_SKB_CB(skb); info = IEEE80211_SKB_CB(skb);
...@@ -1939,38 +1954,41 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, ...@@ -1939,38 +1954,41 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
} }
mac80211_hwsim_tx_frame(hw, skb, 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) { while ((skb = ieee80211_get_buffered_bc(hw, vif)) != NULL) {
mac80211_hwsim_tx_frame(hw, skb, 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); ieee80211_csa_finish(vif);
} }
static enum hrtimer_restart static enum hrtimer_restart
mac80211_hwsim_beacon(struct hrtimer *timer) 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 = 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; struct ieee80211_hw *hw = data->hw;
u64 bcn_int = data->beacon_int; u64 bcn_int = link_data->beacon_int;
if (!data->started) if (!data->started)
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
ieee80211_iterate_active_interfaces_atomic( ieee80211_iterate_active_interfaces_atomic(
hw, IEEE80211_IFACE_ITER_NORMAL, hw, IEEE80211_IFACE_ITER_NORMAL,
mac80211_hwsim_beacon_tx, data); mac80211_hwsim_beacon_tx, link_data);
/* beacon at new TBTT + beacon interval */ /* beacon at new TBTT + beacon interval */
if (data->bcn_delta) { if (data->bcn_delta) {
bcn_int -= data->bcn_delta; bcn_int -= data->bcn_delta;
data->bcn_delta = 0; 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)); ns_to_ktime(bcn_int * NSEC_PER_USEC));
return HRTIMER_RESTART; return HRTIMER_RESTART;
} }
...@@ -2054,16 +2072,21 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2054,16 +2072,21 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
} }
mutex_unlock(&data->mutex); mutex_unlock(&data->mutex);
if (!data->started || !data->beacon_int) for (idx = 0; idx < ARRAY_SIZE(data->link_data); idx++) {
hrtimer_cancel(&data->beacon_timer); struct mac80211_hwsim_link_data *link_data =
else if (!hrtimer_is_queued(&data->beacon_timer)) { &data->link_data[idx];
u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
u32 bcn_int = data->beacon_int; if (!data->started || !link_data->beacon_int) {
u64 until_tbtt = bcn_int - do_div(tsf, bcn_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, hrtimer_start(&link_data->beacon_timer,
ns_to_ktime(until_tbtt * NSEC_PER_USEC), ns_to_ktime(until_tbtt * NSEC_PER_USEC),
HRTIMER_MODE_REL_SOFT); HRTIMER_MODE_REL_SOFT);
}
} }
return 0; return 0;
...@@ -2124,6 +2147,7 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, ...@@ -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 hwsim_vif_priv *vp = (void *)vif->drv_priv;
struct mac80211_hwsim_data *data = hw->priv; struct mac80211_hwsim_data *data = hw->priv;
struct ieee80211_bss_conf *info = vif->link_conf[link_id]; 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); hwsim_check_magic(vif);
...@@ -2141,16 +2165,16 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, ...@@ -2141,16 +2165,16 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
info->enable_beacon, info->beacon_int); info->enable_beacon, info->beacon_int);
vp->bcn_en = info->enable_beacon; vp->bcn_en = info->enable_beacon;
if (data->started && if (data->started &&
!hrtimer_is_queued(&data->beacon_timer) && !hrtimer_is_queued(&link_data->beacon_timer) &&
info->enable_beacon) { info->enable_beacon) {
u64 tsf, until_tbtt; u64 tsf, until_tbtt;
u32 bcn_int; 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); 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); 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), ns_to_ktime(until_tbtt * NSEC_PER_USEC),
HRTIMER_MODE_REL_SOFT); HRTIMER_MODE_REL_SOFT);
} else if (!info->enable_beacon) { } else if (!info->enable_beacon) {
...@@ -2161,8 +2185,8 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw, ...@@ -2161,8 +2185,8 @@ static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u", wiphy_dbg(hw->wiphy, " beaconing vifs remaining: %u",
count); count);
if (count == 0) { if (count == 0) {
hrtimer_cancel(&data->beacon_timer); hrtimer_cancel(&link_data->beacon_timer);
data->beacon_int = 0; link_data->beacon_int = 0;
} }
} }
} }
...@@ -3875,9 +3899,13 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -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); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
hrtimer_init(&data->beacon_timer, CLOCK_MONOTONIC, for (i = 0; i < ARRAY_SIZE(data->link_data); i++) {
HRTIMER_MODE_ABS_SOFT); hrtimer_init(&data->link_data[i].beacon_timer, CLOCK_MONOTONIC,
data->beacon_timer.function = mac80211_hwsim_beacon; 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); err = ieee80211_register_hw(hw);
if (err < 0) { if (err < 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment