[PATCH v2 5/5] Unified channel switch call to remove duplicate code

Omer Dagan omer.dagan at tandemg.com
Sun Apr 7 23:45:06 PDT 2019


    Unified the callback for 'channel_switch' and
    'channel_switch_started' as they both use the
    same code and only differ in the event type and
    message sent to the control interface.
    the 'channel_switch_started' is raised before
    the kernel starts the actual channel switch process
    i.e. right after 'pre_channel_switch' callback,
    the 'channel_switch' event is raised after the process
    has already finished in the kernel and driver.

Signed-off-by: Omer Dagan <omer.dagan at tandemg.com>
---
 src/ap/drv_callbacks.c             | 111 +++++------------------------
 src/ap/hostapd.h                   |   2 +-
 src/drivers/driver.h               |   7 ++
 src/drivers/driver_nl80211_event.c |  90 +++++------------------
 wpa_supplicant/ap.c                |   4 +-
 wpa_supplicant/ap.h                |   2 +-
 wpa_supplicant/events.c            |  76 ++++++++++----------
 7 files changed, 81 insertions(+), 211 deletions(-)

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 455be8a71..e813dc16d 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -737,9 +737,8 @@ void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr,
 	}
 }
 
-
-void hostapd_event_ch_switch_started(struct hostapd_data *hapd, int freq, int ht,
-			     int offset, int width, int cf1, int cf2)
+void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
+			     int offset, int width, int cf1, int cf2, enum ch_switch_state state)
 {
 	/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
 
@@ -748,95 +747,19 @@ void hostapd_event_ch_switch_started(struct hostapd_data *hapd, int freq, int ht
 	u8 seg0_idx = 0, seg1_idx = 0;
 	size_t i;
 
-	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
+	if ( state == CH_SW_STARTED ) {
+		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO,
-		       "driver starting channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+		       "driver had channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
 		       freq, ht, hapd->iconf->ch_switch_vht_config, offset,
 		       width, channel_width_to_string(width), cf1, cf2);
-
-	hapd->iface->freq = freq;
-
-	channel = hostapd_hw_get_channel(hapd, freq);
-	if (!channel) {
+	} else {
 		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
-			       HOSTAPD_LEVEL_WARNING,
-			       "driver switched to bad channel!");
-	}
-
-	switch (width) {
-	case CHAN_WIDTH_80:
-		chwidth = VHT_CHANWIDTH_80MHZ;
-		break;
-	case CHAN_WIDTH_80P80:
-		chwidth = VHT_CHANWIDTH_80P80MHZ;
-		break;
-	case CHAN_WIDTH_160:
-		chwidth = VHT_CHANWIDTH_160MHZ;
-		break;
-	case CHAN_WIDTH_20_NOHT:
-	case CHAN_WIDTH_20:
-	case CHAN_WIDTH_40:
-	default:
-		chwidth = VHT_CHANWIDTH_USE_HT;
-		break;
-	}
-
-	switch (hapd->iface->current_mode->mode) {
-	case HOSTAPD_MODE_IEEE80211A:
-		if (cf1 > 5000)
-			seg0_idx = (cf1 - 5000) / 5;
-		if (cf2 > 5000)
-			seg1_idx = (cf2 - 5000) / 5;
-		break;
-	default:
-		ieee80211_freq_to_chan(cf1, &seg0_idx);
-		ieee80211_freq_to_chan(cf2, &seg1_idx);
-		break;
-	}
-
-	hapd->iconf->channel = channel;
-	hapd->iconf->ieee80211n = ht;
-	if (!ht) {
-		hapd->iconf->ieee80211ac = 0;
-	} else if (hapd->iconf->ch_switch_vht_config) {
-		/* CHAN_SWITCH VHT config */
-		if (hapd->iconf->ch_switch_vht_config &
-		    CH_SWITCH_VHT_ENABLED)
-			hapd->iconf->ieee80211ac = 1;
-		else if (hapd->iconf->ch_switch_vht_config &
-			 CH_SWITCH_VHT_DISABLED)
-			hapd->iconf->ieee80211ac = 0;
-	}
-	hapd->iconf->ch_switch_vht_config = 0;
-
-	hapd->iconf->secondary_channel = offset;
-	hapd->iconf->vht_oper_chwidth = chwidth;
-	hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx;
-	hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx;
-
-	is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
-				  hapd->iface->num_hw_features);
-
-	wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED
-			"freq=%d dfs=%d", freq, is_dfs);
-
-#endif /* NEED_AP_MLME */
-}
-void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset, int width, int cf1, int cf2)
-{
-	/* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */
-
-#ifdef NEED_AP_MLME
-	int channel, chwidth, is_dfs;
-	u8 seg0_idx = 0, seg1_idx = 0;
-	size_t i;
-
-	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
 		       HOSTAPD_LEVEL_INFO,
-		       "driver had channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
+		       "driver starting channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d",
 		       freq, ht, hapd->iconf->ch_switch_vht_config, offset,
 		       width, channel_width_to_string(width), cf1, cf2);
