From 274e76f22f95c7628026e6f08d7206e9eb935765 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 13 Dec 2016 15:25:52 +0200 Subject: [PATCH] mesh: Fix channel configuration in pri/sec switch case If 20/40 MHz co-ex scan resulted in switching primary and secondary channels, mesh setup failed to update the frequency parameters for hostapd side configuration and that could result in invalid secondary channel configuration preventing creating of the mesh network. This could happen, e.g., when trying to set up mesh on 5 GHz channel 36 and co-ex scan finding a BSS on channel 40. Switching the pri/sec channels resulted in hostapd code trying to check whether channel 32 is available. Fix this by swapping the channels for hostapd configuration when needed. Signed-off-by: Jouni Malinen --- wpa_supplicant/mesh.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index d67d3b2aa..602ed2eb2 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -146,7 +146,8 @@ static void wpas_mesh_copy_groups(struct hostapd_data *bss, static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, - struct wpa_ssid *ssid) + struct wpa_ssid *ssid, + struct hostapd_freq_params *freq) { struct hostapd_iface *ifmsh; struct hostapd_data *bss; @@ -156,6 +157,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, static int default_groups[] = { 19, 20, 21, 25, 26, -1 }; size_t len; int rate_len; + int frequency; if (!wpa_s->conf->user_mpm) { /* not much for us to do here */ @@ -185,7 +187,13 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, bss->drv_priv = wpa_s->drv_priv; bss->iface = ifmsh; bss->mesh_sta_free_cb = mesh_mpm_free_sta; - wpa_s->assoc_freq = ssid->frequency; + frequency = ssid->frequency; + if (frequency != freq->freq && + frequency == freq->freq + freq->sec_channel_offset * 20) { + wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched"); + frequency = freq->freq; + } + wpa_s->assoc_freq = frequency; wpa_s->current_ssid = ssid; /* setup an AP config for auth processing */ @@ -211,10 +219,10 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, ifmsh->mconf = mconf; /* need conf->hw_mode for supported rates. */ - conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency, &conf->channel); + conf->hw_mode = ieee80211_freq_to_chan(frequency, &conf->channel); if (conf->hw_mode == NUM_HOSTAPD_MODES) { wpa_printf(MSG_ERROR, "Unsupported mesh mode frequency: %d MHz", - ssid->frequency); + frequency); goto out_free; } if (ssid->ht40) @@ -225,13 +233,13 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, case VHT_CHANWIDTH_80MHZ: case VHT_CHANWIDTH_80P80MHZ: ieee80211_freq_to_chan( - ssid->frequency, + frequency, &conf->vht_oper_centr_freq_seg0_idx); conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; break; case VHT_CHANWIDTH_160MHZ: ieee80211_freq_to_chan( - ssid->frequency, + frequency, &conf->vht_oper_centr_freq_seg0_idx); conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; conf->vht_oper_centr_freq_seg0_idx += 40 / 5; @@ -422,7 +430,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, } params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity; - if (wpa_supplicant_mesh_init(wpa_s, ssid)) { + if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms.freq)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh"); wpa_drv_leave_mesh(wpa_s); ret = -1;