From 59fa205388aa1aa844c707e46e967e39cbdd0aba Mon Sep 17 00:00:00 2001 From: Purushottam Kushwaha Date: Fri, 28 Dec 2018 18:12:00 +0530 Subject: [PATCH] P2P: Allow the avoid channels for P2P discovery/negotiation The avoid channels are notified through QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY allow minimal traffic, so enhance the P2P behavior accordingly by considering these avoid frequencies for P2P discovery/negotiation as long as they are not in disallowed frequencies list. Additionally, do not return failure when none of social channels are available as operation channel, rather, mark the op_channel/op_reg_class to 0 as this would anyway get selected during the group formation in p2p_prepare_channel. Signed-off-by: Jouni Malinen --- src/p2p/p2p.c | 10 +++++++--- src/p2p/p2p.h | 6 +++++- src/p2p/p2p_i.h | 4 +++- src/p2p/p2p_invitation.c | 2 +- src/p2p/p2p_utils.c | 23 ++++++++++++++++++----- wpa_supplicant/p2p_supplicant.c | 15 +++++++++++---- 6 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index b4660c4f9..19fa7b78b 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1470,7 +1470,8 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) p2p->op_channel = p2p->cfg->op_channel; } else if (p2p_channel_random_social(&p2p->cfg->channels, &p2p->op_reg_class, - &p2p->op_channel) == 0) { + &p2p->op_channel, + NULL, NULL) == 0) { p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference", p2p->op_reg_class, p2p->op_channel); } else { @@ -4764,9 +4765,12 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled) int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, - u8 *op_channel) + u8 *op_channel, + struct wpa_freq_range_list *avoid_list, + struct wpa_freq_range_list *disallow_list) { - return p2p_channel_random_social(&p2p->channels, op_class, op_channel); + return p2p_channel_random_social(&p2p->channels, op_class, op_channel, + avoid_list, disallow_list); } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index dd2c25d34..f2969ee13 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -2010,6 +2010,8 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); * @p2p: P2P config * @op_class: Selected operating class * @op_channel: Selected social channel + * @avoid_list: Channel ranges to try to avoid or %NULL + * @disallow_list: Channel ranges to discard or %NULL * Returns: 0 on success, -1 on failure * * This function is used before p2p_init is called. A random social channel @@ -2017,7 +2019,9 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); * returned on success. */ int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, - u8 *op_channel); + u8 *op_channel, + struct wpa_freq_range_list *avoid_list, + struct wpa_freq_range_list *disallow_list); int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 6a4d751c0..d2c55c997 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -707,7 +707,9 @@ void p2p_channels_dump(struct p2p_data *p2p, const char *title, int p2p_channel_select(struct p2p_channels *chans, const int *classes, u8 *op_class, u8 *op_channel); int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, - u8 *op_channel); + u8 *op_channel, + struct wpa_freq_range_list *avoid_list, + struct wpa_freq_range_list *disallow_list); /* p2p_parse.c */ void p2p_copy_filter_devname(char *dst, size_t dst_len, diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index bbba001a7..77d662a47 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -488,7 +488,7 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, if (*msg.status == P2P_SC_FAIL_NO_COMMON_CHANNELS && p2p->retry_invite_req && p2p_channel_random_social(&p2p->cfg->channels, &p2p->op_reg_class, - &p2p->op_channel) == 0) { + &p2p->op_channel, NULL, NULL) == 0) { p2p->retry_invite_req = 0; p2p->cfg->send_action_done(p2p->cfg->cb_ctx); p2p->cfg->stop_listen(p2p->cfg->cb_ctx); diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index 2e2aa8ad0..1a62a44a2 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -413,17 +413,30 @@ int p2p_channel_select(struct p2p_channels *chans, const int *classes, int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, - u8 *op_channel) + u8 *op_channel, + struct wpa_freq_range_list *avoid_list, + struct wpa_freq_range_list *disallow_list) { u8 chan[4]; unsigned int num_channels = 0; - /* Try to find available social channels from 2.4 GHz */ - if (p2p_channels_includes(chans, 81, 1)) + /* Try to find available social channels from 2.4 GHz. + * If the avoid_list includes any of the 2.4 GHz social channels, that + * channel is not allowed by p2p_channels_includes() rules. However, it + * is assumed to allow minimal traffic for P2P negotiation, so allow it + * here for social channel selection unless explicitly disallowed in the + * disallow_list. */ + if (p2p_channels_includes(chans, 81, 1) || + (freq_range_list_includes(avoid_list, 2412) && + !freq_range_list_includes(disallow_list, 2412))) chan[num_channels++] = 1; - if (p2p_channels_includes(chans, 81, 6)) + if (p2p_channels_includes(chans, 81, 6) || + (freq_range_list_includes(avoid_list, 2437) && + !freq_range_list_includes(disallow_list, 2437))) chan[num_channels++] = 6; - if (p2p_channels_includes(chans, 81, 11)) + if (p2p_channels_includes(chans, 81, 11) || + (freq_range_list_includes(avoid_list, 2462) && + !freq_range_list_includes(disallow_list, 2462))) chan[num_channels++] = 11; /* Try to find available social channels from 60 GHz */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 848299d54..e265128b7 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4498,7 +4498,10 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) * channel. */ if (p2p_config_get_random_social(&p2p, &p2p.reg_class, - &p2p.channel) != 0) { + &p2p.channel, + &global->p2p_go_avoid_freq, + &global->p2p_disallow_freq) != + 0) { wpa_printf(MSG_INFO, "P2P: No social channels supported by the driver - do not enable P2P"); return 0; @@ -4523,10 +4526,14 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) * other preference is indicated. */ if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class, - &p2p.op_channel) != 0) { - wpa_printf(MSG_ERROR, + &p2p.op_channel, NULL, + NULL) != 0) { + wpa_printf(MSG_INFO, "P2P: Failed to select random social channel as operation channel"); - return -1; + p2p.op_reg_class = 0; + p2p.op_channel = 0; + /* This will be overridden during group setup in + * p2p_prepare_channel(), so allow setup to continue. */ } p2p.cfg_op_channel = 0; wpa_printf(MSG_DEBUG, "P2P: Random operating channel: "