wpa_supplicant: Handle link measurement requests

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@intel.com>
This commit is contained in:
Andrei Otcheretianski 2014-11-05 03:42:56 -05:00 committed by Jouni Malinen
parent 7dc0338806
commit 70d1e72849
5 changed files with 127 additions and 3 deletions

View file

@ -350,6 +350,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 */
@ -1308,4 +1309,30 @@ 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;
/* IEEE Std 802.11-2012, 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;
/* IEEE Std 802.11-2012, 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 */

View file

@ -2785,7 +2785,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;
@ -2872,6 +2873,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)
@ -3258,7 +3267,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;
}

View file

@ -178,10 +178,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, 2 + rrm_ie_len);
*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;
}

View file

@ -5090,3 +5090,82 @@ int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s,
wpabuf_free(buf);
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;
const struct rrm_link_measurement_request *req;
struct rrm_link_measurement_report report;
if (wpa_s->wpa_state != WPA_COMPLETED) {
wpa_printf(MSG_INFO,
"RRM: Ignoring link measurement request. Not associated");
return;
}
if (!wpa_s->rrm.rrm_used) {
wpa_printf(MSG_INFO,
"RRM: Ignoring link measurement request. Not RRM network");
return;
}
if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) {
wpa_printf(MSG_INFO,
"RRM: Measurement report failed. TX power insertion not supported");
return;
}
req = (const struct rrm_link_measurement_request *) frame;
if (len < sizeof(*req)) {
wpa_printf(MSG_INFO,
"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 24 Mbps 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);
}

View file

@ -1030,6 +1030,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