RRM: Update own neighbor report on channel switch

Message ID 20180820122044.10018-1-markus.theil@tu-ilmenau.de
State New
Headers show
Series
  • RRM: Update own neighbor report on channel switch
Related show

Commit Message

Markus Theil Aug. 20, 2018, 12:20 p.m.
After performing a successful channel switch,
the AP should update its own neighbor report element.
The corresponding functions are therefore moved to
src/ap/neighbor_db.[c,h] and also called from src/ap/drv_callbacks.c
after successful switch.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
 src/ap/drv_callbacks.c |   7 ++-
 src/ap/hostapd.c       | 123 +----------------------------------------
 src/ap/neighbor_db.c   | 119 +++++++++++++++++++++++++++++++++++++++
 src/ap/neighbor_db.h   |   1 +
 4 files changed, 126 insertions(+), 124 deletions(-)

Patch

diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 399427804..dc2faa12e 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -38,7 +38,7 @@ 
 #include "mbo_ap.h"
 #include "dpp_hostapd.h"
 #include "fils_hlp.h"
-
+#include "ap/neighbor_db.h"
 
 #ifdef CONFIG_FILS
 void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd,
@@ -736,7 +736,7 @@  void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 			     int offset, int width, int cf1, int cf2)
 {
 #ifdef NEED_AP_MLME
-	int channel, chwidth, is_dfs;
+	int channel, chwidth, is_dfs, i;
 	u8 seg0_idx = 0, seg1_idx = 0;
 
 	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
@@ -820,6 +820,9 @@  void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht,
 		wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED
 			"freq=%d dfs=%d", freq, is_dfs);
 	}
+
+	for (i = 0; i < hapd->iface->num_bss; i++)
+		hostapd_neighbor_set_own_report(hapd->iface->bss[i]);
 #endif /* NEED_AP_MLME */
 }
 
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index f0955863e..fc3991958 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -1610,127 +1610,6 @@  void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd,
 
 #endif /* CONFIG_FST */
 
-
-#ifdef NEED_AP_MLME
-static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
-						    int ht, int vht)
-{
-	if (!ht && !vht)
-		return NR_CHAN_WIDTH_20;
-	if (!hapd->iconf->secondary_channel)
-		return NR_CHAN_WIDTH_20;
-	if (!vht || hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
-		return NR_CHAN_WIDTH_40;
-	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
-		return NR_CHAN_WIDTH_80;
-	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_160MHZ)
-		return NR_CHAN_WIDTH_160;
-	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ)
-		return NR_CHAN_WIDTH_80P80;
-	return NR_CHAN_WIDTH_20;
-}
-#endif /* NEED_AP_MLME */
-
-
-static void hostapd_set_own_neighbor_report(struct hostapd_data *hapd)
-{
-#ifdef NEED_AP_MLME
-	u16 capab = hostapd_own_capab_info(hapd);
-	int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
-	int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
-	struct wpa_ssid_value ssid;
-	u8 channel, op_class;
-	u8 center_freq1_idx = 0, center_freq2_idx = 0;
-	enum nr_chan_width width;
-	u32 bssid_info;
-	struct wpabuf *nr;
-
-	if (!(hapd->conf->radio_measurements[0] &
-	      WLAN_RRM_CAPS_NEIGHBOR_REPORT))
-		return;
-
-	bssid_info = 3; /* AP is reachable */
-	bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
-	bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
-
-	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
-		bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
-
-	bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
-
-	if (hapd->conf->wmm_enabled) {
-		bssid_info |= NEI_REP_BSSID_INFO_QOS;
-
-		if (hapd->conf->wmm_uapsd &&
-		    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
-			bssid_info |= NEI_REP_BSSID_INFO_APSD;
-	}
-
-	if (ht) {
-		bssid_info |= NEI_REP_BSSID_INFO_HT |
-			NEI_REP_BSSID_INFO_DELAYED_BA;
-
-		/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
-		if (vht)
-			bssid_info |= NEI_REP_BSSID_INFO_VHT;
-	}
-
-	/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
-
-	if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
-					  hapd->iconf->secondary_channel,
-					  hapd->iconf->vht_oper_chwidth,
-					  &op_class, &channel) ==
-	    NUM_HOSTAPD_MODES)
-		return;
-	width = hostapd_get_nr_chan_width(hapd, ht, vht);
-	if (vht) {
-		center_freq1_idx = hapd->iconf->vht_oper_centr_freq_seg0_idx;
-		if (width == NR_CHAN_WIDTH_80P80)
-			center_freq2_idx =
-				hapd->iconf->vht_oper_centr_freq_seg1_idx;
-	} else if (ht) {
-		ieee80211_freq_to_chan(hapd->iface->freq +
-				       10 * hapd->iconf->secondary_channel,
-				       &center_freq1_idx);
-	}
-
-	ssid.ssid_len = hapd->conf->ssid.ssid_len;
-	os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
-
-	/*
-	 * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
-	 * phy type + wide bandwidth channel subelement.
-	 */
-	nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
-	if (!nr)
-		return;
-
-	wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
-	wpabuf_put_le32(nr, bssid_info);
-	wpabuf_put_u8(nr, op_class);
-	wpabuf_put_u8(nr, channel);
-	wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
-
-	/*
-	 * Wide Bandwidth Channel subelement may be needed to allow the
-	 * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
-	 * Figure 9-301.
-	 */
-	wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
-	wpabuf_put_u8(nr, 3);
-	wpabuf_put_u8(nr, width);
-	wpabuf_put_u8(nr, center_freq1_idx);
-	wpabuf_put_u8(nr, center_freq2_idx);
-
-	hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
-			     hapd->iconf->civic, hapd->iconf->stationary_ap);
-
-	wpabuf_free(nr);
-#endif /* NEED_AP_MLME */
-}
-
-
 #ifdef CONFIG_OWE
 
 static int hostapd_owe_iface_iter(struct hostapd_iface *iface, void *ctx)