+	}
 
 	hapd->iface->freq = freq;
 
@@ -902,6 +825,12 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 	is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features,
 				  hapd->iface->num_hw_features);
 
+	if ( state == CH_SW_STARTED ) {
+		wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED
+			"freq=%d dfs=%d", freq, is_dfs);
+		return;
+	}
+
 	if (hapd->csa_in_progress &&
 	    freq == hapd->cs_freq_params.freq) {
 		hostapd_cleanup_cs_params(hapd);
@@ -1741,15 +1670,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 		hostapd_notif_auth(hapd, &data->auth);
 		break;
 	case EVENT_CH_SWITCH_STARTED:
-		if (!data)
-			break;
-		hostapd_event_ch_switch_started(hapd, data->ch_switch.freq,
-					data->ch_switch.ht_enabled,
-					data->ch_switch.ch_offset,
-					data->ch_switch.ch_width,
-					data->ch_switch.cf1,
-					data->ch_switch.cf2);
-		break;
 	case EVENT_CH_SWITCH:
 		if (!data)
 			break;
@@ -1758,7 +1678,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 					data->ch_switch.ch_offset,
 					data->ch_switch.ch_width,
 					data->ch_switch.cf1,
-					data->ch_switch.cf2);
+					data->ch_switch.cf2,
+					data->ch_switch.state);
 		break;
 	case EVENT_CONNECT_FAILED_REASON:
 		if (!data)
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index b8637c46a..6cc873a9f 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -609,7 +609,7 @@ int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da,
 			 const u8 *bssid, const u8 *ie, size_t ie_len,
 			 int ssi_signal);
 void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
-			     int offset, int width, int cf1, int cf2);
+			     int offset, int width, int cf1, int cf2, enum ch_switch_state state);
 struct survey_results;
 void hostapd_event_get_survey(struct hostapd_iface *iface,
 			      struct survey_results *survey_results);
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5d3c15b4f..de5519e8f 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1122,6 +1122,11 @@ enum hide_ssid {
 	HIDDEN_SSID_ZERO_CONTENTS
 };
 
+enum ch_switch_state {
+	CH_SW_STARTED,
+	CH_SW_FINISHED
+};
+
 struct wowlan_triggers {
 	u8 any;
 	u8 disconnect;
@@ -5388,6 +5393,7 @@ union wpa_event_data {
 	 * @ch_width: Channel width
 	 * @cf1: Center frequency 1
 	 * @cf2: Center frequency 2
+	 * @state: Whether the switch has just started or has already finished
 	 */
 	struct ch_switch {
 		int freq;
@@ -5396,6 +5402,7 @@ union wpa_event_data {
 		enum chan_width ch_width;
 		int cf1;
 		int cf2;
+		enum ch_switch_state state;
 	} ch_switch;
 
 	/**
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index a02ed3cf6..97d894494 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -528,78 +528,11 @@ static int calculate_chan_offset(int width, int freq, int cf1, int cf2)
 	return (abs(freq - freq1) / 20) % 2 == 0 ? 1 : -1;
 }
 
-static void mlme_event_ch_switch_started(struct wpa_driver_nl80211_data *drv,
-				 struct nlattr *ifindex, struct nlattr *freq,
-				 struct nlattr *type, struct nlattr *bw,
-				 struct nlattr *cf1, struct nlattr *cf2)
-{
-	struct i802_bss *bss;
-	union wpa_event_data data;
-	int ht_enabled = 1;
-	int chan_offset = 0;
-	int ifidx;
-
-	wpa_printf(MSG_DEBUG, "nl80211: Channel switch started event");
-
-	if (!freq)
-		return;
-
-	ifidx = nla_get_u32(ifindex);
-	bss = get_bss_ifindex(drv, ifidx);
-	if (bss == NULL) {
-		wpa_printf(MSG_WARNING, "nl80211: Unknown ifindex (%d) for channel switch started, ignoring",
-			   ifidx);
-		return;
-	}
-
-	if (type) {
-		enum nl80211_channel_type ch_type = nla_get_u32(type);
-
-		wpa_printf(MSG_DEBUG, "nl80211: Channel type: %d", ch_type);
-		switch (ch_type) {
-		case NL80211_CHAN_NO_HT:
-			ht_enabled = 0;
-			break;
-		case NL80211_CHAN_HT20:
-			break;
-		case NL80211_CHAN_HT40PLUS:
-			chan_offset = 1;
-			break;
-		case NL80211_CHAN_HT40MINUS:
-			chan_offset = -1;
-			break;
-		}
-	} else if (bw && cf1) {
-		/* This can happen for example with VHT80 ch switch */
-		chan_offset = calculate_chan_offset(nla_get_u32(bw),
-						    nla_get_u32(freq),
-						    nla_get_u32(cf1),
-						    cf2 ? nla_get_u32(cf2) : 0);
-	} else {
-		wpa_printf(MSG_WARNING, "nl80211: Unknown secondary channel information - following channel definition calculations may fail");
-	}
-
-	os_memset(&data, 0, sizeof(data));
-	data.ch_switch.freq = nla_get_u32(freq);
-	data.ch_switch.ht_enabled = ht_enabled;
-	data.ch_switch.ch_offset = chan_offset;
-	if (bw)
-		data.ch_switch.ch_width = convert2width(nla_get_u32(bw));
-	if (cf1)
-		data.ch_switch.cf1 = nla_get_u32(cf1);
-	if (cf2)
-		data.ch_switch.cf2 = nla_get_u32(cf2);
-
-	bss->freq = data.ch_switch.freq;
-	drv->assoc_freq = data.ch_switch.freq;
-
-	wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH_STARTED, &data);
-}
-
 static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 				 struct nlattr *ifindex, struct nlattr *freq,
 				 struct nlattr *type, struct nlattr *bw,
