P2P: Allow discoverable interval for p2p_find to be configured

The new P2P_SET parameter disc_int can now be used to configure
discoverable interval for p2p_find operations. The format of the command
for setting the values is "P2P_SET disc_int <minDiscoverableInterval>
<maxDiscoverableInterval> <max TUs for discoverable interval>". The
first two parameters are given in units of 100 TUs (102.4 ms). The third
parameter can be used to further limit the interval into a specific TU
amount. If it is set to -1, no such additional limitation is enforced.
It should be noted that the P2P specification describes the random
Listen state interval to be in units of 100 TUs, so setting the max TU
value to anything else than -1 is not compliant with the specification
and should not be used in normal cases. The default parameters can be
set with "P2P_SET disc_int 1 3 -1".

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2012-10-30 15:12:04 +02:00 committed by Jouni Malinen
parent 23270cd8f5
commit 96beff11d1
5 changed files with 93 additions and 5 deletions

View file

@ -214,7 +214,7 @@ void p2p_go_neg_failed(struct p2p_data *p2p, struct p2p_device *peer,
} }
static void p2p_listen_in_find(struct p2p_data *p2p) static void p2p_listen_in_find(struct p2p_data *p2p, int dev_disc)
{ {
unsigned int r, tu; unsigned int r, tu;
int freq; int freq;
@ -235,6 +235,19 @@ static void p2p_listen_in_find(struct p2p_data *p2p)
os_get_random((u8 *) &r, sizeof(r)); os_get_random((u8 *) &r, sizeof(r));
tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) + tu = (r % ((p2p->max_disc_int - p2p->min_disc_int) + 1) +
p2p->min_disc_int) * 100; p2p->min_disc_int) * 100;
if (p2p->max_disc_tu >= 0 && tu > (unsigned int) p2p->max_disc_tu)
tu = p2p->max_disc_tu;
if (!dev_disc && tu < 100)
tu = 100; /* Need to wait in non-device discovery use cases */
if (p2p->cfg->max_listen && 1024 * tu / 1000 > p2p->cfg->max_listen)
tu = p2p->cfg->max_listen * 1000 / 1024;
if (tu == 0) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Skip listen state "
"since duration was 0 TU");
p2p_set_timeout(p2p, 0, 0);
return;
}
p2p->pending_listen_freq = freq; p2p->pending_listen_freq = freq;
p2p->pending_listen_sec = 0; p2p->pending_listen_sec = 0;
@ -2327,6 +2340,7 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg)
p2p->min_disc_int = 1; p2p->min_disc_int = 1;
p2p->max_disc_int = 3; p2p->max_disc_int = 3;
p2p->max_disc_tu = -1;
os_get_random(&p2p->next_tie_breaker, 1); os_get_random(&p2p->next_tie_breaker, 1);
p2p->next_tie_breaker &= 0x01; p2p->next_tie_breaker &= 0x01;
@ -2590,7 +2604,7 @@ void p2p_continue_find(struct p2p_data *p2p)
} }
} }
p2p_listen_in_find(p2p); p2p_listen_in_find(p2p, 1);
} }
@ -3060,7 +3074,7 @@ static void p2p_timeout_connect(struct p2p_data *p2p)
return; return;
} }
p2p_set_state(p2p, P2P_CONNECT_LISTEN); p2p_set_state(p2p, P2P_CONNECT_LISTEN);
p2p_listen_in_find(p2p); p2p_listen_in_find(p2p, 0);
} }
@ -3124,7 +3138,7 @@ static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p)
"P2P: Go to Listen state while waiting for the peer to become " "P2P: Go to Listen state while waiting for the peer to become "
"ready for GO Negotiation"); "ready for GO Negotiation");
p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT);
p2p_listen_in_find(p2p); p2p_listen_in_find(p2p, 0);
} }
@ -3192,7 +3206,7 @@ static void p2p_timeout_invite(struct p2p_data *p2p)
p2p_set_timeout(p2p, 0, 100000); p2p_set_timeout(p2p, 0, 100000);
return; return;
} }
p2p_listen_in_find(p2p); p2p_listen_in_find(p2p, 0);
} }
@ -4237,3 +4251,20 @@ int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
} }
#endif /* CONFIG_WIFI_DISPLAY */ #endif /* CONFIG_WIFI_DISPLAY */
int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
int max_disc_tu)
{
if (min_disc_int > max_disc_int || min_disc_int < 0 || max_disc_int < 0)
return -1;
p2p->min_disc_int = min_disc_int;
p2p->max_disc_int = max_disc_int;
p2p->max_disc_tu = max_disc_tu;
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Set discoverable interval: "
"min=%d max=%d max_tu=%d", min_disc_int, max_disc_int,
max_disc_tu);
return 0;
}

