mac80211_hwsim: check TX and STA bandwidth
Add checks to hwsim to validate that neither TX nor any station's configured bandwidth can exceed the channel (context) configuration previously requested. Link: https://lore.kernel.org/r/20220214173004.9fd154d2c3c2.Ia0cd152357a373149bab017d479ab7d5ded289c0@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
a3a20feb32
commit
585625c955
@ -654,6 +654,7 @@ struct mac80211_hwsim_data {
|
|||||||
ARRAY_SIZE(hwsim_channels_6ghz)];
|
ARRAY_SIZE(hwsim_channels_6ghz)];
|
||||||
|
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
|
enum nl80211_chan_width bw;
|
||||||
u64 beacon_int /* beacon interval in us */;
|
u64 beacon_int /* beacon interval in us */;
|
||||||
unsigned int rx_filter;
|
unsigned int rx_filter;
|
||||||
bool started, idle, scanning;
|
bool started, idle, scanning;
|
||||||
@ -808,6 +809,38 @@ extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data,
|
|||||||
#define hwsim_virtio_enabled false
|
#define hwsim_virtio_enabled false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int hwsim_get_chanwidth(enum nl80211_chan_width bw)
|
||||||
|
{
|
||||||
|
switch (bw) {
|
||||||
|
case NL80211_CHAN_WIDTH_20_NOHT:
|
||||||
|
case NL80211_CHAN_WIDTH_20:
|
||||||
|
return 20;
|
||||||
|
case NL80211_CHAN_WIDTH_40:
|
||||||
|
return 40;
|
||||||
|
case NL80211_CHAN_WIDTH_80:
|
||||||
|
return 80;
|
||||||
|
case NL80211_CHAN_WIDTH_80P80:
|
||||||
|
case NL80211_CHAN_WIDTH_160:
|
||||||
|
return 160;
|
||||||
|
case NL80211_CHAN_WIDTH_5:
|
||||||
|
return 5;
|
||||||
|
case NL80211_CHAN_WIDTH_10:
|
||||||
|
return 10;
|
||||||
|
case NL80211_CHAN_WIDTH_1:
|
||||||
|
return 1;
|
||||||
|
case NL80211_CHAN_WIDTH_2:
|
||||||
|
return 2;
|
||||||
|
case NL80211_CHAN_WIDTH_4:
|
||||||
|
return 4;
|
||||||
|
case NL80211_CHAN_WIDTH_8:
|
||||||
|
return 8;
|
||||||
|
case NL80211_CHAN_WIDTH_16:
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
return INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct ieee80211_channel *chan);
|
struct ieee80211_channel *chan);
|
||||||
@ -1623,7 +1656,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
struct ieee80211_chanctx_conf *chanctx_conf;
|
struct ieee80211_chanctx_conf *chanctx_conf;
|
||||||
struct ieee80211_channel *channel;
|
struct ieee80211_channel *channel;
|
||||||
bool ack;
|
bool ack;
|
||||||
u32 _portid;
|
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
u32 _portid, i;
|
||||||
|
|
||||||
if (WARN_ON(skb->len < 10)) {
|
if (WARN_ON(skb->len < 10)) {
|
||||||
/* Should not happen; just a sanity check for addr1 use */
|
/* Should not happen; just a sanity check for addr1 use */
|
||||||
@ -1633,14 +1667,17 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
|
|
||||||
if (!data->use_chanctx) {
|
if (!data->use_chanctx) {
|
||||||
channel = data->channel;
|
channel = data->channel;
|
||||||
|
confbw = data->bw;
|
||||||
} else if (txi->hw_queue == 4) {
|
} else if (txi->hw_queue == 4) {
|
||||||
channel = data->tmp_chan;
|
channel = data->tmp_chan;
|
||||||
} else {
|
} else {
|
||||||
chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
|
chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
|
||||||
if (chanctx_conf)
|
if (chanctx_conf) {
|
||||||
channel = chanctx_conf->def.chan;
|
channel = chanctx_conf->def.chan;
|
||||||
else
|
confbw = chanctx_conf->def.width;
|
||||||
|
} else {
|
||||||
channel = NULL;
|
channel = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) {
|
if (WARN(!channel, "TX w/o channel - queue = %d\n", txi->hw_queue)) {
|
||||||
@ -1664,6 +1701,25 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw,
|
|||||||
txi->control.rates,
|
txi->control.rates,
|
||||||
ARRAY_SIZE(txi->control.rates));
|
ARRAY_SIZE(txi->control.rates));
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(txi->control.rates); i++) {
|
||||||
|
u16 rflags = txi->control.rates[i].flags;
|
||||||
|
/* initialize to data->bw for 5/10 MHz handling */
|
||||||
|
enum nl80211_chan_width bw = data->bw;
|
||||||
|
|
||||||
|
if (txi->control.rates[i].idx == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (rflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
|
||||||
|
bw = NL80211_CHAN_WIDTH_40;
|
||||||
|
else if (rflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
|
||||||
|
bw = NL80211_CHAN_WIDTH_80;
|
||||||
|
else if (rflags & IEEE80211_TX_RC_160_MHZ_WIDTH)
|
||||||
|
bw = NL80211_CHAN_WIDTH_160;
|
||||||
|
|
||||||
|
if (WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw)))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (skb->len >= 24 + 8 &&
|
if (skb->len >= 24 + 8 &&
|
||||||
ieee80211_is_probe_resp(hdr->frame_control)) {
|
ieee80211_is_probe_resp(hdr->frame_control)) {
|
||||||
/* fake header transmission time */
|
/* fake header transmission time */
|
||||||
@ -1963,6 +2019,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data->channel = conf->chandef.chan;
|
data->channel = conf->chandef.chan;
|
||||||
|
data->bw = conf->chandef.width;
|
||||||
|
|
||||||
for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) {
|
for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) {
|
||||||
if (data->survey_data[idx].channel &&
|
if (data->survey_data[idx].channel &&
|
||||||
@ -1974,6 +2031,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
data->channel = conf->chandef.chan;
|
data->channel = conf->chandef.chan;
|
||||||
|
data->bw = conf->chandef.width;
|
||||||
}
|
}
|
||||||
mutex_unlock(&data->mutex);
|
mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
@ -2105,12 +2163,48 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
|
|||||||
wiphy_dbg(hw->wiphy, " TX Power: %d dBm\n", info->txpower);
|
wiphy_dbg(hw->wiphy, " TX Power: %d dBm\n", info->txpower);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mac80211_hwsim_sta_rc_update(struct ieee80211_hw *hw,
|
||||||
|
struct ieee80211_vif *vif,
|
||||||
|
struct ieee80211_sta *sta,
|
||||||
|
u32 changed)
|
||||||
|
{
|
||||||
|
struct mac80211_hwsim_data *data = hw->priv;
|
||||||
|
u32 bw = U32_MAX;
|
||||||
|
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
|
||||||
|
|
||||||
|
switch (sta->bandwidth) {
|
||||||
|
#define C(_bw) case IEEE80211_STA_RX_BW_##_bw: bw = _bw; break
|
||||||
|
C(20);
|
||||||
|
C(40);
|
||||||
|
C(80);
|
||||||
|
C(160);
|
||||||
|
#undef C
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data->use_chanctx) {
|
||||||
|
confbw = data->bw;
|
||||||
|
} else {
|
||||||
|
struct ieee80211_chanctx_conf *chanctx_conf =
|
||||||
|
rcu_dereference(vif->chanctx_conf);
|
||||||
|
|
||||||
|
if (!WARN_ON(!chanctx_conf))
|
||||||
|
confbw = chanctx_conf->def.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
WARN(bw > hwsim_get_chanwidth(confbw),
|
||||||
|
"intf %pM: bad STA %pM bandwidth %d MHz (%d) > channel config %d MHz (%d)\n",
|
||||||
|
vif->addr, sta->addr, bw, sta->bandwidth,
|
||||||
|
hwsim_get_chanwidth(data->bw), data->bw);
|
||||||
|
}
|
||||||
|
|
||||||
static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
|
static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
|
||||||
struct ieee80211_vif *vif,
|
struct ieee80211_vif *vif,
|
||||||
struct ieee80211_sta *sta)
|
struct ieee80211_sta *sta)
|
||||||
{
|
{
|
||||||
hwsim_check_magic(vif);
|
hwsim_check_magic(vif);
|
||||||
hwsim_set_sta_magic(sta);
|
hwsim_set_sta_magic(sta);
|
||||||
|
mac80211_hwsim_sta_rc_update(hw, vif, sta, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2677,6 +2771,7 @@ static int mac80211_hwsim_tx_last_beacon(struct ieee80211_hw *hw)
|
|||||||
.sta_add = mac80211_hwsim_sta_add, \
|
.sta_add = mac80211_hwsim_sta_add, \
|
||||||
.sta_remove = mac80211_hwsim_sta_remove, \
|
.sta_remove = mac80211_hwsim_sta_remove, \
|
||||||
.sta_notify = mac80211_hwsim_sta_notify, \
|
.sta_notify = mac80211_hwsim_sta_notify, \
|
||||||
|
.sta_rc_update = mac80211_hwsim_sta_rc_update, \
|
||||||
.set_tim = mac80211_hwsim_set_tim, \
|
.set_tim = mac80211_hwsim_set_tim, \
|
||||||
.conf_tx = mac80211_hwsim_conf_tx, \
|
.conf_tx = mac80211_hwsim_conf_tx, \
|
||||||
.get_survey = mac80211_hwsim_get_survey, \
|
.get_survey = mac80211_hwsim_get_survey, \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user