-				 struct nlattr *cf1, struct nlattr *cf2)
+				 struct nlattr *cf1, struct nlattr *cf2,
+				 enum ch_switch_state state)
 {
 	struct i802_bss *bss;
 	union wpa_event_data data;
@@ -607,7 +540,10 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 	int chan_offset = 0;
 	int ifidx;
 
-	wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
+	if ( state == CH_SW_STARTED )
+		wpa_printf(MSG_DEBUG, "nl80211: Channel switch started event");
+	else
+		wpa_printf(MSG_DEBUG, "nl80211: Channel switch event");
 
 	if (!freq)
 		return;
@@ -658,10 +594,14 @@ static void mlme_event_ch_switch(struct wpa_driver_nl80211_data *drv,
 	if (cf2)
 		data.ch_switch.cf2 = nla_get_u32(cf2);
 
+	data.ch_switch.state = state; 
 	bss->freq = data.ch_switch.freq;
 	drv->assoc_freq = data.ch_switch.freq;
 
-	wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
+	if ( state == CH_SW_STARTED )
+		wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH_STARTED, &data);
+	else
+		wpa_supplicant_event(bss->ctx, EVENT_CH_SWITCH, &data);
 }
 
 
@@ -2569,13 +2509,14 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				   tb[NL80211_ATTR_PMKID]);
 		break;
 	case NL80211_CMD_CH_SWITCH_STARTED_NOTIFY:
-		mlme_event_ch_switch_started(drv,
+		mlme_event_ch_switch(drv,
 				     tb[NL80211_ATTR_IFINDEX],
 				     tb[NL80211_ATTR_WIPHY_FREQ],
 				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
 				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 				     tb[NL80211_ATTR_CENTER_FREQ1],
-				     tb[NL80211_ATTR_CENTER_FREQ2]);
+				     tb[NL80211_ATTR_CENTER_FREQ2],
+					 (enum ch_switch_state)CH_SW_STARTED);
 		break;
 	case NL80211_CMD_CH_SWITCH_NOTIFY:
 		mlme_event_ch_switch(drv,
@@ -2584,7 +2525,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
 				     tb[NL80211_ATTR_WIPHY_CHANNEL_TYPE],
 				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 				     tb[NL80211_ATTR_CENTER_FREQ1],
-				     tb[NL80211_ATTR_CENTER_FREQ2]);
+				     tb[NL80211_ATTR_CENTER_FREQ2],
+					 (enum ch_switch_state)CH_SW_FINISHED);
 		break;
 	case NL80211_CMD_DISCONNECT:
 		mlme_event_disconnect(drv, tb[NL80211_ATTR_REASON_CODE],
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 453c99dd5..5f1637a62 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -1384,7 +1384,7 @@ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
 
 
 void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
-		       int offset, int width, int cf1, int cf2)
+		       int offset, int width, int cf1, int cf2, enum ch_switch_state state)
 {
 	struct hostapd_iface *iface = wpa_s->ap_iface;
 
@@ -1396,7 +1396,7 @@ void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
 	if (wpa_s->current_ssid)
 		wpa_s->current_ssid->frequency = freq;
 	hostapd_event_ch_switch(iface->bss[0], freq, ht,
-				offset, width, cf1, cf2);
+				offset, width, cf1, cf2, state);
 }
 
 
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 447b55186..89efc801e 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -54,7 +54,7 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s,
 		      struct csa_settings *settings);
 int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *txtaddr);
 void wpas_ap_ch_switch(struct wpa_supplicant *wpa_s, int freq, int ht,
-		       int offset, int width, int cf1, int cf2);
+		       int offset, int width, int cf1, int cf2, enum ch_switch_state state);
 struct wpabuf * wpas_ap_wps_nfc_config_token(struct wpa_supplicant *wpa_s,
 					     int ndef);
 #ifdef CONFIG_AP
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index d4452cf7a..2c884a33e 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -4440,54 +4440,54 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #endif /* CONFIG_AP */
 
 	case EVENT_CH_SWITCH_STARTED:
