mesh: Factor out mesh join function

Mesh join function consists of two parts which are preparing
configurations and sending join event to the driver. Since physical mesh
join event could happen either right after mesh configuration is done or
after CAC is done in case of DFS channel is used, factor out the
function into two parts to reduce redundant calls.

Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
This commit is contained in:
Peter Oh 2018-08-27 14:28:34 -07:00 committed by Jouni Malinen
parent 03d9019811
commit 0daa7b75fa
2 changed files with 79 additions and 54 deletions

View file

@ -34,6 +34,8 @@ static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s)
wpa_s->current_ssid = NULL;
os_free(wpa_s->mesh_rsn);
wpa_s->mesh_rsn = NULL;
os_free(wpa_s->mesh_params);
wpa_s->mesh_params = NULL;
/* TODO: leave mesh (stop beacon). This will happen on link down
* anyway, so it's not urgent */
}
@ -188,6 +190,49 @@ static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s)
}
static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
{
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
struct wpa_ssid *ssid = wpa_s->current_ssid;
int ret;
if (!params || !ssid) {
wpa_printf(MSG_ERROR, "mesh: %s called without active mesh",
__func__);
return -1;
}
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
}
if (ifmsh) {
params->ies = ifmsh->mconf->rsn_ie;
params->ie_len = ifmsh->mconf->rsn_ie_len;
params->basic_rates = ifmsh->basic_rates;
params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
params->conf.ht_opmode = ifmsh->bss[0]->iface->ht_op_mode;
}
wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
ret = wpa_drv_join_mesh(wpa_s, params);
if (ret)
wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
/* hostapd sets the interface down until we associate */
wpa_drv_set_operstate(wpa_s, 1);
if (!ret)
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
return ret;
}
static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid,
struct hostapd_freq_params *freq)
@ -375,11 +420,13 @@ void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s,
int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
struct wpa_ssid *ssid)
{
struct wpa_driver_mesh_join_params params;
struct wpa_driver_mesh_join_params *params = os_zalloc(sizeof(*params));
int ret = 0;
if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency ||
!params) {
ret = -ENOENT;
os_free(params);
goto out;
}
@ -389,22 +436,22 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
wpa_s->group_cipher = WPA_CIPHER_NONE;
wpa_s->mgmt_group_cipher = 0;
os_memset(&params, 0, sizeof(params));
params.meshid = ssid->ssid;
params.meshid_len = ssid->ssid_len;
ibss_mesh_setup_freq(wpa_s, ssid, &params.freq);
wpa_s->mesh_ht_enabled = !!params.freq.ht_enabled;
wpa_s->mesh_vht_enabled = !!params.freq.vht_enabled;
if (params.freq.ht_enabled && params.freq.sec_channel_offset)
ssid->ht40 = params.freq.sec_channel_offset;
params->meshid = ssid->ssid;
params->meshid_len = ssid->ssid_len;
ibss_mesh_setup_freq(wpa_s, ssid, &params->freq);
wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
if (params->freq.ht_enabled && params->freq.sec_channel_offset)
ssid->ht40 = params->freq.sec_channel_offset;
if (wpa_s->mesh_vht_enabled) {
ssid->vht = 1;
switch (params.freq.bandwidth) {
switch (params->freq.bandwidth) {
case 80:
if (params.freq.center_freq2) {
if (params->freq.center_freq2) {
ssid->max_oper_chwidth = VHT_CHANWIDTH_80P80MHZ;
ssid->vht_center_freq2 =
params.freq.center_freq2;
params->freq.center_freq2;
} else {
ssid->max_oper_chwidth = VHT_CHANWIDTH_80MHZ;
}
@ -418,67 +465,44 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
}
}
if (ssid->beacon_int > 0)
params.beacon_int = ssid->beacon_int;
params->beacon_int = ssid->beacon_int;
else if (wpa_s->conf->beacon_int > 0)
params.beacon_int = wpa_s->conf->beacon_int;
params->beacon_int = wpa_s->conf->beacon_int;
if (ssid->dtim_period > 0)
params.dtim_period = ssid->dtim_period;
params->dtim_period = ssid->dtim_period;
else if (wpa_s->conf->dtim_period > 0)
params.dtim_period = wpa_s->conf->dtim_period;
params.conf.max_peer_links = wpa_s->conf->max_peer_links;
params->dtim_period = wpa_s->conf->dtim_period;
params->conf.max_peer_links = wpa_s->conf->max_peer_links;
if (ssid->mesh_rssi_threshold < DEFAULT_MESH_RSSI_THRESHOLD) {
params.conf.rssi_threshold = ssid->mesh_rssi_threshold;
params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
params->conf.rssi_threshold = ssid->mesh_rssi_threshold;
params->conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_RSSI_THRESHOLD;
}
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
params.flags |= WPA_DRIVER_MESH_FLAG_AMPE;
params->flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
params->flags |= WPA_DRIVER_MESH_FLAG_AMPE;
wpa_s->conf->user_mpm = 1;
}
if (wpa_s->conf->user_mpm) {
params.flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
params.conf.auto_plinks = 0;
params->flags |= WPA_DRIVER_MESH_FLAG_USER_MPM;
params->conf.auto_plinks = 0;
} else {
params.flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
params.conf.auto_plinks = 1;
params->flags |= WPA_DRIVER_MESH_FLAG_DRIVER_MPM;
params->conf.auto_plinks = 1;
}
params.conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
params->conf.peer_link_timeout = wpa_s->conf->mesh_max_inactivity;
if (wpa_supplicant_mesh_init(wpa_s, ssid, &params.freq)) {
os_free(wpa_s->mesh_params);
wpa_s->mesh_params = params;
if (wpa_supplicant_mesh_init(wpa_s, ssid, &params->freq)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
wpa_drv_leave_mesh(wpa_s);
ret = -1;
goto out;
}
if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
wpa_s->pairwise_cipher = wpa_s->mesh_rsn->pairwise_cipher;
wpa_s->group_cipher = wpa_s->mesh_rsn->group_cipher;
wpa_s->mgmt_group_cipher = wpa_s->mesh_rsn->mgmt_group_cipher;
}
if (wpa_s->ifmsh) {
params.ies = wpa_s->ifmsh->mconf->rsn_ie;
params.ie_len = wpa_s->ifmsh->mconf->rsn_ie_len;
params.basic_rates = wpa_s->ifmsh->basic_rates;
params.conf.flags |= WPA_DRIVER_MESH_CONF_FLAG_HT_OP_MODE;
params.conf.ht_opmode = wpa_s->ifmsh->bss[0]->iface->ht_op_mode;
}
wpa_msg(wpa_s, MSG_INFO, "joining mesh %s",
wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
ret = wpa_drv_join_mesh(wpa_s, &params);
if (ret)
wpa_msg(wpa_s, MSG_ERROR, "mesh join error=%d", ret);
/* hostapd sets the interface down until we associate */
wpa_drv_set_operstate(wpa_s, 1);
if (!ret)
wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
ret = wpas_mesh_complete(wpa_s);
out:
return ret;
}

View file

@ -820,6 +820,7 @@ struct wpa_supplicant {
unsigned int mesh_if_created:1;
unsigned int mesh_ht_enabled:1;
unsigned int mesh_vht_enabled:1;
struct wpa_driver_mesh_join_params *mesh_params;
#ifdef CONFIG_PMKSA_CACHE_EXTERNAL
/* struct external_pmksa_cache::list */
struct dl_list mesh_external_pmksa_cache;