[PATCH 12/12] wpa_supplicant: Handle link measurement requests

Ilan Peer ilan.peer
Wed Nov 5 00:42:56 PST 2014


From: Andrei Otcheretianski <andrei.otcheretianski at intel.com>

Send link measurement response when a request is received. Advertise only
rcpi, computing it from the rssi of the request. The tx power field is left
to be filled by the driver. All other fields are not published.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/common/ieee802_11_defs.h      | 26 ++++++++++++++
 wpa_supplicant/events.c           | 14 ++++++--
 wpa_supplicant/sme.c              |  6 +++-
 wpa_supplicant/wpa_supplicant.c   | 75 +++++++++++++++++++++++++++++++++++++++
 wpa_supplicant/wpa_supplicant_i.h |  4 +++
 5 files changed, 122 insertions(+), 3 deletions(-)

diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index 80f61ec..c27af2b 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -348,6 +348,7 @@
 
 /* Radio Measurement capabilities (from RRM Capabilities IE) */
 /* byte 1 (out of 5) */
+#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0)
 #define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1)
 
 /* Timeout Interval Type */
@@ -1302,4 +1303,29 @@ enum wnm_sleep_mode_subelement_id {
 #define CHAN_SWITCH_MODE_ALLOW_TX	0
 #define CHAN_SWITCH_MODE_BLOCK_TX	1
 
+struct tpc_report {
+	u8 eid;
+	u8 len;
+	u8 tx_power;
+	u8 link_margin;
+} STRUCT_PACKED;
+
+/* 802.11-2012 spec, chapter 8.5.7.4 "Link Measurement Request frame format" */
+struct rrm_link_measurement_request {
+	u8 dialog_token;
+	s8 tx_power;
+	s8 max_tp;
+	u8 variable[0];
+} STRUCT_PACKED;
+
+/* 802.11-2012 spec, chapter 8.5.7.5 "Link Measurement Report frame format" */
+struct rrm_link_measurement_report {
+	u8 dialog_token;
+	struct tpc_report tpc;
+	u8 rx_ant_id;
+	u8 tx_ant_id;
+	u8 rcpi;
+	u8 rsni;
+	u8 variable[0];
+} STRUCT_PACKED;
 #endif /* IEEE802_11_DEFS_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 9c674d0..ba6c662 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2773,7 +2773,8 @@ static void wpa_supplicant_update_channel_list(
 
 
 static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
-				      const u8 *frame, size_t len, int freq)
+				      const u8 *frame, size_t len, int freq,
+				      int rssi)
 {
 	const struct ieee80211_mgmt *mgmt;
 	const u8 *payload;
@@ -2855,6 +2856,14 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
+	if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+	    payload[0] == WLAN_RRM_LINK_MEASUREMENT_REQUEST) {
+		wpas_rrm_handle_link_measurement_request(wpa_s, mgmt->sa,
+							 payload + 1, plen - 1,
+							 rssi);
+		return;
+	}
+
 	wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
 			   category, payload, plen, freq);
 	if (wpa_s->ifmsh)
@@ -3241,7 +3250,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 				wpas_event_rx_mgmt_action(
 					wpa_s, data->rx_mgmt.frame,
 					data->rx_mgmt.frame_len,
-					data->rx_mgmt.freq);
+					data->rx_mgmt.freq,
+					data->rx_mgmt.ssi_signal);
 				break;
 			}
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index bd42a64..ca7b7bc 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -175,10 +175,14 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
 
 	wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to association request");
 	pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
-	 /* IE body is made of bit flags, all initialized to 0 */
 	os_memset(pos, 0, rrm_ie_len + 2);
 	*pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
 	*pos++ = rrm_ie_len;
+
+	/* set supported capabilites flags */
+	if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
+		*pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
+
 	wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
 	wpa_s->rrm.rrm_used = 1;
 }
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 993102a..ac65576 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -5091,3 +5091,78 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
 	return 0;
 }
 
+
+void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
+					      const u8 *src,
+					      const u8 *frame, size_t len,
+					      int rssi) {
+	struct wpabuf *buf;
+	struct rrm_link_measurement_request *req = (void *)frame;
+	struct rrm_link_measurement_report report;
+
+	if (wpa_s->wpa_state != WPA_COMPLETED) {
+		wpa_printf(MSG_WARNING,
+			   "RRM: Ignoring link measurement request. Not associated");
+		return;
+	}
+
+	if (!wpa_s->rrm.rrm_used) {
+		wpa_printf(MSG_WARNING,
+			   "RRM: Ignoring link measurement request. Not RRM network");
+		return;
+	}
+
+	if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
+		wpa_printf(MSG_WARNING,
+			   "RRM: Msrmt report failed. Tx power insertion not supported");
+		return;
+	}
+
+	if (len < sizeof(*req)) {
+		wpa_printf(MSG_ERROR,
+			   "RRM: Link measurement report failed. Request too short.");
+		return;
+	}
+
+	os_memset(&report, 0, sizeof(report));
+	report.tpc.eid = WLAN_EID_TPC_REPORT;
+	report.tpc.len = 2;
+	report.rsni = 255; /* 255 indicates that RSNI is not available */
+	report.dialog_token = req->dialog_token;
+
+	/*
+	 * It's possible to estimate rcpi based on rssi in dBm. This
+	 * calculation will not reflect the correct value for high rates,
+	 * but it's good enough for action frames which are transmitted
+	 * with up to 24mbps rates.
+	 */
+	if (!rssi)
+		report.rcpi = 255; /* not available */
+	else if (rssi < -110)
+		report.rcpi = 0;
+	else if (rssi > 0)
+		report.rcpi = 220;
+	else
+		report.rcpi = (rssi + 110) * 2;
+
+	/* action_category + action_code */
+	buf = wpabuf_alloc(2 + sizeof(report));
+	if (buf == NULL) {
+		wpa_printf(MSG_ERROR,
+			   "RRM: Link measurement report failed. Buffer allocation failed");
+		return;
+	}
+
+	wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
+	wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT);
+	wpabuf_put_data(buf, &report, sizeof(report));
+	wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:",
+		    wpabuf_head(buf), wpabuf_len(buf));
+
+	if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src,
+				wpa_s->own_addr, wpa_s->bssid,
+				wpabuf_head(buf), wpabuf_len(buf), 0))
+		wpa_printf(MSG_ERROR,
+			   "RRM: Link measurement report failed. Send action failed.");
+	wpabuf_free(buf);
+}
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 91b563d..1be89d3 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -1018,6 +1018,10 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
 				       void (*cb)(void *ctx,
 						  struct wpabuf *neighbor_rep),
 				       void *cb_ctx);
+void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
+					      const u8 *src,
+					      const u8 *frame, size_t len,
+					      int rssi);
 
 /**
  * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response
-- 
1.8.3.2




More information about the Hostap mailing list