P2P: Allow P2P client to specify preferred group channel
When re-invoking a persistent group in P2P client role, the new pref=<MHz> parameter can now be used with the p2p_invite command to indicate a preferred operating frequency. Unlike the older freq=<MHz> parameter, this leaves GO an option to select another channel (from our supported channels) if the GO cannot accept the channel. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
5de4b72177
commit
f5877af01e
7 changed files with 34 additions and 11 deletions
|
@ -92,6 +92,7 @@ struct p2p_device {
|
||||||
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
#define P2P_DEV_REPORTED_ONCE BIT(15)
|
||||||
#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
|
#define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
|
||||||
#define P2P_DEV_PD_BEFORE_GO_NEG BIT(17)
|
#define P2P_DEV_PD_BEFORE_GO_NEG BIT(17)
|
||||||
|
#define P2P_DEV_NO_PREF_CHAN BIT(18)
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
|
|
||||||
int status; /* enum p2p_status_code */
|
int status; /* enum p2p_status_code */
|
||||||
|
|
|
@ -62,8 +62,11 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
|
||||||
p2p->client_timeout);
|
p2p->client_timeout);
|
||||||
p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
|
p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
|
||||||
P2P_INVITATION_FLAGS_TYPE : 0);
|
P2P_INVITATION_FLAGS_TYPE : 0);
|
||||||
|
if (p2p->inv_role != P2P_INVITE_ROLE_CLIENT ||
|
||||||
|
!(peer->flags & P2P_DEV_NO_PREF_CHAN))
|
||||||
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
|
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
|
||||||
p2p->op_reg_class, p2p->op_channel);
|
p2p->op_reg_class,
|
||||||
|
p2p->op_channel);
|
||||||
if (p2p->inv_bssid_set)
|
if (p2p->inv_bssid_set)
|
||||||
p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
|
p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
|
||||||
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
|
p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
|
||||||
|
@ -564,6 +567,12 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
|
||||||
if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
|
if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (persistent_group && role == P2P_INVITE_ROLE_CLIENT && !force_freq &&
|
||||||
|
!pref_freq)
|
||||||
|
dev->flags |= P2P_DEV_NO_PREF_CHAN;
|
||||||
|
else
|
||||||
|
dev->flags &= ~P2P_DEV_NO_PREF_CHAN;
|
||||||
|
|
||||||
if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
|
if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
|
||||||
if (!(dev->info.dev_capab &
|
if (!(dev->info.dev_capab &
|
||||||
P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
|
P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
|
||||||
|
|
|
@ -365,7 +365,7 @@ Remove all local services from internal SD query processing.
|
||||||
Invitation
|
Invitation
|
||||||
|
|
||||||
p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
|
p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
|
||||||
[go_dev_addr=address] [freq=<freq in MHz>] [ht40]
|
[go_dev_addr=address] [freq=<freq in MHz>] [ht40] [pref=<MHz>]
|
||||||
|
|
||||||
Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
|
Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
|
||||||
persistent group (e.g., persistent=4). If the peer device is the GO of
|
persistent group (e.g., persistent=4). If the peer device is the GO of
|
||||||
|
@ -374,7 +374,11 @@ used to specify which device to invite. go_dev_addr parameter can be
|
||||||
used to override the GO device address for Invitation Request should
|
used to override the GO device address for Invitation Request should
|
||||||
it be not known for some reason (this should not be needed in most
|
it be not known for some reason (this should not be needed in most
|
||||||
cases). When reinvoking a persistent group, the GO device can specify
|
cases). When reinvoking a persistent group, the GO device can specify
|
||||||
the frequency for the group with the freq parameter.
|
the frequency for the group with the freq parameter. When reinvoking a
|
||||||
|
persistent group, the P2P client device can use freq parameter to force
|
||||||
|
a specific operating channel (or invitation failure if GO rejects that)
|
||||||
|
or pref parameter to request a specific channel (while allowing GO to
|
||||||
|
select to use another channel, if needed).
|
||||||
|
|
||||||
Group Operations
|
Group Operations
|
||||||
|
|
||||||
|
|
|
@ -3969,7 +3969,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
int id;
|
int id;
|
||||||
struct wpa_ssid *ssid;
|
struct wpa_ssid *ssid;
|
||||||
u8 *_peer = NULL, peer[ETH_ALEN];
|
u8 *_peer = NULL, peer[ETH_ALEN];
|
||||||
int freq = 0;
|
int freq = 0, pref_freq = 0;
|
||||||
int ht40;
|
int ht40;
|
||||||
|
|
||||||
id = atoi(cmd);
|
id = atoi(cmd);
|
||||||
|
@ -3996,9 +3996,17 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos = os_strstr(cmd, " pref=");
|
||||||
|
if (pos) {
|
||||||
|
pos += 6;
|
||||||
|
pref_freq = atoi(pos);
|
||||||
|
if (pref_freq <= 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
|
ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
|
||||||
|
|
||||||
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40);
|
return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, pref_freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -630,7 +630,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
|
||||||
if (ssid == NULL || ssid->disabled != 2)
|
if (ssid == NULL || ssid->disabled != 2)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0) < 0) {
|
if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0) < 0)
|
||||||
|
{
|
||||||
reply = wpas_dbus_error_unknown_error(
|
reply = wpas_dbus_error_unknown_error(
|
||||||
message,
|
message,
|
||||||
"Failed to reinvoke a persistent group");
|
"Failed to reinvoke a persistent group");
|
||||||
|
|
|
@ -3585,7 +3585,7 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
|
||||||
"(%u MHz) not available for P2P - try to use "
|
"(%u MHz) not available for P2P - try to use "
|
||||||
"another channel", *oper_freq);
|
"another channel", *oper_freq);
|
||||||
*force_freq = 0;
|
*force_freq = 0;
|
||||||
} else if (*oper_freq > 0 &&
|
} else if (*oper_freq > 0 && *pref_freq == 0 &&
|
||||||
(wpa_s->drv_flags &
|
(wpa_s->drv_flags &
|
||||||
WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
|
WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
|
||||||
wpa_printf(MSG_DEBUG, "P2P: Trying to prefer the channel we "
|
wpa_printf(MSG_DEBUG, "P2P: Trying to prefer the channel we "
|
||||||
|
@ -4583,11 +4583,11 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
|
||||||
/* Invite to reinvoke a persistent group */
|
/* Invite to reinvoke a persistent group */
|
||||||
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
|
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
|
||||||
int ht40)
|
int ht40, int pref_freq)
|
||||||
{
|
{
|
||||||
enum p2p_invite_role role;
|
enum p2p_invite_role role;
|
||||||
u8 *bssid = NULL, bssid_buf[ETH_ALEN];
|
u8 *bssid = NULL, bssid_buf[ETH_ALEN];
|
||||||
int force_freq = 0, pref_freq = 0, oper_freq = 0;
|
int force_freq = 0, oper_freq = 0;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
wpa_s->p2p_persistent_go_freq = freq;
|
wpa_s->p2p_persistent_go_freq = freq;
|
||||||
|
|
|
@ -105,7 +105,7 @@ int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
|
||||||
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
|
int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
|
||||||
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
|
||||||
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
|
struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
|
||||||
int ht40);
|
int ht40, int pref_freq);
|
||||||
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
|
int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
|
||||||
const u8 *peer_addr, const u8 *go_dev_addr);
|
const u8 *peer_addr, const u8 *go_dev_addr);
|
||||||
void wpas_p2p_completed(struct wpa_supplicant *wpa_s);
|
void wpas_p2p_completed(struct wpa_supplicant *wpa_s);
|
||||||
|
|
Loading…
Reference in a new issue