Use radio work for GAS requests
Avoid concurrent GAS operations with any other exclusive use of the radio by using the radio work queuing mechanism. This replaces some of the earlier constraints on concurrent operations with the more generic wpa_radio work concept. Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
e05e130837
commit
b9e6d7001d
3 changed files with 46 additions and 29 deletions
|
@ -2,6 +2,7 @@
|
||||||
* Generic advertisement service (GAS) query
|
* Generic advertisement service (GAS) query
|
||||||
* Copyright (c) 2009, Atheros Communications
|
* Copyright (c) 2009, Atheros Communications
|
||||||
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
* Copyright (c) 2011-2013, Qualcomm Atheros, Inc.
|
||||||
|
* Copyright (c) 2011-2014, Jouni Malinen <j@w1.fi>
|
||||||
*
|
*
|
||||||
* This software may be distributed under the terms of the BSD license.
|
* This software may be distributed under the terms of the BSD license.
|
||||||
* See README for more details.
|
* See README for more details.
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
*/
|
*/
|
||||||
struct gas_query_pending {
|
struct gas_query_pending {
|
||||||
struct dl_list list;
|
struct dl_list list;
|
||||||
|
struct gas_query *gas;
|
||||||
u8 addr[ETH_ALEN];
|
u8 addr[ETH_ALEN];
|
||||||
u8 dialog_token;
|
u8 dialog_token;
|
||||||
u8 next_frag_id;
|
u8 next_frag_id;
|
||||||
|
@ -55,6 +57,7 @@ struct gas_query {
|
||||||
struct wpa_supplicant *wpa_s;
|
struct wpa_supplicant *wpa_s;
|
||||||
struct dl_list pending; /* struct gas_query_pending */
|
struct dl_list pending; /* struct gas_query_pending */
|
||||||
struct gas_query_pending *current;
|
struct gas_query_pending *current;
|
||||||
|
struct wpa_radio_work *work;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,6 +109,25 @@ static const char * gas_result_txt(enum gas_query_result result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gas_query_free(struct gas_query_pending *query, int del_list)
|
||||||
|
{
|
||||||
|
struct gas_query *gas = query->gas;
|
||||||
|
|
||||||
|
if (del_list)
|
||||||
|
dl_list_del(&query->list);
|
||||||
|
|
||||||
|
if (gas->work && gas->work->ctx == query) {
|
||||||
|
radio_work_done(gas->work);
|
||||||
|
gas->work = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wpabuf_free(query->req);
|
||||||
|
wpabuf_free(query->adv_proto);
|
||||||
|
wpabuf_free(query->resp);
|
||||||
|
os_free(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void gas_query_done(struct gas_query *gas,
|
static void gas_query_done(struct gas_query *gas,
|
||||||
struct gas_query_pending *query,
|
struct gas_query_pending *query,
|
||||||
enum gas_query_result result)
|
enum gas_query_result result)
|
||||||
|
@ -124,10 +146,7 @@ static void gas_query_done(struct gas_query *gas,
|
||||||
dl_list_del(&query->list);
|
dl_list_del(&query->list);
|
||||||
query->cb(query->ctx, query->addr, query->dialog_token, result,
|
query->cb(query->ctx, query->addr, query->dialog_token, result,
|
||||||
query->adv_proto, query->resp, query->status_code);
|
query->adv_proto, query->resp, query->status_code);
|
||||||
wpabuf_free(query->req);
|
gas_query_free(query, 0);
|
||||||
wpabuf_free(query->adv_proto);
|
|
||||||
wpabuf_free(query->resp);
|
|
||||||
os_free(query);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -516,11 +535,8 @@ static void gas_service_timeout(void *eloop_data, void *user_ctx)
|
||||||
int conn;
|
int conn;
|
||||||
|
|
||||||
conn = wpas_wpa_is_in_progress(wpa_s, 1);
|
conn = wpas_wpa_is_in_progress(wpa_s, 1);
|
||||||
if (conn || wpa_s->scanning || gas->current) {
|
if (conn) {
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while another operation is in progress:%s%s%s",
|
wpa_printf(MSG_DEBUG, "GAS: Delaying GAS query Tx while connection operation is in progress");
|
||||||
conn ? " connection" : "",
|
|
||||||
wpa_s->scanning ? " scanning" : "",
|
|
||||||
gas->current ? " gas_query" : "");
|
|
||||||
eloop_register_timeout(
|
eloop_register_timeout(
|
||||||
GAS_SERVICE_RETRY_PERIOD_MS / 1000,
|
GAS_SERVICE_RETRY_PERIOD_MS / 1000,
|
||||||
(GAS_SERVICE_RETRY_PERIOD_MS % 1000) * 1000,
|
(GAS_SERVICE_RETRY_PERIOD_MS % 1000) * 1000,
|
||||||
|
@ -531,9 +547,7 @@ static void gas_service_timeout(void *eloop_data, void *user_ctx)
|
||||||
if (gas_query_tx(gas, query, query->req) < 0) {
|
if (gas_query_tx(gas, query, query->req) < 0) {
|
||||||
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
|
wpa_printf(MSG_DEBUG, "GAS: Failed to send Action frame to "
|
||||||
MACSTR, MAC2STR(query->addr));
|
MACSTR, MAC2STR(query->addr));
|
||||||
dl_list_del(&query->list);
|
gas_query_free(query, 1);
|
||||||
wpabuf_free(query->req);
|
|
||||||
os_free(query);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gas->current = query;
|
gas->current = query;
|
||||||
|
@ -559,6 +573,20 @@ static int gas_query_dialog_token_available(struct gas_query *gas,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void gas_query_start_cb(struct wpa_radio_work *work, int deinit)
|
||||||
|
{
|
||||||
|
struct gas_query_pending *query = work->ctx;
|
||||||
|
|
||||||
|
if (deinit) {
|
||||||
|
gas_query_free(query, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
query->gas->work = work;
|
||||||
|
gas_service_timeout(query->gas, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gas_query_req - Request a GAS query
|
* gas_query_req - Request a GAS query
|
||||||
* @gas: GAS query data from gas_query_init()
|
* @gas: GAS query data from gas_query_init()
|
||||||
|
@ -599,6 +627,7 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
|
||||||
if (query == NULL)
|
if (query == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
query->gas = gas;
|
||||||
os_memcpy(query->addr, dst, ETH_ALEN);
|
os_memcpy(query->addr, dst, ETH_ALEN);
|
||||||
query->dialog_token = dialog_token;
|
query->dialog_token = dialog_token;
|
||||||
query->freq = freq;
|
query->freq = freq;
|
||||||
|
@ -613,7 +642,11 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq,
|
||||||
" dialog_token=%u freq=%d",
|
" dialog_token=%u freq=%d",
|
||||||
MAC2STR(query->addr), query->dialog_token, query->freq);
|
MAC2STR(query->addr), query->dialog_token, query->freq);
|
||||||
|
|
||||||
eloop_register_timeout(0, 0, gas_service_timeout, gas, query);
|
if (radio_add_work(gas->wpa_s, freq, "gas-query", 0, gas_query_start_cb,
|
||||||
|
query) < 0) {
|
||||||
|
gas_query_free(query, 1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return dialog_token;
|
return dialog_token;
|
||||||
}
|
}
|
||||||
|
@ -634,9 +667,3 @@ void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token)
|
||||||
gas_query_done(gas, query, GAS_QUERY_CANCELLED);
|
gas_query_done(gas, query, GAS_QUERY_CANCELLED);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int gas_query_in_progress(struct gas_query *gas)
|
|
||||||
{
|
|
||||||
return gas->current != NULL;
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s);
|
||||||
void gas_query_deinit(struct gas_query *gas);
|
void gas_query_deinit(struct gas_query *gas);
|
||||||
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
|
int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa,
|
||||||
const u8 *bssid, const u8 *data, size_t len, int freq);
|
const u8 *bssid, const u8 *data, size_t len, int freq);
|
||||||
int gas_query_in_progress(struct gas_query *gas);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum gas_query_result - GAS query result
|
* enum gas_query_result - GAS query result
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "hs20_supplicant.h"
|
#include "hs20_supplicant.h"
|
||||||
#include "notify.h"
|
#include "notify.h"
|
||||||
#include "bss.h"
|
#include "bss.h"
|
||||||
#include "gas_query.h"
|
|
||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -582,14 +581,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
#ifdef CONFIG_GAS
|
|
||||||
if (gas_query_in_progress(wpa_s->gas)) {
|
|
||||||
wpa_dbg(wpa_s, MSG_DEBUG, "Delay scan while GAS query is in progress");
|
|
||||||
wpa_supplicant_req_scan(wpa_s, 1, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_GAS */
|
|
||||||
|
|
||||||
if (wpa_s->conf->ap_scan == 2)
|
if (wpa_s->conf->ap_scan == 2)
|
||||||
max_ssids = 1;
|
max_ssids = 1;
|
||||||
else {
|
else {
|
||||||
|
|
Loading…
Reference in a new issue