From 4065a3092b37246e906f6a9faeb2238631957214 Mon Sep 17 00:00:00 2001 From: Jay Katabathuni Date: Sat, 25 Aug 2012 16:09:01 +0300 Subject: [PATCH] HS 2.0: Add advertisement of WAN Metrics Signed-hostap: Jouni Malinen --- hostapd/config_file.c | 70 +++++++++++++++++++++++++++++++++++++++++++ hostapd/hostapd.conf | 14 +++++++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/gas_serv.c | 24 +++++++++++++++ src/ap/gas_serv.h | 2 ++ 6 files changed, 112 insertions(+) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8988bf926..9692251f6 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1441,6 +1441,71 @@ static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf, return 0; } + + +static int hs20_parse_wan_metrics(struct hostapd_bss_config *bss, char *buf, + int line) +{ + u8 *wan_metrics; + char *pos; + + /* :
:
    :
    :
      : */ + + wan_metrics = os_zalloc(13); + if (wan_metrics == NULL) + return -1; + + pos = buf; + /* WAN Info */ + if (hexstr2bin(pos, wan_metrics, 1) < 0) + goto fail; + pos += 2; + if (*pos != ':') + goto fail; + pos++; + + /* Downlink Speed */ + WPA_PUT_LE32(wan_metrics + 1, atoi(pos)); + pos = os_strchr(pos, ':'); + if (pos == NULL) + goto fail; + pos++; + + /* Uplink Speed */ + WPA_PUT_LE32(wan_metrics + 5, atoi(pos)); + pos = os_strchr(pos, ':'); + if (pos == NULL) + goto fail; + pos++; + + /* Downlink Load */ + wan_metrics[9] = atoi(pos); + pos = os_strchr(pos, ':'); + if (pos == NULL) + goto fail; + pos++; + + /* Uplink Load */ + wan_metrics[10] = atoi(pos); + pos = os_strchr(pos, ':'); + if (pos == NULL) + goto fail; + pos++; + + /* LMD */ + WPA_PUT_LE16(wan_metrics + 11, atoi(pos)); + + os_free(bss->hs20_wan_metrics); + bss->hs20_wan_metrics = wan_metrics; + + return 0; + +fail: + wpa_printf(MSG_ERROR, "Line %d: Invalid hs20_wan_metrics '%s'", + line, pos); + os_free(wan_metrics); + return -1; +} #endif /* CONFIG_HS20 */ @@ -2609,6 +2674,11 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->hs20 = atoi(pos); } else if (os_strcmp(buf, "disable_dgaf") == 0) { bss->disable_dgaf = atoi(pos); + } else if (os_strcmp(buf, "hs20_wan_metrics") == 0) { + if (hs20_parse_wan_metrics(bss, pos, line) < 0) { + errors++; + return errors; + } } else if (os_strcmp(buf, "hs20_conn_capab") == 0) { if (hs20_parse_conn_capab(bss, pos, line) < 0) { errors++; diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index aa90d78bb..95a9835e9 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1412,6 +1412,20 @@ own_ip_addr=127.0.0.1 #hs20_conn_capab=6:22:1 #hs20_conn_capab=17:5060:0 +# WAN Metrics +# format: :
      :
        :
        :
          : +# WAN Info: B0-B1: Link Status, B2: Symmetric Link, B3: At Capabity +# (encoded as two hex digits) +# Link Status: 1 = Link up, 2 = Link down, 3 = Link in test state +# Downlink Speed: Estimate of WAN backhaul link current downlink speed in kbps; +# 1..4294967295; 0 = unknown +# Uplink Speed: Estimate of WAN backhaul link current uplink speed in kbps +# 1..4294967295; 0 = unknown +# Downlink Load: Current load of downlink WAN connection (scaled to 255 = 100%) +# Uplink Load: Current load of uplink WAN connection (scaled to 255 = 100%) +# Load Measurement Duration: Duration for measuring downlink/uplink load in +# tenths of a second (1..65535); 0 if load cannot be determined +#hs20_wan_metrics=01:8000:1000:80:240:3000 # Operating Class Indication # List of operating classes the BSSes in this ESS use. The Global operating diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index c4aabdad4..a2f226e2f 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -507,6 +507,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf) #endif /* CONFIG_RADIUS_TEST */ #ifdef CONFIG_HS20 + os_free(conf->hs20_wan_metrics); os_free(conf->hs20_connection_capability); os_free(conf->hs20_operating_class); #endif /* CONFIG_HS20 */ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index ebc1b9599..5dfc8a615 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -410,6 +410,7 @@ struct hostapd_bss_config { #ifdef CONFIG_HS20 int hs20; int disable_dgaf; + u8 *hs20_wan_metrics; u8 *hs20_connection_capability; size_t hs20_connection_capability_len; u8 *hs20_operating_class; diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index f914eefef..5572c073f 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -139,6 +139,8 @@ static void anqp_add_hs_capab_list(struct hostapd_data *hapd, wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); wpabuf_put_u8(buf, 0); /* Reserved */ wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST); + if (hapd->conf->hs20_wan_metrics) + wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); if (hapd->conf->hs20_connection_capability) wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY); if (hapd->conf->hs20_operating_class) @@ -255,6 +257,21 @@ static void anqp_add_domain_name(struct hostapd_data *hapd, struct wpabuf *buf) } +static void anqp_add_wan_metrics(struct hostapd_data *hapd, + struct wpabuf *buf) +{ + if (hapd->conf->hs20_wan_metrics) { + u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC); + wpabuf_put_be24(buf, OUI_WFA); + wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE); + wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS); + wpabuf_put_u8(buf, 0); /* Reserved */ + wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13); + gas_anqp_set_element_len(buf, len); + } +} + + static void anqp_add_connection_capability(struct hostapd_data *hapd, struct wpabuf *buf) { @@ -315,6 +332,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd, if (request & ANQP_REQ_HS_CAPABILITY_LIST) anqp_add_hs_capab_list(hapd, buf); + if (request & ANQP_REQ_WAN_METRICS) + anqp_add_wan_metrics(hapd, buf); if (request & ANQP_REQ_CONNECTION_CAPABILITY) anqp_add_connection_capability(hapd, buf); if (request & ANQP_REQ_OPERATING_CLASS) @@ -430,6 +449,11 @@ static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype, set_anqp_req(ANQP_REQ_HS_CAPABILITY_LIST, "HS Capability List", 1, 0, 0, qi); break; + case HS20_STYPE_WAN_METRICS: + set_anqp_req(ANQP_REQ_WAN_METRICS, "WAN Metrics", + hapd->conf->hs20_wan_metrics != NULL, + 0, 0, qi); + break; case HS20_STYPE_CONNECTION_CAPABILITY: set_anqp_req(ANQP_REQ_CONNECTION_CAPABILITY, "Connection Capability", diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h index e6e373995..390252528 100644 --- a/src/ap/gas_serv.h +++ b/src/ap/gas_serv.h @@ -25,6 +25,8 @@ (1 << (ANQP_DOMAIN_NAME - ANQP_QUERY_LIST)) #define ANQP_REQ_HS_CAPABILITY_LIST \ (0x10000 << HS20_STYPE_CAPABILITY_LIST) +#define ANQP_REQ_WAN_METRICS \ + (0x10000 << HS20_STYPE_WAN_METRICS) #define ANQP_REQ_CONNECTION_CAPABILITY \ (0x10000 << HS20_STYPE_CONNECTION_CAPABILITY) #define ANQP_REQ_OPERATING_CLASS \