diff mbox

[RFC,2/6] mesh: Allow CAC to be done during mesh initialization before joining

Message ID 20161128153843.3179-3-benjamin@sipsolutions.net
State RFC
Headers show

Commit Message

Benjamin Berg Nov. 28, 2016, 3:38 p.m. UTC
Before joining a CAC might be required. This requires changing the
interface into mesh mode a bit earlier and being able to handle it
correctly if hostapd_setup_interface needs to delay the interface
completition until the CAC is finished.

Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
---
 wpa_supplicant/ap.c               |  68 +++++++++++++++----------
 wpa_supplicant/mesh.c             | 104 ++++++++++++++++++++++----------------
 wpa_supplicant/wpa_supplicant_i.h |   2 +
 3 files changed, 104 insertions(+), 70 deletions(-)
diff mbox

Patch

diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 5afb772..e538bf0 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1443,61 +1443,77 @@  void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s)
 void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
 				   struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
-		return;
 	wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq);
-	hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
-				   radar->ht_enabled, radar->chan_offset,
-				   radar->chan_width,
-				   radar->cf1, radar->cf2);
+	if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0])
+		hostapd_dfs_radar_detected(wpa_s->ap_iface, radar->freq,
+					   radar->ht_enabled, radar->chan_offset,
+					   radar->chan_width,
+					   radar->cf1, radar->cf2);
+	if (wpa_s->ifmsh && wpa_s->ifmsh->bss[0])
+		hostapd_dfs_radar_detected(wpa_s->ifmsh, radar->freq,
+					   radar->ht_enabled, radar->chan_offset,
+					   radar->chan_width,
+					   radar->cf1, radar->cf2);
 }
 
 
 void wpas_event_dfs_cac_started(struct wpa_supplicant *wpa_s,
 				struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
-		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC started on %d MHz", radar->freq);
-	hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
-			      radar->ht_enabled, radar->chan_offset,
-			      radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0])
+		hostapd_dfs_start_cac(wpa_s->ap_iface, radar->freq,
+				      radar->ht_enabled, radar->chan_offset,
+				      radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ifmsh && wpa_s->ifmsh->bss[0])
+		hostapd_dfs_start_cac(wpa_s->ifmsh, radar->freq,
+				      radar->ht_enabled, radar->chan_offset,
+				      radar->chan_width, radar->cf1, radar->cf2);
 }
 
 
 void wpas_event_dfs_cac_finished(struct wpa_supplicant *wpa_s,
 				 struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
-		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
-				 radar->ht_enabled, radar->chan_offset,
-				 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0])
+		hostapd_dfs_complete_cac(wpa_s->ap_iface, 1, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ifmsh && wpa_s->ifmsh->bss[0])
+		hostapd_dfs_complete_cac(wpa_s->ifmsh, 1, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
 }
 
 
 void wpas_event_dfs_cac_aborted(struct wpa_supplicant *wpa_s,
 				struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
-		return;
 	wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq);
-	hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
-				 radar->ht_enabled, radar->chan_offset,
-				 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0])
+		hostapd_dfs_complete_cac(wpa_s->ap_iface, 0, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ifmsh && wpa_s->ifmsh->bss[0])
+		hostapd_dfs_complete_cac(wpa_s->ifmsh, 0, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
 }
 
 
 void wpas_event_dfs_cac_nop_finished(struct wpa_supplicant *wpa_s,
 				     struct dfs_event *radar)
 {
-	if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0])
-		return;
 	wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq);
-	hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
-				 radar->ht_enabled, radar->chan_offset,
-				 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ap_iface && wpa_s->ap_iface->bss[0])
+		hostapd_dfs_nop_finished(wpa_s->ap_iface, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
+	if (wpa_s->ifmsh && wpa_s->ifmsh->bss[0])
+		hostapd_dfs_nop_finished(wpa_s->ifmsh, radar->freq,
+					 radar->ht_enabled, radar->chan_offset,
+					 radar->chan_width, radar->cf1, radar->cf2);
 }
 #endif /* NEED_AP_MLME */
 
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 70069bf..116a2d6 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -144,6 +144,35 @@  static void wpas_mesh_copy_groups(struct hostapd_data *bss,
 			  groups_size);
 }
 
+static void wpas_mesh_configured_cb(void *ctx)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	struct wpa_driver_mesh_join_params *params = &wpa_s->mesh_join_params;
+	int ret;
+
+	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(params->meshid, params->meshid_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;
+}
+
 
 static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 				    struct wpa_ssid *ssid)
@@ -203,6 +232,10 @@  static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 	ifmsh->bss[0]->max_plinks = wpa_s->conf->max_peer_links;
 	ifmsh->bss[0]->dot11RSNASAERetransPeriod =
 		wpa_s->conf->dot11RSNASAERetransPeriod;
+
+	ifmsh->bss[0]->setup_complete_cb = wpas_mesh_configured_cb;
+	ifmsh->bss[0]->setup_complete_cb_ctx = wpa_s;
+
 	os_strlcpy(bss->conf->iface, wpa_s->ifname, sizeof(bss->conf->iface));
 
 	mconf = mesh_config_create(wpa_s, ssid);
@@ -362,7 +395,7 @@  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 = &wpa_s->mesh_join_params;
 	int ret = 0;
 
 	if (!ssid || !ssid->ssid || !ssid->ssid_len || !ssid->frequency) {
@@ -376,22 +409,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;
+	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;
 	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;
 			}
@@ -405,30 +438,33 @@  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->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;
 
+
+	/* hostapd_setup_interface calls wpas_mesh_configured_cb when we are
+	 * ready to join the mesh network. */
 	if (wpa_supplicant_mesh_init(wpa_s, ssid)) {
 		wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh");
 		wpa_drv_leave_mesh(wpa_s);
@@ -442,26 +478,6 @@  int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 		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);
-
 out:
 	return ret;
 }
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index d6ff6de..efedc5c 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -770,6 +770,8 @@  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_join_params;
 #endif /* CONFIG_MESH */
 
 	unsigned int off_channel_freq;