All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] mac80211: notify driver about auth/assoc
@ 2011-05-13 13:14 Johannes Berg
  2011-06-22 15:52 ` Johannes Berg
  0 siblings, 1 reply; 2+ messages in thread
From: Johannes Berg @ 2011-05-13 13:14 UTC (permalink / raw)
  To: linux-wireless

From: Johannes Berg <johannes.berg@intel.com>

In P2P client mode, the GO (AP) to connect to might
have periods of time where it is not available due
to powersave. To allow the driver to sync with them
and send frames to the GO only when it is available
add a new callback prepare_auth_assoc (and also the
corresponding finish_auth_assoc). They are invoked
for each authentication/association as described in
the documentation.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h      |   21 +++++++++++++++++++++
 net/mac80211/driver-ops.h   |   31 +++++++++++++++++++++++++++++++
 net/mac80211/driver-trace.h |   38 ++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h  |    2 ++
 net/mac80211/mlme.c         |   21 ++++++++++++++++++---
 net/mac80211/work.c         |   22 ++++++++++++++++++++++
 6 files changed, 132 insertions(+), 3 deletions(-)

--- a/include/net/mac80211.h	2011-05-13 14:58:43.000000000 +0200
+++ b/include/net/mac80211.h	2011-05-13 15:11:55.000000000 +0200
@@ -1671,6 +1671,19 @@ enum ieee80211_ampdu_mlme_action {
  *	of the bss parameters has changed when a call is made. The callback
  *	can sleep.
  *
+ * @prepare_auth_assoc: Called before an authentication or association is
+ *	attempted. The function allows the driver to implement for example
+ *	support for sending frames to a P2P GO only during its availability
+ *	periods only. It is called for every authentication and association
+ *	separately, since applications might attempt to authenticate with
+ *	multiple APs before chosing one to associate to. If it returns an
+ *	error, the authentication process is reported as failed.
+ *	This callback can sleep.
+ * @finish_auth_assoc: Called after an authentication or association was
+ *	completed (whether successfully or not), as a counterpart to the
+ *	@prepare_auth_assoc function.
+ *	This callback can sleep.
+ *
  * @prepare_multicast: Prepare for multicast filter configuration.
  *	This callback is optional, and its return value is passed
  *	to configure_filter(). This callback must be atomic.
@@ -1881,6 +1894,14 @@ struct ieee80211_ops {
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *info,
 				 u32 changed);
+
+	int (*prepare_auth_assoc)(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  const u8 *bssid);
+	void (*finish_auth_assoc)(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  const u8 *bssid);
+
 	u64 (*prepare_multicast)(struct ieee80211_hw *hw,
 				 struct netdev_hw_addr_list *mc_list);
 	void (*configure_filter)(struct ieee80211_hw *hw,
--- a/net/mac80211/ieee80211_i.h	2011-05-13 14:58:43.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h	2011-05-13 14:58:44.000000000 +0200
@@ -308,6 +308,7 @@ struct ieee80211_work {
 			u8 key[WLAN_KEY_LEN_WEP104];
 			u8 key_len, key_idx;
 			bool privacy;
+			bool prepared;
 		} probe_auth;
 		struct {
 			struct cfg80211_bss *bss;
@@ -321,6 +322,7 @@ struct ieee80211_work {
 			u8 ssid_len;
 			u8 supp_rates_len;
 			bool wmm_used, use_11n, uapsd_used;
+			bool prepared;
 		} assoc;
 		struct {
 			u32 duration;
--- a/net/mac80211/mlme.c	2011-05-13 14:58:43.000000000 +0200
+++ b/net/mac80211/mlme.c	2011-05-13 15:06:06.000000000 +0200
@@ -2270,14 +2270,16 @@ static enum work_done_result
 ieee80211_probe_auth_done(struct ieee80211_work *wk,
 			  struct sk_buff *skb)
 {
+	struct ieee80211_local *local = wk->sdata->local;
+
 	if (!skb) {
 		cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	if (wk->type == IEEE80211_WORK_AUTH) {
 		cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	mutex_lock(&wk->sdata->u.mgd.mtx);
@@ -2287,6 +2289,11 @@ ieee80211_probe_auth_done(struct ieee802
 	wk->type = IEEE80211_WORK_AUTH;
 	wk->probe_auth.tries = 0;
 	return WORK_DONE_REQUEUE;
+ destroy:
+	if (wk->probe_auth.prepared)
+		drv_finish_auth_assoc(local, wk->sdata, wk->filter_ta);
+
+	return WORK_DONE_DESTROY;
 }
 
 int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
@@ -2359,6 +2366,7 @@ int ieee80211_mgd_auth(struct ieee80211_
 static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,
 						  struct sk_buff *skb)
 {
+	struct ieee80211_local *local = wk->sdata->local;
 	struct ieee80211_mgmt *mgmt;
 	struct ieee80211_rx_status *rx_status;
 	struct ieee802_11_elems elems;
@@ -2366,7 +2374,7 @@ static enum work_done_result ieee80211_a
 
 	if (!skb) {
 		cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);
-		return WORK_DONE_DESTROY;
+		goto destroy;
 	}
 
 	if (wk->type == IEEE80211_WORK_ASSOC_BEACON_WAIT) {
@@ -2386,6 +2394,9 @@ static enum work_done_result ieee80211_a
 	status = le16_to_cpu(mgmt->u.assoc_resp.status_code);
 
 	if (status == WLAN_STATUS_SUCCESS) {
+		if (wk->assoc.prepared)
+			drv_finish_auth_assoc(local, wk->sdata, wk->filter_ta);
+
 		mutex_lock(&wk->sdata->u.mgd.mtx);
 		if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {
 			mutex_unlock(&wk->sdata->u.mgd.mtx);
@@ -2399,6 +2410,10 @@ static enum work_done_result ieee80211_a
 	}
 
 	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len);
+ destroy:
+	if (wk->assoc.prepared)
+		drv_finish_auth_assoc(local, wk->sdata, wk->filter_ta);
+
 	return WORK_DONE_DESTROY;
 }
 
--- a/net/mac80211/work.c	2011-05-13 14:58:43.000000000 +0200
+++ b/net/mac80211/work.c	2011-05-13 15:07:23.000000000 +0200
@@ -25,6 +25,7 @@
 
 #include "ieee80211_i.h"
 #include "rate.h"
+#include "driver-ops.h"
 
 #define IEEE80211_AUTH_TIMEOUT (HZ / 5)
 #define IEEE80211_AUTH_MAX_TRIES 3
@@ -435,6 +436,13 @@ ieee80211_direct_probe(struct ieee80211_
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->probe_auth.prepared) {
+		int ret = drv_prepare_auth_assoc(local, sdata, wk->filter_ta);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->probe_auth.prepared = true;
+
 	wk->probe_auth.tries++;
 	if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: direct probe to %pM timed out\n",
@@ -473,6 +481,13 @@ ieee80211_authenticate(struct ieee80211_
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->probe_auth.prepared) {
+		int ret = drv_prepare_auth_assoc(local, sdata, wk->filter_ta);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->probe_auth.prepared = true;
+
 	wk->probe_auth.tries++;
 	if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: authentication with %pM"
@@ -506,6 +521,13 @@ ieee80211_associate(struct ieee80211_wor
 	struct ieee80211_sub_if_data *sdata = wk->sdata;
 	struct ieee80211_local *local = sdata->local;
 
+	if (!wk->assoc.prepared) {
+		int ret = drv_prepare_auth_assoc(local, sdata, wk->filter_ta);
+		if (ret)
+			return WORK_ACT_TIMEOUT;
+	}
+	wk->assoc.prepared = true;
+
 	wk->assoc.tries++;
 	if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) {
 		printk(KERN_DEBUG "%s: association with %pM"
--- a/net/mac80211/driver-ops.h	2011-05-13 14:59:50.000000000 +0200
+++ b/net/mac80211/driver-ops.h	2011-05-13 15:04:55.000000000 +0200
@@ -130,6 +130,37 @@ static inline void drv_bss_info_changed(
 	trace_drv_return_void(local);
 }
 
+static inline int drv_prepare_auth_assoc(struct ieee80211_local *local,
+					 struct ieee80211_sub_if_data *sdata,
+					 const u8 *bssid)
+{
+	int ret = 0;
+
+	might_sleep();
+
+	trace_drv_prepare_auth_assoc(local, sdata, bssid);
+	if (local->ops->prepare_auth_assoc)
+		ret = local->ops->prepare_auth_assoc(&local->hw,
+						     &sdata->vif,
+						     bssid);
+	trace_drv_return_int(local, ret);
+	return ret;
+}
+
+static inline void drv_finish_auth_assoc(struct ieee80211_local *local,
+					 struct ieee80211_sub_if_data *sdata,
+					 const u8 *bssid)
+{
+	might_sleep();
+
+	trace_drv_finish_auth_assoc(local, sdata, bssid);
+	if (local->ops->finish_auth_assoc)
+		local->ops->finish_auth_assoc(&local->hw,
+					      &sdata->vif,
+					      bssid);
+	trace_drv_return_void(local);
+}
+
 static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
 					struct netdev_hw_addr_list *mc_list)
 {
--- a/net/mac80211/driver-trace.h	2011-05-13 15:02:09.000000000 +0200
+++ b/net/mac80211/driver-trace.h	2011-05-13 15:04:35.000000000 +0200
@@ -119,6 +119,30 @@ DECLARE_EVENT_CLASS(local_sdata_evt,
 	)
 );
 
+DECLARE_EVENT_CLASS(local_sdata_bssid_evt,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid),
+	TP_ARGS(local, sdata, bssid),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		__array(char, bssid, ETH_ALEN)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		memcpy(__entry->bssid, bssid, ETH_ALEN);
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT " bssid:%pM",
+		LOCAL_PR_ARG, VIF_PR_ARG, __entry->bssid
+	)
+);
+
 DEFINE_EVENT(local_only_evt, drv_return_void,
 	TP_PROTO(struct ieee80211_local *local),
 	TP_ARGS(local)
@@ -319,6 +343,20 @@ TRACE_EVENT(drv_bss_info_changed,
 	)
 );
 
+DEFINE_EVENT(local_sdata_bssid_evt, drv_prepare_auth_assoc,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid),
+	TP_ARGS(local, sdata, bssid)
+)
+
+DEFINE_EVENT(local_sdata_bssid_evt, drv_finish_auth_assoc,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 const u8 *bssid),
+	TP_ARGS(local, sdata, bssid)
+)
+
 TRACE_EVENT(drv_prepare_multicast,
 	TP_PROTO(struct ieee80211_local *local, int mc_count),
 



^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [RFC] mac80211: notify driver about auth/assoc
  2011-05-13 13:14 [RFC] mac80211: notify driver about auth/assoc Johannes Berg
@ 2011-06-22 15:52 ` Johannes Berg
  0 siblings, 0 replies; 2+ messages in thread
From: Johannes Berg @ 2011-06-22 15:52 UTC (permalink / raw)
  To: linux-wireless

On Fri, 2011-05-13 at 15:14 +0200, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> In P2P client mode, the GO (AP) to connect to might
> have periods of time where it is not available due
> to powersave. To allow the driver to sync with them
> and send frames to the GO only when it is available
> add a new callback prepare_auth_assoc (and also the
> corresponding finish_auth_assoc). They are invoked
> for each authentication/association as described in
> the documentation.

Doesn't anybody have comments on this?

I can't really decide whether I want to change the bss_config flow to
maybe set the BSSID first and add a preauth flag there or something, or
use this way. This way certainly has less impact on existing drivers...

johannes


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2011-06-22 15:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-13 13:14 [RFC] mac80211: notify driver about auth/assoc Johannes Berg
2011-06-22 15:52 ` Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.