Test functionality to override driver reported signal levels
"SET driver_signal_override <BSSID> [<si_signal< <si_avg_signal> <si_avg_beacon_signal> <si_noise> <scan_level>]" command can now be used to request wpa_supplicant to override driver reported signal levels for signal_poll and scan results. This can be used to test roaming behavior. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
c8eb7fe66c
commit
6c57019376
4 changed files with 180 additions and 14 deletions
|
@ -419,6 +419,64 @@ static int wpas_ctrl_iface_set_ric_ies(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
static int wpas_ctrl_iface_set_dso(struct wpa_supplicant *wpa_s,
|
||||
const char *val)
|
||||
{
|
||||
u8 bssid[ETH_ALEN];
|
||||
const char *pos = val;
|
||||
struct driver_signal_override *dso = NULL, *tmp, parsed;
|
||||
|
||||
if (hwaddr_aton(pos, bssid))
|
||||
return -1;
|
||||
pos = os_strchr(pos, ' ');
|
||||
|
||||
dl_list_for_each(tmp, &wpa_s->drv_signal_override,
|
||||
struct driver_signal_override, list) {
|
||||
if (os_memcmp(bssid, tmp->bssid, ETH_ALEN) == 0) {
|
||||
dso = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pos) {
|
||||
/* Remove existing entry */
|
||||
if (dso) {
|
||||
dl_list_del(&dso->list);
|
||||
os_free(dso);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
pos++;
|
||||
|
||||
/* Update an existing entry or add a new one */
|
||||
os_memset(&parsed, 0, sizeof(parsed));
|
||||
if (sscanf(pos, "%d %d %d %d %d",
|
||||
&parsed.si_current_signal,
|
||||
&parsed.si_avg_signal,
|
||||
&parsed.si_avg_beacon_signal,
|
||||
&parsed.si_current_noise,
|
||||
&parsed.scan_level) != 5)
|
||||
return -1;
|
||||
|
||||
if (!dso) {
|
||||
dso = os_zalloc(sizeof(*dso));
|
||||
if (!dso)
|
||||
return -1;
|
||||
os_memcpy(dso->bssid, bssid, ETH_ALEN);
|
||||
dl_list_add(&wpa_s->drv_signal_override, &dso->list);
|
||||
}
|
||||
dso->si_current_signal = parsed.si_current_signal;
|
||||
dso->si_avg_signal = parsed.si_avg_signal;
|
||||
dso->si_avg_beacon_signal = parsed.si_avg_beacon_signal;
|
||||
dso->si_current_noise = parsed.si_current_noise;
|
||||
dso->scan_level = parsed.scan_level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
||||
char *cmd)
|
||||
{
|
||||
|
@ -713,6 +771,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
|
|||
wpa_s->sae_commit_override = NULL;
|
||||
else
|
||||
wpa_s->sae_commit_override = wpabuf_parse_bin(value);
|
||||
} else if (os_strcasecmp(cmd, "driver_signal_override") == 0) {
|
||||
ret = wpas_ctrl_iface_set_dso(wpa_s, value);
|
||||
#ifdef CONFIG_DPP
|
||||
} else if (os_strcasecmp(cmd, "dpp_config_obj_override") == 0) {
|
||||
os_free(wpa_s->dpp_config_obj_override);
|
||||
|
@ -8104,6 +8164,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->rsnxe_override_assoc = NULL;
|
||||
wpabuf_free(wpa_s->rsnxe_override_eapol);
|
||||
wpa_s->rsnxe_override_eapol = NULL;
|
||||
wpas_clear_driver_signal_override(wpa_s);
|
||||
#ifdef CONFIG_DPP
|
||||
os_free(wpa_s->dpp_config_obj_override);
|
||||
wpa_s->dpp_config_obj_override = NULL;
|
||||
|
|
|
@ -124,13 +124,8 @@ static inline int wpa_drv_stop_sched_scan(struct wpa_supplicant *wpa_s)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline struct wpa_scan_results * wpa_drv_get_scan_results2(
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
if (wpa_s->driver->get_scan_results2)
|
||||
return wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
|
||||
return NULL;
|
||||
}
|
||||
struct wpa_scan_results *
|
||||
wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s);
|
||||
|
||||
static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid)
|
||||
{
|
||||
|
@ -494,13 +489,8 @@ static inline int wpa_drv_signal_monitor(struct wpa_supplicant *wpa_s,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_signal_info *si)
|
||||
{
|
||||
if (wpa_s->driver->signal_poll)
|
||||
return wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
|
||||
return -1;
|
||||
}
|
||||
int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_signal_info *si);
|
||||
|
||||
static inline int wpa_drv_channel_info(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_channel_info *ci)
|
||||
|
|
|
@ -487,6 +487,20 @@ void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx)
|
|||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct driver_signal_override *dso;
|
||||
|
||||
while ((dso = dl_list_first(&wpa_s->drv_signal_override,
|
||||
struct driver_signal_override, list))) {
|
||||
dl_list_del(&dso->list);
|
||||
os_free(dso);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
int i;
|
||||
|
@ -516,6 +530,7 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
|
|||
wpa_s->rsnxe_override_assoc = NULL;
|
||||
wpabuf_free(wpa_s->rsnxe_override_eapol);
|
||||
wpa_s->rsnxe_override_eapol = NULL;
|
||||
wpas_clear_driver_signal_override(wpa_s);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
if (wpa_s->conf != NULL) {
|
||||
|
@ -4802,6 +4817,9 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
|
|||
|
||||
dl_list_init(&wpa_s->bss_tmp_disallowed);
|
||||
dl_list_init(&wpa_s->fils_hlp_req);
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
dl_list_init(&wpa_s->drv_signal_override);
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
return wpa_s;
|
||||
}
|
||||
|
@ -7884,3 +7902,87 @@ int wpas_disable_mac_addr_randomization(struct wpa_supplicant *wpa_s,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s,
|
||||
struct wpa_signal_info *si)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!wpa_s->driver->signal_poll)
|
||||
return -1;
|
||||
|
||||
res = wpa_s->driver->signal_poll(wpa_s->drv_priv, si);
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
if (res == 0) {
|
||||
struct driver_signal_override *dso;
|
||||
|
||||
dl_list_for_each(dso, &wpa_s->drv_signal_override,
|
||||
struct driver_signal_override, list) {
|
||||
if (os_memcmp(wpa_s->bssid, dso->bssid,
|
||||
ETH_ALEN) != 0)
|
||||
continue;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Override driver signal_poll information: current_signal: %d->%d avg_signal: %d->%d avg_beacon_signal: %d->%d current_noise: %d->%d",
|
||||
si->current_signal,
|
||||
dso->si_current_signal,
|
||||
si->avg_signal,
|
||||
dso->si_avg_signal,
|
||||
si->avg_beacon_signal,
|
||||
dso->si_avg_beacon_signal,
|
||||
si->current_noise,
|
||||
dso->si_current_noise);
|
||||
si->current_signal = dso->si_current_signal;
|
||||
si->avg_signal = dso->si_avg_signal;
|
||||
si->avg_beacon_signal = dso->si_avg_beacon_signal;
|
||||
si->current_noise = dso->si_current_noise;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
struct wpa_scan_results *
|
||||
wpa_drv_get_scan_results2(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
struct wpa_scan_results *scan_res;
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
size_t idx;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
if (!wpa_s->driver->get_scan_results2)
|
||||
return NULL;
|
||||
|
||||
scan_res = wpa_s->driver->get_scan_results2(wpa_s->drv_priv);
|
||||
|
||||
#ifdef CONFIG_TESTING_OPTIONS
|
||||
for (idx = 0; scan_res && idx < scan_res->num; idx++) {
|
||||
struct driver_signal_override *dso;
|
||||
struct wpa_scan_res *res = scan_res->res[idx];
|
||||
|
||||
dl_list_for_each(dso, &wpa_s->drv_signal_override,
|
||||
struct driver_signal_override, list) {
|
||||
if (os_memcmp(res->bssid, dso->bssid, ETH_ALEN) != 0)
|
||||
continue;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"Override driver scan signal level %d->%d for "
|
||||
MACSTR,
|
||||
res->level, dso->scan_level,
|
||||
MAC2STR(res->bssid));
|
||||
res->flags |= WPA_SCAN_QUAL_INVALID;
|
||||
if (dso->scan_level < 0)
|
||||
res->flags |= WPA_SCAN_LEVEL_DBM;
|
||||
else
|
||||
res->flags &= ~WPA_SCAN_LEVEL_DBM;
|
||||
res->level = dso->scan_level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
return scan_res;
|
||||
}
|
||||
|
|
|
@ -480,6 +480,16 @@ struct fils_hlp_req {
|
|||
struct wpabuf *pkt;
|
||||
};
|
||||
|
||||
struct driver_signal_override {
|
||||
struct dl_list list;
|
||||
u8 bssid[ETH_ALEN];
|
||||
int si_current_signal;
|
||||
int si_avg_signal;
|
||||
int si_avg_beacon_signal;
|
||||
int si_current_noise;
|
||||
int scan_level;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wpa_supplicant - Internal data for wpa_supplicant interface
|
||||
*
|
||||
|
@ -1132,6 +1142,7 @@ struct wpa_supplicant {
|
|||
int *extra_sae_rejected_groups;
|
||||
struct wpabuf *rsnxe_override_assoc;
|
||||
struct wpabuf *rsnxe_override_eapol;
|
||||
struct dl_list drv_signal_override;
|
||||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
struct wmm_ac_assoc_data *wmm_ac_assoc_info;
|
||||
|
@ -1570,4 +1581,6 @@ int wpas_ctrl_iface_get_pref_freq_list_override(struct wpa_supplicant *wpa_s,
|
|||
int wpa_is_fils_supported(struct wpa_supplicant *wpa_s);
|
||||
int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s);
|
||||
|
||||
void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s);
|
||||
|
||||
#endif /* WPA_SUPPLICANT_I_H */
|
||||
|
|
Loading…
Reference in a new issue