mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 16:11:38 +00:00
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)];
|
||||
|
||||
struct ieee80211_channel *channel;
|
||||
enum nl80211_chan_width bw;
|
||||
u64 beacon_int /* beacon interval in us */;
|
||||
unsigned int rx_filter;
|
||||
bool started, idle, scanning;
|
||||
@ -808,6 +809,38 @@ extern int hwsim_tx_virtio(struct mac80211_hwsim_data *data,
|
||||
#define hwsim_virtio_enabled false
|
||||
#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,
|
||||
struct sk_buff *skb,
|
||||
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_channel *channel;
|
||||
bool ack;
|
||||
u32 _portid;
|
||||
enum nl80211_chan_width confbw = NL80211_CHAN_WIDTH_20_NOHT;
|
||||
u32 _portid, i;
|
||||
|
||||
if (WARN_ON(skb->len < 10)) {
|
||||
/* 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) {
|
||||
channel = data->channel;
|
||||
confbw = data->bw;
|
||||
} else if (txi->hw_queue == 4) {
|
||||
channel = data->tmp_chan;
|
||||
} else {
|
||||
chanctx_conf = rcu_dereference(txi->control.vif->chanctx_conf);
|
||||
if (chanctx_conf)
|
||||
if (chanctx_conf) {
|
||||
channel = chanctx_conf->def.chan;
|
||||
else
|
||||
confbw = chanctx_conf->def.width;
|
||||
} else {
|
||||
channel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
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 &&
|
||||
ieee80211_is_probe_resp(hdr->frame_control)) {
|
||||
/* 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->bw = conf->chandef.width;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) {
|
||||
if (data->survey_data[idx].channel &&
|
||||
@ -1974,6 +2031,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
} else {
|
||||
data->channel = conf->chandef.chan;
|
||||
data->bw = conf->chandef.width;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
hwsim_check_magic(vif);
|
||||
hwsim_set_sta_magic(sta);
|
||||
mac80211_hwsim_sta_rc_update(hw, vif, sta, 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_remove = mac80211_hwsim_sta_remove, \
|
||||
.sta_notify = mac80211_hwsim_sta_notify, \
|
||||
.sta_rc_update = mac80211_hwsim_sta_rc_update, \
|
||||
.set_tim = mac80211_hwsim_set_tim, \
|
||||
.conf_tx = mac80211_hwsim_conf_tx, \
|
||||
.get_survey = mac80211_hwsim_get_survey, \
|
||||
|
Loading…
Reference in New Issue
Block a user