-		if (!data || !wpa_s->current_ssid)
-			break;
-
-		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED
-			"freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
-			data->ch_switch.freq,
-			data->ch_switch.ht_enabled,
-			data->ch_switch.ch_offset,
-			channel_width_to_string(data->ch_switch.ch_width),
-			data->ch_switch.cf1,
-			data->ch_switch.cf2);
-		break;
 	case EVENT_CH_SWITCH:
 		if (!data || !wpa_s->current_ssid)
 			break;
 
-		wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
-			"freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
-			data->ch_switch.freq,
-			data->ch_switch.ht_enabled,
-			data->ch_switch.ch_offset,
-			channel_width_to_string(data->ch_switch.ch_width),
-			data->ch_switch.cf1,
-			data->ch_switch.cf2);
-
-		wpa_s->assoc_freq = data->ch_switch.freq;
-		wpa_s->current_ssid->frequency = data->ch_switch.freq;
+		if ( data->ch_switch.state == CH_SW_STARTED ) {
+			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH_STARTED
+				"freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+				data->ch_switch.freq,
+				data->ch_switch.ht_enabled,
+				data->ch_switch.ch_offset,
+				channel_width_to_string(data->ch_switch.ch_width),
+				data->ch_switch.cf1,
+				data->ch_switch.cf2);
+		} else {
+			wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
+				"freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+				data->ch_switch.freq,
+				data->ch_switch.ht_enabled,
+				data->ch_switch.ch_offset,
+				channel_width_to_string(data->ch_switch.ch_width),
+				data->ch_switch.cf1,
+				data->ch_switch.cf2);
+
+			wpa_s->assoc_freq = data->ch_switch.freq;
+			wpa_s->current_ssid->frequency = data->ch_switch.freq;
 
 #ifdef CONFIG_AP
-		if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
-		    wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
-		    wpa_s->current_ssid->mode == WPAS_MODE_MESH ||
-		    wpa_s->current_ssid->mode ==
-		    WPAS_MODE_P2P_GROUP_FORMATION) {
-			wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
-					  data->ch_switch.ht_enabled,
-					  data->ch_switch.ch_offset,
-					  data->ch_switch.ch_width,
-					  data->ch_switch.cf1,
-					  data->ch_switch.cf2);
-		}
+			if (wpa_s->current_ssid->mode == WPAS_MODE_AP ||
+				wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO ||
+				wpa_s->current_ssid->mode == WPAS_MODE_MESH ||
+				wpa_s->current_ssid->mode ==
+				WPAS_MODE_P2P_GROUP_FORMATION) {
+				wpas_ap_ch_switch(wpa_s, data->ch_switch.freq,
+						  data->ch_switch.ht_enabled,
+						  data->ch_switch.ch_offset,
+						  data->ch_switch.ch_width,
+						  data->ch_switch.cf1,
+						  data->ch_switch.cf2,
+						  data->ch_switch.state);
+			}
 #endif /* CONFIG_AP */
 
 #ifdef CONFIG_IEEE80211W
-		sme_event_ch_switch(wpa_s);
+			sme_event_ch_switch(wpa_s);
 #endif /* CONFIG_IEEE80211W */
-		wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
-		wnm_clear_coloc_intf_reporting(wpa_s);
+			wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
+			wnm_clear_coloc_intf_reporting(wpa_s);
+		}
 		break;
 #ifdef CONFIG_AP
 #ifdef NEED_AP_MLME
-- 
2.17.1




More information about the Hostap mailing list