@@ -2027,7 +1906,7 @@  dfs_offload:
 		iface->interfaces->terminate_on_error--;
 
 	for (j = 0; j < iface->num_bss; j++)
-		hostapd_set_own_neighbor_report(iface->bss[j]);
+		hostapd_neighbor_set_own_report(iface->bss[j]);
 
 	return 0;
 
diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c
index b8fd5924b..8e65f2dde 100644
--- a/src/ap/neighbor_db.c
+++ b/src/ap/neighbor_db.c
@@ -12,6 +12,7 @@ 
 #include "utils/common.h"
 #include "hostapd.h"
 #include "neighbor_db.h"
+#include "ap/ieee802_11.h"
 
 
 struct hostapd_neighbor_entry *
@@ -134,3 +135,121 @@  void hostpad_free_neighbor_db(struct hostapd_data *hapd)
 		os_free(nr);
 	}
 }
+
+#ifdef NEED_AP_MLME
+static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
+						    int ht, int vht)
+{
+	if (!ht && !vht)
+		return NR_CHAN_WIDTH_20;
+	if (!hapd->iconf->secondary_channel)
+		return NR_CHAN_WIDTH_20;
+	if (!vht || hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_USE_HT)
+		return NR_CHAN_WIDTH_40;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ)
+		return NR_CHAN_WIDTH_80;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_160MHZ)
+		return NR_CHAN_WIDTH_160;
+	if (hapd->iconf->vht_oper_chwidth == VHT_CHANWIDTH_80P80MHZ)
+		return NR_CHAN_WIDTH_80P80;
+	return NR_CHAN_WIDTH_20;
+}
+#endif /* NEED_AP_MLME */
+
+void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
+{
+#ifdef NEED_AP_MLME
+	u16 capab = hostapd_own_capab_info(hapd);
+	int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
+	int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
+	struct wpa_ssid_value ssid;
+	u8 channel, op_class;
+	u8 center_freq1_idx = 0, center_freq2_idx = 0;
+	enum nr_chan_width width;
+	u32 bssid_info;
+	struct wpabuf *nr;
+
+	if (!(hapd->conf->radio_measurements[0] &
+	      WLAN_RRM_CAPS_NEIGHBOR_REPORT))
+		return;
+
+	bssid_info = 3; /* AP is reachable */
+	bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
+	bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
+
+	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
+		bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
+
+	bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
+
+	if (hapd->conf->wmm_enabled) {
+		bssid_info |= NEI_REP_BSSID_INFO_QOS;
+
+		if (hapd->conf->wmm_uapsd &&
+		    (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
+			bssid_info |= NEI_REP_BSSID_INFO_APSD;
+	}
+
+	if (ht) {
+		bssid_info |= NEI_REP_BSSID_INFO_HT |
+			NEI_REP_BSSID_INFO_DELAYED_BA;
+
+		/* VHT bit added in IEEE P802.11-REVmc/D4.3 */
+		if (vht)
+			bssid_info |= NEI_REP_BSSID_INFO_VHT;
+	}
+
+	/* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
+
+	if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
+					  hapd->iconf->secondary_channel,
+					  hapd->iconf->vht_oper_chwidth,
+					  &op_class, &channel) ==
+	    NUM_HOSTAPD_MODES)
+		return;
+	width = hostapd_get_nr_chan_width(hapd, ht, vht);
+	if (vht) {
+		center_freq1_idx = hapd->iconf->vht_oper_centr_freq_seg0_idx;
+		if (width == NR_CHAN_WIDTH_80P80)
+			center_freq2_idx =
+				hapd->iconf->vht_oper_centr_freq_seg1_idx;
+	} else if (ht) {
+		ieee80211_freq_to_chan(hapd->iface->freq +
+				       10 * hapd->iconf->secondary_channel,
+				       &center_freq1_idx);
+	}
+
+	ssid.ssid_len = hapd->conf->ssid.ssid_len;
+	os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
+
+	/*
+	 * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
+	 * phy type + wide bandwidth channel subelement.
+	 */
+	nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
+	if (!nr)
+		return;
+
+	wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
+	wpabuf_put_le32(nr, bssid_info);
+	wpabuf_put_u8(nr, op_class);
+	wpabuf_put_u8(nr, channel);
+	wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
+
+	/*
+	 * Wide Bandwidth Channel subelement may be needed to allow the
+	 * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
+	 * Figure 9-301.
+	 */
+	wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
+	wpabuf_put_u8(nr, 3);
+	wpabuf_put_u8(nr, width);
+	wpabuf_put_u8(nr, center_freq1_idx);
+	wpabuf_put_u8(nr, center_freq2_idx);
+
+	hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
+			     hapd->iconf->civic, hapd->iconf->stationary_ap);
+
+	wpabuf_free(nr);
+#endif /* NEED_AP_MLME */
+}
\ No newline at end of file
diff --git a/src/ap/neighbor_db.h b/src/ap/neighbor_db.h
index ba46d8843..730f624a5 100644
--- a/src/ap/neighbor_db.h
+++ b/src/ap/neighbor_db.h
@@ -17,6 +17,7 @@  int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
 			 const struct wpa_ssid_value *ssid,
 			 const struct wpabuf *nr, const struct wpabuf *lci,
 			 const struct wpabuf *civic, int stationary);
+void hostapd_neighbor_set_own_report(struct hostapd_data *hapd);
 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
 			    const struct wpa_ssid_value *ssid);
 void hostpad_free_neighbor_db(struct hostapd_data *hapd);