[PATCH 12/23] P2PS: Add channel policy to PD request

Ilan Peer ilan.peer at intel.com
Thu Sep 24 13:38:02 EDT 2015


Add operating channel selection and channel list processing
similar to that done when build GON request, i.e., consider the
currently used channels, configured channels etc.

P2PS introduces a flow where a responder needs to provide
channel data without being previously aware of the current
constraints, i.e., the channels currently in use by other
interfaces. To handle this, extend the get_group_capability()
callback to also handle channels selection aspects of
group capabilities.

Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
 src/p2p/p2p.c                   |  8 +++---
 src/p2p/p2p.h                   | 26 +++++++++++++++-----
 src/p2p/p2p_pd.c                | 54 +++++++++++++++++++++++------------------
 wpa_supplicant/p2p_supplicant.c | 24 ++++++++++++++++--
 4 files changed, 76 insertions(+), 36 deletions(-)

diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index 53527f4..a6002f7 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -1459,7 +1459,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
 
 
 /**
- * p2p_prepare_channel - Select operating channel for GO Negotiation
+ * p2p_prepare_channel - Select operating channel for GO Negotiation or P2PS PD
  * @p2p: P2P module context from p2p_init()
  * @dev: Selected peer device
  * @force_freq: Forced frequency in MHz or 0 if not forced
@@ -1468,9 +1468,9 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
  * Returns: 0 on success, -1 on failure (channel not supported for P2P)
  *
  * This function is used to do initial operating channel selection for GO
- * Negotiation prior to having received peer information. The selected channel
- * may be further optimized in p2p_reselect_channel() once the peer information
- * is available.
+ * Negotiation prior to having received peer information or for P2PS PD
+ * signalling. The selected channel may be further optimized in
+ * p2p_reselect_channel() once the peer information is available.
  */
 int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
 			unsigned int force_freq, unsigned int pref_freq, int go)
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index b4060be..8f7e19b 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -224,6 +224,16 @@ struct p2ps_provision {
 	u8 cpt_priority[P2PS_FEATURE_CAPAB_CPT_MAX + 1];
 
 	/**
+	 * force_freq - the only allowed channel frequency in MHz or 0.
+	 */
+	int force_freq;
+
+	/**
+	 * pref_freq - preferred operating frequency in MHz or 0.
+	 */
+	int pref_freq;
+
+	/**
 	 * info - Vendor defined extra Provisioning information
 	 */
 	char info[0];
@@ -1070,14 +1080,18 @@ struct p2p_config {
 
 	/**
 	 * p2ps_group_capability - Determine group capability
+	 * @incoming: peer requested roles, expressed with P2PS_SETUP* bitmap.
+	 * @role: local roles, expressed with P2PS_SETUP* bitmap.
+	 * @force_freq: variable for returning forced frequency for the group.
+	 * @pref_freq: variable for returning preferred frequency for the group.
+	 * Returns: P2PS_SETUP_* bitmap of group capability result.
 	 *
-	 * This function can be used to determine group capability based on
-	 * information from P2PS PD exchange and the current state of ongoing
-	 * groups and driver capabilities.
-	 *
-	 * P2PS_SETUP_* bitmap is used as the parameters and return value.
+	 * This function can be used to determine group capability and
+	 * frequencies based on information from P2PS PD exchange and the
+	 * current state of ongoing groups and driver capabilities.
 	 */
-	u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role);
+	u8 (*p2ps_group_capability)(void *ctx, u8 incoming, u8 role,
+				    int *force_freq, int *pref_freq);
 
 	/**
 	 * get_pref_freq_list - Get preferred frequency list for an interface
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index b96b125..d354f76 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -109,25 +109,18 @@ static void p2ps_add_pd_req_attrs(struct p2p_data *p2p, struct p2p_device *dev,
 			go_dev_addr, ssid, &ssid_len, intended_addr);
 	}
 
-	/* Add Operating Channel if conncap includes GO */
 	if (shared_group ||
-	    (prov->conncap & (P2PS_SETUP_GROUP_OWNER |
-			      P2PS_SETUP_NEW))) {
-		u8 tmp;
-
-		p2p_go_select_channel(p2p, dev, &tmp);
-
-		if (p2p->op_reg_class && p2p->op_channel)
-			p2p_buf_add_operating_channel(buf, p2p->cfg->country,
-						      p2p->op_reg_class,
-						      p2p->op_channel);
-		else
-			p2p_buf_add_operating_channel(buf, p2p->cfg->country,
-						      p2p->cfg->op_reg_class,
-						      p2p->cfg->op_channel);
-	}
+	    (prov->conncap & P2PS_SETUP_CLIENT) ||
+	    (prov->conncap & P2PS_SETUP_NEW))
+		p2p_buf_add_channel_list(buf, p2p->cfg->country,
+					 &p2p->channels);
 
-	p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->cfg->channels);
+	if ((shared_group && !is_zero_ether_addr(intended_addr)) ||
+	    (prov->conncap & P2PS_SETUP_GROUP_OWNER) ||
+	    (prov->conncap & P2PS_SETUP_NEW))
+		p2p_buf_add_operating_channel(buf, p2p->cfg->country,
+					      p2p->op_reg_class,
+					      p2p->op_channel);
 
 	if (prov->info[0])
 		p2p_buf_add_session_info(buf, prov->info);
@@ -345,7 +338,7 @@ static struct wpabuf * p2p_build_prov_disc_resp(struct p2p_data *p2p,
 		}
 
 		p2p_buf_add_channel_list(buf, p2p->cfg->country,
-					 &p2p->cfg->channels);
+					 &p2p->channels);
 
 		if (!persist && (status == P2P_SC_SUCCESS ||
 				 status == P2P_SC_SUCCESS_DEFERRED))
@@ -701,9 +694,14 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 	}
 
 	if (p2ps_adv) {
+		int forced_freq, pref_freq;
+
 		auto_accept = p2ps_adv->auto_accept;
 		conncap = p2p->cfg->p2ps_group_capability(
-			p2p->cfg->cb_ctx, conncap, auto_accept);
+			p2p->cfg->cb_ctx, conncap, auto_accept,
+			&forced_freq, &pref_freq);
+
+		p2p_prepare_channel(p2p, dev, forced_freq, pref_freq, 0);
 
 		p2p_dbg(p2p, "Conncap: local:%d remote:%d result:%d",
 			auto_accept, remote_conncap, conncap);
@@ -754,6 +752,8 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 			}
 
 			tmp = p2p->p2ps_prov;
+			tmp->force_freq = forced_freq;
+			tmp->pref_freq = pref_freq;
 			if (conncap) {
 				tmp->conncap = conncap;
 				tmp->status = P2P_SC_SUCCESS;
@@ -816,12 +816,9 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 
 	conncap = p2p->cfg->p2ps_group_capability(
 		p2p->cfg->cb_ctx, remote_conncap,
-		p2p->p2ps_prov->conncap);
-
-	p2p_dbg(p2p,
-		"Conncap: local:%d remote:%d result:%d",
 		p2p->p2ps_prov->conncap,
-		remote_conncap, conncap);
+		&p2p->p2ps_prov->force_freq,
+		&p2p->p2ps_prov->pref_freq);
 
 	resp_fcap.cpt = p2ps_own_preferred_cpt(
 		p2p->p2ps_prov->cpt_priority,
@@ -832,6 +829,11 @@ void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
 		p2p->p2ps_prov->cpt_mask,
 		req_fcap->cpt, resp_fcap.cpt);
 
+	p2p_prepare_channel(p2p, dev,
+			    p2p->p2ps_prov->force_freq,
+			    p2p->p2ps_prov->pref_freq,
+			    0);
+
 	/*
 	 * Ensure that if we asked for PIN originally,
 	 * our method is consistent with original
@@ -1466,6 +1468,10 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
 			"Building PD Request based on P2PS config method 0x%x status %d --> req_config_methods 0x%x",
 			p2p->p2ps_prov->method, p2p->p2ps_prov->status,
 			dev->req_config_methods);
+
+		if (p2p_prepare_channel(p2p, dev, p2p->p2ps_prov->force_freq,
+					p2p->p2ps_prov->pref_freq, 1) < 0)
+			return -1;
 	}
 
 	req = p2p_build_prov_disc_req(p2p, dev, join);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5b98b69..be71fce 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -117,6 +117,10 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
 			 int go);
 static int wpas_p2p_join_start(struct wpa_supplicant *wpa_s, int freq,
 			       const u8 *ssid, size_t ssid_len);
+static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
+				int *force_freq, int *pref_freq, int go,
+				unsigned int *pref_freq_list,
+				unsigned int *num_pref_freq);
 static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
 				   const u8 *ssid, size_t ssid_len);
 static void wpas_p2p_join_scan(void *eloop_ctx, void *timeout_ctx);
@@ -633,7 +637,8 @@ wpas_p2p_get_persistent_go(struct wpa_supplicant *wpa_s)
 }
 
 
-static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
+static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role,
+				int *force_freq, int *pref_freq)
 {
 	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_ssid *s;
@@ -645,6 +650,19 @@ static u8 p2ps_group_capability(void *ctx, u8 incoming, u8 role)
 
 	wpa_printf(MSG_DEBUG, "P2P: Conncap - in:%d role:%d", incoming, role);
 
+	if (force_freq && pref_freq) {
+		unsigned int pref_freq_list[P2P_MAX_PREF_CHANNELS], size;
+		*force_freq = 0;
+		*pref_freq = 0;
+
+		if (!wpas_p2p_setup_freqs(wpa_s, 0, force_freq, pref_freq, 0,
+					  pref_freq_list, &size))
+			wpas_p2p_set_own_freq_preference(wpa_s,
+							 *force_freq ?
+							 *force_freq :
+							 *pref_freq);
+	}
+
 	/*
 	 * For non-concurrent capable devices:
 	 * If persistent_go, then no new.
@@ -6188,7 +6206,9 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 	wpa_s->pending_pd_use = NORMAL_PD;
 	if (p2ps_prov && use == WPAS_P2P_PD_FOR_ASP) {
 		p2ps_prov->conncap = p2ps_group_capability(
-			wpa_s, P2PS_SETUP_NONE, p2ps_prov->role);
+			wpa_s, P2PS_SETUP_NONE, p2ps_prov->role,
+			&p2ps_prov->force_freq, &p2ps_prov->pref_freq);
+
 		wpa_printf(MSG_DEBUG,
 			   "P2P: %s conncap: %d - ASP parsed: %x %x %d %s",
 			   __func__, p2ps_prov->conncap,
-- 
1.9.1



More information about the HostAP mailing list