Commit 626c30f9 authored by Weilun Du's avatar Weilun Du Committed by Johannes Berg

mac80211_hwsim: add concurrent channels scanning support over virtio

This fixed the crash when setting channels to 2 or more when
communicating over virtio.
Signed-off-by: default avatarWeilun Du <wdu@google.com>
Link: https://lore.kernel.org/r/20210506180530.3418576-1-wdu@google.comSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent e6ed929b
...@@ -626,6 +626,7 @@ struct mac80211_hwsim_data { ...@@ -626,6 +626,7 @@ struct mac80211_hwsim_data {
u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
struct mac_address addresses[2]; struct mac_address addresses[2];
struct ieee80211_chanctx_conf *chanctx;
int channels, idx; int channels, idx;
bool use_chanctx; bool use_chanctx;
bool destroy_on_close; bool destroy_on_close;
...@@ -1257,7 +1258,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate) ...@@ -1257,7 +1258,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate)
static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
struct sk_buff *my_skb, struct sk_buff *my_skb,
int dst_portid) int dst_portid,
struct ieee80211_channel *channel)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct mac80211_hwsim_data *data = hw->priv; struct mac80211_hwsim_data *data = hw->priv;
...@@ -1312,7 +1314,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, ...@@ -1312,7 +1314,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw,
if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags))
goto nla_put_failure; goto nla_put_failure;
if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq))
goto nla_put_failure; goto nla_put_failure;
/* We get the tx control (rate and retries) info*/ /* We get the tx control (rate and retries) info*/
...@@ -1659,7 +1661,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, ...@@ -1659,7 +1661,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
_portid = READ_ONCE(data->wmediumd); _portid = READ_ONCE(data->wmediumd);
if (_portid || hwsim_virtio_enabled) if (_portid || hwsim_virtio_enabled)
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel);
/* NO wmediumd detected, perfect medium simulation */ /* NO wmediumd detected, perfect medium simulation */
data->tx_pkts++; data->tx_pkts++;
...@@ -1775,7 +1777,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, ...@@ -1775,7 +1777,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
mac80211_hwsim_monitor_rx(hw, skb, chan); mac80211_hwsim_monitor_rx(hw, skb, chan);
if (_pid || hwsim_virtio_enabled) if (_pid || hwsim_virtio_enabled)
return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan);
mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); mac80211_hwsim_tx_frame_no_nl(hw, skb, chan);
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -2514,6 +2516,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw, ...@@ -2514,6 +2516,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw,
static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx) struct ieee80211_chanctx_conf *ctx)
{ {
struct mac80211_hwsim_data *hwsim = hw->priv;
mutex_lock(&hwsim->mutex);
hwsim->chanctx = ctx;
mutex_unlock(&hwsim->mutex);
hwsim_set_chanctx_magic(ctx); hwsim_set_chanctx_magic(ctx);
wiphy_dbg(hw->wiphy, wiphy_dbg(hw->wiphy,
"add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
...@@ -2525,6 +2532,11 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, ...@@ -2525,6 +2532,11 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx) struct ieee80211_chanctx_conf *ctx)
{ {
struct mac80211_hwsim_data *hwsim = hw->priv;
mutex_lock(&hwsim->mutex);
hwsim->chanctx = NULL;
mutex_unlock(&hwsim->mutex);
wiphy_dbg(hw->wiphy, wiphy_dbg(hw->wiphy,
"remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
ctx->def.chan->center_freq, ctx->def.width, ctx->def.chan->center_freq, ctx->def.width,
...@@ -2537,6 +2549,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, ...@@ -2537,6 +2549,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
struct ieee80211_chanctx_conf *ctx, struct ieee80211_chanctx_conf *ctx,
u32 changed) u32 changed)
{ {
struct mac80211_hwsim_data *hwsim = hw->priv;
mutex_lock(&hwsim->mutex);
hwsim->chanctx = ctx;
mutex_unlock(&hwsim->mutex);
hwsim_check_chanctx_magic(ctx); hwsim_check_chanctx_magic(ctx);
wiphy_dbg(hw->wiphy, wiphy_dbg(hw->wiphy,
"change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
...@@ -3129,6 +3146,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ...@@ -3129,6 +3146,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
hw->wiphy->max_remain_on_channel_duration = 1000; hw->wiphy->max_remain_on_channel_duration = 1000;
data->if_combination.radar_detect_widths = 0; data->if_combination.radar_detect_widths = 0;
data->if_combination.num_different_channels = data->channels; data->if_combination.num_different_channels = data->channels;
data->chanctx = NULL;
} else { } else {
data->if_combination.num_different_channels = 1; data->if_combination.num_different_channels = 1;
data->if_combination.radar_detect_widths = data->if_combination.radar_detect_widths =
...@@ -3638,6 +3656,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, ...@@ -3638,6 +3656,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
int frame_data_len; int frame_data_len;
void *frame_data; void *frame_data;
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
struct ieee80211_channel *channel = NULL;
if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] ||
!info->attrs[HWSIM_ATTR_FRAME] || !info->attrs[HWSIM_ATTR_FRAME] ||
...@@ -3664,6 +3683,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, ...@@ -3664,6 +3683,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
if (!data2) if (!data2)
goto out; goto out;
if (data2->use_chanctx) {
if (data2->tmp_chan)
channel = data2->tmp_chan;
else if (data2->chanctx)
channel = data2->chanctx->def.chan;
} else {
channel = data2->channel;
}
if (!channel)
goto out;
if (!hwsim_virtio_enabled) { if (!hwsim_virtio_enabled) {
if (hwsim_net_get_netgroup(genl_info_net(info)) != if (hwsim_net_get_netgroup(genl_info_net(info)) !=
data2->netgroup) data2->netgroup)
...@@ -3675,7 +3705,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, ...@@ -3675,7 +3705,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
/* check if radio is configured properly */ /* check if radio is configured properly */
if (data2->idle || !data2->started) if ((data2->idle && !data2->tmp_chan) || !data2->started)
goto out; goto out;
/* A frame is received from user space */ /* A frame is received from user space */
...@@ -3688,18 +3718,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, ...@@ -3688,18 +3718,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
mutex_lock(&data2->mutex); mutex_lock(&data2->mutex);
rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]); rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]);
if (rx_status.freq != data2->channel->center_freq && if (rx_status.freq != channel->center_freq) {
(!data2->tmp_chan ||
rx_status.freq != data2->tmp_chan->center_freq)) {
mutex_unlock(&data2->mutex); mutex_unlock(&data2->mutex);
goto out; goto out;
} }
mutex_unlock(&data2->mutex); mutex_unlock(&data2->mutex);
} else { } else {
rx_status.freq = data2->channel->center_freq; rx_status.freq = channel->center_freq;
} }
rx_status.band = data2->channel->band; rx_status.band = channel->band;
rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
......
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