View file

@ -354,6 +354,11 @@ struct p2p_config {
*/ */
size_t ssid_postfix_len; size_t ssid_postfix_len;
/**
* max_listen - Maximum listen duration in ms
*/
unsigned int max_listen;
/** /**
* msg_ctx - Context to use with wpa_msg() calls * msg_ctx - Context to use with wpa_msg() calls
*/ */
@ -1739,4 +1744,25 @@ int p2p_set_wfd_coupled_sink_info(struct p2p_data *p2p,
const struct wpabuf *elem); const struct wpabuf *elem);
struct wpabuf * wifi_display_encaps(struct wpabuf *subelems); struct wpabuf * wifi_display_encaps(struct wpabuf *subelems);
/**
* p2p_set_disc_int - Set min/max discoverable interval for p2p_find
* @p2p: P2P module context from p2p_init()
* @min_disc_int: minDiscoverableInterval (in units of 100 TU); default 1
* @max_disc_int: maxDiscoverableInterval (in units of 100 TU); default 3
* @max_disc_tu: Maximum number of TUs (1.024 ms) for discoverable interval; or
* -1 not to limit
* Returns: 0 on success, or -1 on failure
*
* This function can be used to configure minDiscoverableInterval and
* maxDiscoverableInterval parameters for the Listen state during device
* discovery (p2p_find). A random number of 100 TU units is picked for each
* Listen state iteration from [min_disc_int,max_disc_int] range.
*
* max_disc_tu can be used to futher limit the discoverable duration. However,
* it should be noted that use of this parameter is not recommended since it
* would not be compliant with the P2P specification.
*/
int p2p_set_disc_int(struct p2p_data *p2p, int min_disc_int, int max_disc_int,
int max_disc_tu);
#endif /* P2P_H */ #endif /* P2P_H */

View file

@ -225,6 +225,11 @@ struct p2p_data {
*/ */
int max_disc_int; int max_disc_int;
/**
* max_disc_tu - Maximum number of TUs for discoverable interval
*/
int max_disc_tu;
/** /**
* devices - List of known P2P Device peers * devices - List of known P2P Device peers
*/ */

View file

@ -4223,6 +4223,30 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd)
if (os_strcmp(cmd, "disallow_freq") == 0) if (os_strcmp(cmd, "disallow_freq") == 0)
return p2p_ctrl_disallow_freq(wpa_s, param); return p2p_ctrl_disallow_freq(wpa_s, param);
if (os_strcmp(cmd, "disc_int") == 0) {
int min_disc_int, max_disc_int, max_disc_tu;
char *pos;
pos = param;
min_disc_int = atoi(pos);
pos = os_strchr(pos, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
max_disc_int = atoi(pos);
pos = os_strchr(pos, ' ');
if (pos == NULL)
return -1;
*pos++ = '\0';
max_disc_tu = atoi(pos);
return p2p_set_disc_int(wpa_s->global->p2p, min_disc_int,
max_disc_int, max_disc_tu);
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'",
cmd); cmd);

View file

@ -2760,6 +2760,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss; p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
p2p.max_listen = wpa_s->max_remain_on_chan;
global->p2p = p2p_init(&p2p); global->p2p = p2p_init(&p2p);
if (global->p2p == NULL) if (global->p2p == NULL)
return -1; return -1;