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: Shaul Triebitz <shaul.triebitz@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
630c7e4621
commit
e57f8a489c
1 changed files with 59 additions and 31 deletions
|
@ -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 {
|
||||||
|
|
||||||
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 {
|
||||||
|
|
||||||
/* 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,
|
||||||
{
|
{
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
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;
|
|
||||||
u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
|
|
||||||
|
|
||||||
hrtimer_start(&data->beacon_timer,
|
if (!data->started || !link_data->beacon_int) {
|
||||||
ns_to_ktime(until_tbtt * NSEC_PER_USEC),
|
hrtimer_cancel(&link_data->beacon_timer);
|
||||||
HRTIMER_MODE_REL_SOFT);
|
} 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(&link_data->beacon_timer,
|
||||||
|
ns_to_ktime(until_tbtt * NSEC_PER_USEC),
|
||||||
|
HRTIMER_MODE_REL_SOFT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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 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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue