Browse Source

P2P: Delay send_action call if p2p_scan is in progress

In order to avoid confusing the driver with a new remain-on-channel
request, delay sending of a new Action frame if the driver indicates
Action frame RX diromg a scan.
Jouni Malinen 14 years ago
parent
commit
3f9285ff19
7 changed files with 107 additions and 64 deletions
  1. 56 8
      src/p2p/p2p.c
  2. 6 9
      src/p2p/p2p_dev_disc.c
  3. 8 13
      src/p2p/p2p_go_neg.c
  4. 14 0
      src/p2p/p2p_i.h
  5. 6 9
      src/p2p/p2p_invitation.c
  6. 6 9
      src/p2p/p2p_pd.c
  7. 11 16
      src/p2p/p2p_sd.c

+ 56 - 8
src/p2p/p2p.c

@@ -691,6 +691,25 @@ static int p2p_run_after_scan(struct p2p_data *p2p)
 	struct p2p_device *dev;
 	enum p2p_after_scan op;
 
+	if (p2p->after_scan_tx) {
+		int ret;
+		/* TODO: schedule p2p_run_after_scan to be called from TX
+		 * status callback(?) */
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Send pending "
+			"Action frame at p2p_scan completion");
+		ret = p2p->cfg->send_action(p2p->cfg->cb_ctx,
+					    p2p->after_scan_tx->freq,
+					    p2p->after_scan_tx->dst,
+					    p2p->after_scan_tx->src,
+					    p2p->after_scan_tx->bssid,
+					    (u8 *) (p2p->after_scan_tx + 1),
+					    p2p->after_scan_tx->len,
+					    p2p->after_scan_tx->wait_time);
+		os_free(p2p->after_scan_tx);
+		p2p->after_scan_tx = NULL;
+		return 1;
+	}
+
 	op = p2p->start_after_scan;
 	p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING;
 	switch (op) {
@@ -1831,6 +1850,7 @@ void p2p_deinit(struct p2p_data *p2p)
 	os_free(p2p->cfg->dev_name);
 	os_free(p2p->groups);
 	wpabuf_free(p2p->sd_resp);
+	os_free(p2p->after_scan_tx);
 	os_free(p2p);
 }
 
@@ -2675,11 +2695,9 @@ int p2p_presence_req(struct p2p_data *p2p, const u8 *go_interface_addr,
 		return -1;
 
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, go_interface_addr,
-				  own_interface_addr,
-				  go_interface_addr,
-				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
-	{
+	if (p2p_send_action(p2p, freq, go_interface_addr, own_interface_addr,
+			    go_interface_addr,
+			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}
@@ -2776,9 +2794,8 @@ fail:
 		return;
 
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, rx_freq, sa, da, da,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0) {
+	if (p2p_send_action(p2p, rx_freq, sa, da, da,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}
@@ -3062,3 +3079,34 @@ void p2p_update_channel_list(struct p2p_data *p2p, struct p2p_channels *chan)
 	wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Update channel list");
 	os_memcpy(&p2p->cfg->channels, chan, sizeof(struct p2p_channels));
 }
+
+
+int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
+		    const u8 *src, const u8 *bssid, const u8 *buf,
+		    size_t len, unsigned int wait_time)
+{
+	if (p2p->p2p_scan_running) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Delay Action "
+			"frame TX until p2p_scan completes");
+		if (p2p->after_scan_tx) {
+			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Dropped "
+				"previous pending Action frame TX");
+			os_free(p2p->after_scan_tx);
+		}
+		p2p->after_scan_tx = os_malloc(sizeof(*p2p->after_scan_tx) +
+					       len);
+		if (p2p->after_scan_tx == NULL)
+			return -1;
+		p2p->after_scan_tx->freq = freq;
+		os_memcpy(p2p->after_scan_tx->dst, dst, ETH_ALEN);
+		os_memcpy(p2p->after_scan_tx->src, src, ETH_ALEN);
+		os_memcpy(p2p->after_scan_tx->bssid, bssid, ETH_ALEN);
+		p2p->after_scan_tx->len = len;
+		p2p->after_scan_tx->wait_time = wait_time;
+		os_memcpy(p2p->after_scan_tx + 1, buf, len);
+		return 0;
+	}
+
+	return p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, dst, src, bssid,
+				     buf, len, wait_time);
+}

+ 6 - 9
src/p2p/p2p_dev_disc.c

@@ -99,11 +99,9 @@ int p2p_send_dev_disc_req(struct p2p_data *p2p, struct p2p_device *dev)
 	os_memcpy(p2p->pending_client_disc_addr, dev->p2p_device_addr,
 		  ETH_ALEN);
 	p2p->pending_action_state = P2P_PENDING_DEV_DISC_REQUEST;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, dev->oper_freq,
-				  go->p2p_device_addr, p2p->cfg->dev_addr,
-				  go->p2p_device_addr,
-				  wpabuf_head(req), wpabuf_len(req), 1000) < 0)
-	{
+	if (p2p_send_action(p2p, dev->oper_freq, go->p2p_device_addr,
+			    p2p->cfg->dev_addr, go->p2p_device_addr,
+			    wpabuf_head(req), wpabuf_len(req), 1000) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		wpabuf_free(req);
@@ -160,10 +158,9 @@ static void p2p_send_dev_disc_resp(struct p2p_data *p2p, u8 dialog_token,
 		MAC2STR(addr), status, freq);
 
 	p2p->pending_action_state = P2P_PENDING_DEV_DISC_RESPONSE;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, addr,
-				  p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0) {
+	if (p2p_send_action(p2p, freq, addr, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}

+ 8 - 13
src/p2p/p2p_go_neg.c

@@ -209,11 +209,9 @@ int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev)
 	p2p->pending_action_state = P2P_PENDING_GO_NEG_REQUEST;
 	p2p->go_neg_peer = dev;
 	dev->flags |= P2P_DEV_WAIT_GO_NEG_RESPONSE;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dev->p2p_device_addr, p2p->cfg->dev_addr,
-				  dev->p2p_device_addr,
-				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
-	{
+	if (p2p_send_action(p2p, freq, dev->p2p_device_addr,
+			    p2p->cfg->dev_addr, dev->p2p_device_addr,
+			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		/* Use P2P find to recover and retry */
@@ -616,10 +614,9 @@ fail:
 	} else
 		p2p->pending_action_state =
 			P2P_PENDING_GO_NEG_RESPONSE_FAILURE;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, sa,
-				  p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0) {
+	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}
@@ -982,10 +979,8 @@ fail:
 		freq = rx_freq;
 	else
 		freq = dev->listen_freq;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, sa,
-				  p2p->cfg->dev_addr, sa,
-				  wpabuf_head(conf), wpabuf_len(conf), 200) <
-	    0) {
+	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, sa,
+			    wpabuf_head(conf), wpabuf_len(conf), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		p2p_go_neg_failed(p2p, dev, -1);

+ 14 - 0
src/p2p/p2p_i.h

@@ -113,6 +113,16 @@ struct p2p_sd_query {
 	struct wpabuf *tlvs;
 };
 
+struct p2p_pending_action_tx {
+	unsigned int freq;
+	u8 dst[ETH_ALEN];
+	u8 src[ETH_ALEN];
+	u8 bssid[ETH_ALEN];
+	size_t len;
+	unsigned int wait_time;
+	/* Followed by len octets of the frame */
+};
+
 /**
  * struct p2p_data - P2P module data (internal to P2P module)
  */
@@ -351,6 +361,7 @@ struct p2p_data {
 		P2P_AFTER_SCAN_CONNECT
 	} start_after_scan;
 	u8 after_scan_peer[ETH_ALEN];
+	struct p2p_pending_action_tx *after_scan_tx;
 
 	struct p2p_group **groups;
 	size_t num_groups;
@@ -597,5 +608,8 @@ int dev_type_list_match(const u8 *dev_type, const u8 *req_dev_type[],
 			size_t num_req_dev_type);
 struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p);
 void p2p_build_ssid(struct p2p_data *p2p, u8 *ssid, size_t *ssid_len);
+int p2p_send_action(struct p2p_data *p2p, unsigned int freq, const u8 *dst,
+		    const u8 *src, const u8 *bssid, const u8 *buf,
+		    size_t len, unsigned int wait_time);
 
 #endif /* P2P_I_H */

+ 6 - 9
src/p2p/p2p_invitation.c

@@ -271,10 +271,9 @@ fail:
 	p2p->inv_op_freq = op_freq;
 
 	p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, sa,
-				  p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0) {
+	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}
@@ -357,11 +356,9 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
 	p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST;
 	p2p->invite_peer = dev;
 	dev->invitation_reqs++;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dev->p2p_device_addr, p2p->cfg->dev_addr,
-				  dev->p2p_device_addr,
-				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
-	{
+	if (p2p_send_action(p2p, freq, dev->p2p_device_addr,
+			    p2p->cfg->dev_addr, dev->p2p_device_addr,
+			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		/* Use P2P find to recover and retry */

+ 6 - 9
src/p2p/p2p_pd.c

@@ -165,10 +165,9 @@ out:
 		return;
 	}
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq, sa,
-				  p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0) {
+	if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 	}
@@ -292,11 +291,9 @@ int p2p_send_prov_disc_req(struct p2p_data *p2p, struct p2p_device *dev,
 		return -1;
 
 	p2p->pending_action_state = P2P_PENDING_PD;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dev->p2p_device_addr, p2p->cfg->dev_addr,
-				  dev->p2p_device_addr,
-				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
-	{
+	if (p2p_send_action(p2p->cfg->cb_ctx, freq, dev->p2p_device_addr,
+			    p2p->cfg->dev_addr, dev->p2p_device_addr,
+			    wpabuf_head(req), wpabuf_len(req), 200) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		wpabuf_free(req);

+ 11 - 16
src/p2p/p2p_sd.c

@@ -149,9 +149,8 @@ static void p2p_send_gas_comeback_req(struct p2p_data *p2p, const u8 *dst,
 		return;
 
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dst, p2p->cfg->dev_addr, dst,
-				  wpabuf_head(req), wpabuf_len(req), 200) < 0)
+	if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, dst,
+			    wpabuf_head(req), wpabuf_len(req), 200) < 0)
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 
@@ -286,11 +285,9 @@ int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev)
 	p2p->sd_query = query;
 	p2p->pending_action_state = P2P_PENDING_SD;
 
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dev->p2p_device_addr, p2p->cfg->dev_addr,
-				  dev->p2p_device_addr,
-				  wpabuf_head(req), wpabuf_len(req), 5000) < 0)
-	{
+	if (p2p_send_action(p2p->cfg->cb_ctx, freq, dev->p2p_device_addr,
+			    p2p->cfg->dev_addr, dev->p2p_device_addr,
+			    wpabuf_head(req), wpabuf_len(req), 5000) < 0) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 		ret = -1;
@@ -452,10 +449,9 @@ void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst,
 		return;
 
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, freq,
-				  dst, p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0)
+	if (p2p_send_action(p2p->cfg->cb_ctx, freq, dst, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0)
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");
 
@@ -691,10 +687,9 @@ void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa,
 	}
 
 	p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	if (p2p->cfg->send_action(p2p->cfg->cb_ctx, rx_freq,
-				  sa, p2p->cfg->dev_addr, p2p->cfg->dev_addr,
-				  wpabuf_head(resp), wpabuf_len(resp), 200) <
-	    0)
+	if (p2p_send_action(p2p, rx_freq, sa, p2p->cfg->dev_addr,
+			    p2p->cfg->dev_addr,
+			    wpabuf_head(resp), wpabuf_len(resp), 200) < 0)
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Failed to send Action frame");