All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v2 00/12] get rid of AP mode monitor interfaces
@ 2011-10-21 14:23 Johannes Berg
  2011-10-21 14:23 ` [RFC v2 01/12] mac80211: add helper to free TX skb Johannes Berg
                   ` (12 more replies)
  0 siblings, 13 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

Here's a resend, now with OBSS beacon receive that
allows implementing the right protection logic in
hostapd.

As far as I can tell, this is complete. Separate
hostapd/wpa_s patchset will be on the way shortly.

johannes

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

* [RFC v2 01/12] mac80211: add helper to free TX skb
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 02/12] mac80211: add support for control port protocol in AP mode Johannes Berg
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Drivers that need to drop a frame before it
can be transmitted will usually simply free
that frame. This is currently fine, but in
the future it'll be needed to tell mac80211
about this case, so add a new routine that
frees a TX skb.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h |   10 ++++++++++
 net/mac80211/status.c  |    6 ++++++
 2 files changed, 16 insertions(+)

--- a/include/net/mac80211.h	2011-10-21 10:20:42.000000000 +0200
+++ b/include/net/mac80211.h	2011-10-21 12:07:38.000000000 +0200
@@ -1304,6 +1304,16 @@ ieee80211_get_alt_retry_rate(const struc
 }
 
 /**
+ * ieee80211_free_txskb - free TX skb
+ * @hw: the hardware
+ * @skb: the skb
+ *
+ * Free a transmit skb. Use this funtion when some failure
+ * to transmit happened and thus status cannot be reported.
+ */
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
  * DOC: Hardware crypto acceleration
  *
  * mac80211 is capable of taking advantage of many hardware
--- a/net/mac80211/status.c	2011-10-21 10:20:42.000000000 +0200
+++ b/net/mac80211/status.c	2011-10-21 12:07:38.000000000 +0200
@@ -609,3 +609,9 @@ void ieee80211_report_low_ack(struct iee
 				    num_packets, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(ieee80211_report_low_ack);
+
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	dev_kfree_skb_any(skb);
+}
+EXPORT_SYMBOL(ieee80211_free_txskb);



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

* [RFC v2 02/12] mac80211: add support for control port protocol in AP mode
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
  2011-10-21 14:23 ` [RFC v2 01/12] mac80211: add helper to free TX skb Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 03/12] nl80211: allow subscribing to unexpected class3 frames Johannes Berg
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

This will allow us to support dynamic WEP with 802.1X
properly in mac80211 by not encrypting outgoing and
accepting unencrypted incoming frames.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/cfg.c   |   21 ++++++++++++++++++++-
 net/mac80211/iface.c |   13 ++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

--- a/net/mac80211/cfg.c	2011-10-21 10:20:42.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-21 12:07:38.000000000 +0200
@@ -594,6 +594,8 @@ static int ieee80211_add_beacon(struct w
 {
 	struct ieee80211_sub_if_data *sdata;
 	struct beacon_data *old;
+	struct ieee80211_sub_if_data *vlan;
+	int ret;
 
 	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
@@ -601,7 +603,24 @@ static int ieee80211_add_beacon(struct w
 	if (old)
 		return -EALREADY;
 
-	return ieee80211_config_beacon(sdata, params);
+	ret = ieee80211_config_beacon(sdata, params);
+	if (ret)
+		return ret;
+
+	/*
+	 * Apply control port protocol, this allows us to
+	 * not encrypt dynamic WEP control frames.
+	 */
+	sdata->control_port_protocol = params->crypto.control_port_ethertype;
+	sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
+	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
+		vlan->control_port_protocol =
+			params->crypto.control_port_ethertype;
+		vlan->control_port_no_encrypt =
+			params->crypto.control_port_no_encrypt;
+	}
+
+	return 0;
 }
 
 static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
--- a/net/mac80211/iface.c	2011-10-21 12:07:37.000000000 +0200
+++ b/net/mac80211/iface.c	2011-10-21 12:07:38.000000000 +0200
@@ -188,11 +188,22 @@ static int ieee80211_do_open(struct net_
 		if (!is_valid_ether_addr(sdata->u.wds.remote_addr))
 			return -ENOLINK;
 		break;
-	case NL80211_IFTYPE_AP_VLAN:
+	case NL80211_IFTYPE_AP_VLAN: {
+		struct ieee80211_sub_if_data *master;
+
 		if (!sdata->bss)
 			return -ENOLINK;
+
 		list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
+
+		master = container_of(sdata->bss,
+				      struct ieee80211_sub_if_data, u.ap);
+		sdata->control_port_protocol =
+			master->control_port_protocol;
+		sdata->control_port_no_encrypt =
+			master->control_port_no_encrypt;
 		break;
+		}
 	case NL80211_IFTYPE_AP:
 		sdata->bss = &sdata->u.ap;
 		break;



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

* [RFC v2 03/12] nl80211: allow subscribing to unexpected class3 frames
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
  2011-10-21 14:23 ` [RFC v2 01/12] mac80211: add helper to free TX skb Johannes Berg
  2011-10-21 14:23 ` [RFC v2 02/12] mac80211: add support for control port protocol in AP mode Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 04/12] mac80211: support spurious class3 event Johannes Berg
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

To implement AP mode without monitor interfaces we
need to be able to send a deauth to stations that
send frames without being associated. Enable this
by adding a new nl80211 event for such frames that
an application can subscribe to.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |   13 +++++++++
 include/net/cfg80211.h  |   19 +++++++++++++
 net/wireless/mlme.c     |   16 +++++++++++
 net/wireless/nl80211.c  |   66 ++++++++++++++++++++++++++++++++++++++++++++++++
 net/wireless/nl80211.h  |    3 ++
 5 files changed, 117 insertions(+)

--- a/include/linux/nl80211.h	2011-10-21 10:20:41.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-21 12:07:39.000000000 +0200
@@ -509,6 +509,17 @@
  * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
  * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
  *
+ * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP
+ *	(or GO) interface (i.e. hostapd) to ask for unexpected frames to
+ *	implement sending deauth to stations that send unexpected class 3
+ *	frames. Also used as the event sent by the kernel when such a frame
+ *	is received. When 4 address mode is supported, it may also be used
+ *	to notify the AP controller about those frames.
+ *	For the event, the %NL80211_ATTR_MAC attribute carries TA along
+ *	with more information like the interface index.
+ *	If used as the command, must have an interface index, and you can
+ *	only unsubscribe from the event by closing the socket.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -638,6 +649,8 @@ enum nl80211_commands {
 	NL80211_CMD_TDLS_OPER,
 	NL80211_CMD_TDLS_MGMT,
 
+	NL80211_CMD_UNEXPECTED_FRAME,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- a/include/net/cfg80211.h	2011-10-21 10:20:42.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-21 12:07:39.000000000 +0200
@@ -2179,6 +2179,8 @@ struct wireless_dev {
 
 	int beacon_interval;
 
+	u32 ap_unexpected_nlpid;
+
 #ifdef CONFIG_CFG80211_WEXT
 	/* wext data */
 	struct {
@@ -3185,6 +3187,23 @@ void cfg80211_gtk_rekey_notify(struct ne
 void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
 				     const u8 *bssid, bool preauth, gfp_t gfp);
 
+/**
+ * cfg80211_rx_spurious_frame - inform userspace about a spurious frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * a spurious class 3 frame was received, to be able to deauth the
+ * sender. If 4addr frames are supported in AP mode, these may also
+ * be passed here if they aren't yet allowed for the sender so that
+ * the userspace application can set up things properly.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+				const u8 *addr, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
--- a/net/wireless/mlme.c	2011-10-21 10:20:42.000000000 +0200
+++ b/net/wireless/mlme.c	2011-10-21 12:07:39.000000000 +0200
@@ -879,6 +879,9 @@ void cfg80211_mlme_unregister_socket(str
 	}
 
 	spin_unlock_bh(&wdev->mgmt_registrations_lock);
+
+	if (nlpid == wdev->ap_unexpected_nlpid)
+		wdev->ap_unexpected_nlpid = 0;
 }
 
 void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
@@ -1107,3 +1110,16 @@ void cfg80211_pmksa_candidate_notify(str
 	nl80211_pmksa_candidate_notify(rdev, dev, index, bssid, preauth, gfp);
 }
 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
+
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+				const u8 *addr, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+		    wdev->iftype != NL80211_IFTYPE_P2P_GO))
+		return false;
+
+	return nl80211_unexpected_frame(dev, addr, gfp);
+}
+EXPORT_SYMBOL(cfg80211_rx_spurious_frame);
--- a/net/wireless/nl80211.c	2011-10-21 10:20:42.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-21 12:07:39.000000000 +0200
@@ -5827,6 +5827,23 @@ static int nl80211_set_rekey_data(struct
 	return err;
 }
 
+static int nl80211_register_unexpected_frame(struct sk_buff *skb,
+					     struct genl_info *info)
+{
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+	if (wdev->iftype != NL80211_IFTYPE_AP &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EINVAL;
+
+	if (wdev->ap_unexpected_nlpid)
+		return -EBUSY;
+
+	wdev->ap_unexpected_nlpid = info->snd_pid;
+	return 0;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -6382,6 +6399,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_UNEXPECTED_FRAME,
+		.doit = nl80211_register_unexpected_frame,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7202,6 +7227,47 @@ void nl80211_send_sta_del_event(struct c
 	nlmsg_free(msg);
 }
 
+bool nl80211_unexpected_frame(struct net_device *dev, const u8 *addr, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+	u32 nlpid = ACCESS_ONCE(wdev->ap_unexpected_nlpid);
+
+	if (!nlpid)
+		return false;
+
+	msg = nlmsg_new(100, gfp);
+	if (!msg)
+		return true;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_UNEXPECTED_FRAME);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return true;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return true;
+	}
+
+	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
+	return true;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+	return true;
+}
+
 int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
 		      struct net_device *netdev, u32 nlpid,
 		      int freq, const u8 *buf, size_t len, gfp_t gfp)
--- a/net/wireless/nl80211.h	2011-10-21 10:20:42.000000000 +0200
+++ b/net/wireless/nl80211.h	2011-10-21 12:07:39.000000000 +0200
@@ -117,4 +117,7 @@ void nl80211_pmksa_candidate_notify(stru
 				    struct net_device *netdev, int index,
 				    const u8 *bssid, bool preauth, gfp_t gfp);
 
+bool nl80211_unexpected_frame(struct net_device *dev,
+			      const u8 *addr, gfp_t gfp);
+
 #endif /* __NET_WIRELESS_NL80211_H */



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

* [RFC v2 04/12] mac80211: support spurious class3 event
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (2 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 03/12] nl80211: allow subscribing to unexpected class3 frames Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 05/12] nl80211: advertise device AP SME Johannes Berg
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Add support for the spurious class3 frame event
to mac80211 to enable AP w/o monitor mode.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/rx.c |    7 +++++++
 1 file changed, 7 insertions(+)

--- a/net/mac80211/rx.c	2011-10-21 10:22:38.000000000 +0200
+++ b/net/mac80211/rx.c	2011-10-21 12:07:40.000000000 +0200
@@ -854,6 +854,13 @@ ieee80211_rx_h_check(struct ieee80211_rx
 			    rx->sdata->control_port_protocol)
 				return RX_CONTINUE;
 		}
+
+		if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
+		    cfg80211_rx_spurious_frame(rx->sdata->dev,
+		    			       hdr->addr2,
+		    			       GFP_ATOMIC))
+			return RX_DROP_UNUSABLE;
+
 		return RX_DROP_MONITOR;
 	}
 



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

* [RFC v2 05/12] nl80211: advertise device AP SME
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (3 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 04/12] mac80211: support spurious class3 event Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-25 10:13   ` Eliad Peller
  2011-10-21 14:23 ` [RFC v2 06/12] nl80211: add API to probe a client Johannes Berg
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Add the ability to advertise that the device
contains the AP SME and what features it can
support.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/ath/ath6kl/init.c |    4 +++-
 include/linux/nl80211.h                |   20 ++++++++++++++++++++
 include/net/cfg80211.h                 |    6 ++++++
 net/wireless/core.c                    |    4 ++++
 net/wireless/nl80211.c                 |    4 ++++
 5 files changed, 37 insertions(+), 1 deletion(-)

--- a/include/linux/nl80211.h	2011-10-21 12:07:39.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-21 12:07:41.000000000 +0200
@@ -1122,6 +1122,11 @@ enum nl80211_commands {
  *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver to perform a TDLS operation.
  *
+ * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
+ *	that have AP support to indicate that the have the AP SME integrated
+ *	with support for the features listed in this attribute, see
+ *	&enum nl80211_ap_sme_features.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1350,6 +1355,8 @@ enum nl80211_attrs {
 	NL80211_ATTR_TDLS_SUPPORT,
 	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
 
+	NL80211_ATTR_DEVICE_AP_MLME,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2663,4 +2670,17 @@ enum nl80211_tdls_operation {
 	NL80211_TDLS_DISABLE_LINK,
 };
 
+/**
+ * enum nl80211_ap_sme_features - device-integrated AP features
+ * @NL80211_AP_SME_WSC: The driver is capable of indicating received probe
+ *	request frames to userspace via management frame subscription events
+ *	if the payload includes the WSC IE. The driver is capable of adding
+ *	the WSC IE as configured from userspace into beacons, probe responses
+ *	and (re)association reponse frame and allows userspace to update them
+ *	during the lifetime of the BSS.
+ */
+enum nl80211_ap_sme_features {
+	NL80211_AP_SME_WSC	= 1 << 0,
+};
+
 #endif /* __LINUX_NL80211_H */
--- a/include/net/cfg80211.h	2011-10-21 12:07:39.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-21 12:07:41.000000000 +0200
@@ -1675,6 +1675,7 @@ struct cfg80211_ops {
  *	teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
  *	command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1693,6 +1694,7 @@ enum wiphy_flags {
 	WIPHY_FLAG_AP_UAPSD			= BIT(14),
 	WIPHY_FLAG_SUPPORTS_TDLS		= BIT(15),
 	WIPHY_FLAG_TDLS_EXTERNAL_SETUP		= BIT(16),
+	WIPHY_FLAG_HAVE_AP_SME			= BIT(17),
 };
 
 /**
@@ -1903,6 +1905,8 @@ struct wiphy_wowlan_support {
  *	may request, if implemented.
  *
  * @wowlan: WoWLAN support information
+ *
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -1926,6 +1930,8 @@ struct wiphy {
 
 	u32 flags;
 
+	u32 ap_sme_capa;
+
 	enum cfg80211_signal_type signal_type;
 
 	int bss_priv_size;
--- a/net/wireless/core.c	2011-10-21 10:20:41.000000000 +0200
+++ b/net/wireless/core.c	2011-10-21 12:07:41.000000000 +0200
@@ -492,6 +492,10 @@ int wiphy_register(struct wiphy *wiphy)
 		    !(wiphy->wowlan.flags & WIPHY_WOWLAN_SUPPORTS_GTK_REKEY)))
 		return -EINVAL;
 
+	if (WARN_ON(wiphy->ap_sme_capa &&
+		    !(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME)))
+		return -EINVAL;
+
 	if (WARN_ON(wiphy->addresses && !wiphy->n_addresses))
 		return -EINVAL;
 
--- a/net/wireless/nl80211.c	2011-10-21 12:07:39.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-21 12:07:41.000000000 +0200
@@ -1008,6 +1008,10 @@ static int nl80211_send_wiphy(struct sk_
 	if (nl80211_put_iface_combinations(&dev->wiphy, msg))
 		goto nla_put_failure;
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME)
+		NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_MLME,
+			    dev->wiphy.ap_sme_capa);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
--- a/drivers/net/wireless/ath/ath6kl/init.c	2011-10-21 10:20:41.000000000 +0200
+++ b/drivers/net/wireless/ath/ath6kl/init.c	2011-10-21 12:07:41.000000000 +0200
@@ -1548,7 +1548,9 @@ static int ath6kl_init(struct net_device
 	ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
 			 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
 
-	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
+	ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
+				  WIPHY_FLAG_HAVE_AP_SME;
+	ar->wdev->wiphy->ap_sme_capa = NL80211_AP_SME_WSC;
 
 	status = ath6kl_target_config_wlan_params(ar);
 	if (!status)



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

* [RFC v2 06/12] nl80211: add API to probe a client
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (4 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 05/12] nl80211: advertise device AP SME Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 07/12] mac80211: support client probe Johannes Berg
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

When the AP SME in hostapd is used it wants to
probe the clients when they have been idle for
some time. Add explicit API to support this.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: - indicate both ack/non-ack status for cookie validity

 include/linux/nl80211.h |   10 ++++
 include/net/cfg80211.h  |   17 +++++++
 net/wireless/nl80211.c  |  104 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 131 insertions(+)

--- a/include/linux/nl80211.h	2011-10-21 12:07:41.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-21 12:07:42.000000000 +0200
@@ -520,6 +520,14 @@
  *	If used as the command, must have an interface index, and you can
  *	only unsubscribe from the event by closing the socket.
  *
+ * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface
+ *	by sending a null data frame to it and reporting when the frame is
+ *	acknowleged. This is used to allow timing out inactive clients. Uses
+ *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a
+ *	direct reply with an %NL80211_ATTR_COOKIE that is later used to match
+ *	up the event with the request. The event includes the same data and
+ *	has %NL80211_ATTR_ACK set if the frame was ACKed.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -651,6 +659,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_UNEXPECTED_FRAME,
 
+	NL80211_CMD_PROBE_CLIENT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- a/include/net/cfg80211.h	2011-10-21 12:07:41.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-21 12:07:42.000000000 +0200
@@ -1428,6 +1428,9 @@ struct cfg80211_gtk_rekey_data {
  *
  * @tdls_mgmt: Transmit a TDLS management frame.
  * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
+ *
+ * @probe_client: probe an associated client, must return a cookie that it
+ *	later passes to cfg80211_probe_status().
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1617,6 +1620,9 @@ struct cfg80211_ops {
 			     u16 status_code, const u8 *buf, size_t len);
 	int	(*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
 			     u8 *peer, enum nl80211_tdls_operation oper);
+
+	int	(*probe_client)(struct wiphy *wiphy, struct net_device *dev,
+				const u8 *peer, u64 *cookie);
 };
 
 /*
@@ -3210,6 +3216,17 @@ void cfg80211_pmksa_candidate_notify(str
 bool cfg80211_rx_spurious_frame(struct net_device *dev,
 				const u8 *addr, gfp_t gfp);
 
+/**
+ * cfg80211_probe_status - notify userspace about probe status
+ * @dev: the device the probe was sent on
+ * @addr: the address of the peer
+ * @cookie: the cookie filled in @probe_client previously
+ * @acked: indicates whether probe was acked or not
+ * @gfp: allocation flags
+ */
+void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
+			   u64 cookie, bool acked, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
--- a/net/wireless/nl80211.c	2011-10-21 12:07:41.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-21 12:07:42.000000000 +0200
@@ -891,6 +891,7 @@ static int nl80211_send_wiphy(struct sk_
 	}
 	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
 		CMD(sched_scan_start, START_SCHED_SCAN);
+	CMD(probe_client, PROBE_CLIENT);
 
 #undef CMD
 
@@ -5848,6 +5849,59 @@ static int nl80211_register_unexpected_f
 	return 0;
 }
 
+static int nl80211_probe_client(struct sk_buff *skb,
+				struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct sk_buff *msg;
+	void *hdr;
+	const u8 *addr;
+	u64 cookie;
+	int err;
+
+	if (wdev->iftype != NL80211_IFTYPE_AP &&
+	    wdev->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	if (!rdev->ops->probe_client)
+		return -EOPNOTSUPP;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+			     NL80211_CMD_PROBE_CLIENT);
+
+	if (IS_ERR(hdr)) {
+		err = PTR_ERR(hdr);
+		goto free_msg;
+	}
+
+	addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+	err = rdev->ops->probe_client(&rdev->wiphy, dev, addr, &cookie);
+	if (err)
+		goto free_msg;
+
+	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+
+	genlmsg_end(msg, hdr);
+
+	return genlmsg_reply(msg, info);
+
+ nla_put_failure:
+	err = -ENOBUFS;
+ free_msg:
+	nlmsg_free(msg);
+	return err;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -6411,6 +6465,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_PROBE_CLIENT,
+		.doit = nl80211_probe_client,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7532,6 +7594,48 @@ nl80211_send_cqm_pktloss_notify(struct c
 	nlmsg_free(msg);
 }
 
+void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
+			   u64 cookie, bool acked, gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	int err;
+
+	msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PROBE_CLIENT);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
+	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+	if (acked)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_ACK);
+
+	err = genlmsg_end(msg, hdr);
+	if (err < 0) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+				nl80211_mlme_mcgrp.id, gfp);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_probe_status);
+
 static int nl80211_netlink_notify(struct notifier_block * nb,
 				  unsigned long state,
 				  void *_notify)



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

* [RFC v2 07/12] mac80211: support client probe
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (5 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 06/12] nl80211: add API to probe a client Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 08/12] net: add wireless TX status socket option Johannes Berg
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Support probing clients with null data frames
in AP mode.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: update to use cfg80211_probe_status

 net/mac80211/cfg.c    |   68 ++++++++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/status.c |   45 +++++++++++++++++++--------------
 2 files changed, 95 insertions(+), 18 deletions(-)

--- a/net/mac80211/cfg.c	2011-10-21 12:07:38.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-21 12:07:42.000000000 +0200
@@ -2507,6 +2507,73 @@ static int ieee80211_tdls_oper(struct wi
 	return 0;
 }
 
+static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
+				  const u8 *peer, u64 *cookie)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_qos_hdr *nullfunc;
+	struct sk_buff *skb;
+	int size = sizeof(*nullfunc);
+	__le16 fc;
+	bool qos;
+	struct ieee80211_tx_info *info;
+	struct sta_info *sta;
+
+	rcu_read_lock();
+	sta = sta_info_get(sdata, peer);
+	if (sta)
+		qos = test_sta_flag(sta, WLAN_STA_WME);
+	rcu_read_unlock();
+
+	if (!sta)
+		return -ENOLINK;
+
+	if (qos) {
+		fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+				 IEEE80211_STYPE_QOS_NULLFUNC |
+				 IEEE80211_FCTL_FROMDS);
+	} else {
+		size -= 2;
+		fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
+				 IEEE80211_STYPE_NULLFUNC |
+				 IEEE80211_FCTL_FROMDS);
+	}
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
+	if (!skb)
+		return -ENOMEM;
+
+	skb->dev = dev;
+
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	nullfunc = (void *) skb_put(skb, size);
+	nullfunc->frame_control = fc;
+	nullfunc->duration_id = 0;
+	memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
+	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
+	memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
+	nullfunc->seq_ctrl = 0;
+
+	info = IEEE80211_SKB_CB(skb);
+
+	info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
+		       IEEE80211_TX_INTFL_NL80211_FRAME_TX;
+
+	skb_set_queue_mapping(skb, IEEE80211_AC_VO);
+	skb->priority = 7;
+	if (qos)
+		nullfunc->qos_ctrl = cpu_to_le16(7);
+
+	local_bh_disable();
+	ieee80211_xmit(sdata, skb);
+	local_bh_enable();
+
+	*cookie = (unsigned long) skb;
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2572,4 +2639,5 @@ struct cfg80211_ops mac80211_config_ops
 	.set_rekey_data = ieee80211_set_rekey_data,
 	.tdls_oper = ieee80211_tdls_oper,
 	.tdls_mgmt = ieee80211_tdls_mgmt,
+	.probe_client = ieee80211_probe_client,
 };
--- a/net/mac80211/status.c	2011-10-21 12:07:38.000000000 +0200
+++ b/net/mac80211/status.c	2011-10-21 12:07:42.000000000 +0200
@@ -516,27 +516,36 @@ void ieee80211_tx_status(struct ieee8021
 	}
 
 	if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
-		struct ieee80211_work *wk;
 		u64 cookie = (unsigned long)skb;
 
-		rcu_read_lock();
-		list_for_each_entry_rcu(wk, &local->work_list, list) {
-			if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
-				continue;
-			if (wk->offchan_tx.frame != skb)
-				continue;
-			wk->offchan_tx.status = true;
-			break;
-		}
-		rcu_read_unlock();
-		if (local->hw_roc_skb_for_status == skb) {
-			cookie = local->hw_roc_cookie ^ 2;
-			local->hw_roc_skb_for_status = NULL;
-		}
+		if (ieee80211_is_nullfunc(hdr->frame_control) ||
+		    ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+		    	bool acked = info->flags & IEEE80211_TX_STAT_ACK;
+			cfg80211_probe_status(skb->dev, hdr->addr1,
+					      cookie, acked, GFP_ATOMIC);
+		} else {
+			struct ieee80211_work *wk;
 
-		cfg80211_mgmt_tx_status(
-			skb->dev, cookie, skb->data, skb->len,
-			!!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
+			rcu_read_lock();
+			list_for_each_entry_rcu(wk, &local->work_list, list) {
+				if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX)
+					continue;
+				if (wk->offchan_tx.frame != skb)
+					continue;
+				wk->offchan_tx.status = true;
+				break;
+			}
+			rcu_read_unlock();
+			if (local->hw_roc_skb_for_status == skb) {
+				cookie = local->hw_roc_cookie ^ 2;
+				local->hw_roc_skb_for_status = NULL;
+			}
+
+			cfg80211_mgmt_tx_status(
+				skb->dev, cookie, skb->data, skb->len,
+				!!(info->flags & IEEE80211_TX_STAT_ACK),
+				GFP_ATOMIC);
+		}
 	}
 
 	/* this was a transmitted frame, but now we want to reuse it */



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

* [RFC v2 08/12] net: add wireless TX status socket option
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (6 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 07/12] mac80211: support client probe Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-25 10:40   ` Eliad Peller
  2011-10-21 14:23 ` [RFC v2 09/12] nl80211: advertise socket TX status capability Johannes Berg
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

The 802.1X EAPOL handshake hostapd does requires
knowing whether the frame was ack'ed by the peer.
Currently, we fudge this pretty badly by not even
transmitting the frame as a normal data frame but
injecting it with radiotap and getting the status
out of radiotap monitor as well. This is rather
complex, confuses users (mon.wlan0 presence) and
doesn't work with all hardware.

To get rid of that hack, introduce a real wifi TX
status option for data frame transmissions.

This works similar to the existing TX timestamping
in that it reflects the SKB back to the socket's
error queue with a SCM_WIFI_STATUS cmsg that has
an int indicating ACK status (0/1).

Since it is possible that at some point we will
want to have TX timestamping and wifi status in a
single errqueue SKB (there's little point in not
doing that), redefine SO_EE_ORIGIN_TIMESTAMPING
to SO_EE_ORIGIN_TXSTATUS which can collect more
than just the timestamp; keep the old constant
as an alias of course. Currently the internal APIs
don't make that possible, but it wouldn't be hard
to split them up in a way that makes it possible.

Thanks to Neil Horman for helping me figure out
the functions that add the control messages.

TODO:
 * sock_tx_timestamp() function should be renamed,
   maybe to sock_tx_status()?
 * sock_recv_timestamp() should also be renamed,
   I had a hard time figuring out the difference
   between that and sock_recv_ts_and_drops(). The
   former is generic, while the latter adds RX
   information only, maybe that should be reflected
   in new names?

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 arch/alpha/include/asm/socket.h   |    3 +++
 arch/arm/include/asm/socket.h     |    3 +++
 arch/avr32/include/asm/socket.h   |    3 +++
 arch/cris/include/asm/socket.h    |    3 +++
 arch/frv/include/asm/socket.h     |    3 +++
 arch/h8300/include/asm/socket.h   |    3 +++
 arch/ia64/include/asm/socket.h    |    3 +++
 arch/m32r/include/asm/socket.h    |    3 +++
 arch/m68k/include/asm/socket.h    |    3 +++
 arch/mips/include/asm/socket.h    |    3 +++
 arch/mn10300/include/asm/socket.h |    3 +++
 arch/parisc/include/asm/socket.h  |    3 +++
 arch/powerpc/include/asm/socket.h |    3 +++
 arch/s390/include/asm/socket.h    |    3 +++
 arch/sparc/include/asm/socket.h   |    3 +++
 arch/xtensa/include/asm/socket.h  |    3 +++
 include/asm-generic/socket.h      |    3 +++
 include/linux/errqueue.h          |    3 ++-
 include/linux/skbuff.h            |   19 +++++++++++++++++--
 include/net/sock.h                |    7 +++++++
 net/core/skbuff.c                 |   20 ++++++++++++++++++++
 net/core/sock.c                   |    9 +++++++++
 net/socket.c                      |   19 +++++++++++++++++++
 23 files changed, 125 insertions(+), 3 deletions(-)

--- a/include/asm-generic/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/include/asm-generic/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -64,4 +64,7 @@
 #define SO_DOMAIN		39
 
 #define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS	SO_WIFI_STATUS
 #endif /* __ASM_GENERIC_SOCKET_H */
--- a/net/core/sock.c	2011-10-21 10:20:39.000000000 +0200
+++ b/net/core/sock.c	2011-10-21 12:07:43.000000000 +0200
@@ -743,6 +743,11 @@ set_rcvbuf:
 		else
 			sock_reset_flag(sk, SOCK_RXQ_OVFL);
 		break;
+
+	case SO_WIFI_STATUS:
+		sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
+		break;
+
 	default:
 		ret = -ENOPROTOOPT;
 		break;
@@ -964,6 +969,10 @@ int sock_getsockopt(struct socket *sock,
 		v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
 		break;
 
+	case SO_WIFI_STATUS:
+		v.val = !!sock_flag(sk, SOCK_WIFI_STATUS);
+		break;
+
 	default:
 		return -ENOPROTOOPT;
 	}
--- a/include/net/sock.h	2011-10-21 10:20:39.000000000 +0200
+++ b/include/net/sock.h	2011-10-21 12:07:43.000000000 +0200
@@ -564,6 +564,7 @@ enum sock_flags {
 	SOCK_FASYNC, /* fasync() active */
 	SOCK_RXQ_OVFL,
 	SOCK_ZEROCOPY, /* buffers from userspace */
+	SOCK_WIFI_STATUS, /* push wifi status to userspace */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -1705,7 +1706,10 @@ static inline int sock_intr_errno(long t
 
 extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 	struct sk_buff *skb);
+extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb);
 
+/* XXX: rename this function now? */
 static __inline__ void
 sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
 {
@@ -1732,6 +1736,9 @@ sock_recv_timestamp(struct msghdr *msg,
 		__sock_recv_timestamp(msg, sk, skb);
 	else
 		sk->sk_stamp = kt;
+
+	if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
+		__sock_recv_wifi_status(msg, sk, skb);
 }
 
 extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
--- a/arch/alpha/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/alpha/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -69,6 +69,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/arm/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/arm/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/avr32/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/avr32/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* __ASM_AVR32_SOCKET_H */
--- a/arch/cris/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/cris/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -64,6 +64,9 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
 
--- a/arch/frv/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/frv/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,5 +62,8 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
 
--- a/arch/h8300/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/h8300/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/ia64/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/ia64/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -71,4 +71,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_IA64_SOCKET_H */
--- a/arch/m32r/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/m32r/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_M32R_SOCKET_H */
--- a/arch/m68k/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/m68k/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/mips/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/mips/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -82,6 +82,9 @@ To add: #define SO_REUSEPORT 0x0200	/* A
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
--- a/arch/mn10300/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/mn10300/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -62,4 +62,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/parisc/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/parisc/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -61,6 +61,9 @@
 
 #define SO_RXQ_OVFL             0x4021
 
+#define SO_WIFI_STATUS		0x4022
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
--- a/arch/powerpc/include/asm/socket.h	2011-10-21 10:20:39.000000000 +0200
+++ b/arch/powerpc/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -69,4 +69,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _ASM_POWERPC_SOCKET_H */
--- a/arch/s390/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/s390/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -70,4 +70,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif /* _ASM_SOCKET_H */
--- a/arch/sparc/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/sparc/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -58,6 +58,9 @@
 
 #define SO_RXQ_OVFL             0x0024
 
+#define SO_WIFI_STATUS		0x0025
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION		0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
--- a/arch/xtensa/include/asm/socket.h	2011-10-21 10:20:38.000000000 +0200
+++ b/arch/xtensa/include/asm/socket.h	2011-10-21 12:07:43.000000000 +0200
@@ -73,4 +73,7 @@
 
 #define SO_RXQ_OVFL             40
 
+#define SO_WIFI_STATUS		41
+#define SCM_WIFI_STATUS		SO_WIFI_STATUS
+
 #endif	/* _XTENSA_SOCKET_H */
--- a/include/linux/errqueue.h	2011-10-21 10:20:39.000000000 +0200
+++ b/include/linux/errqueue.h	2011-10-21 12:07:43.000000000 +0200
@@ -17,7 +17,8 @@ struct sock_extended_err {
 #define SO_EE_ORIGIN_LOCAL	1
 #define SO_EE_ORIGIN_ICMP	2
 #define SO_EE_ORIGIN_ICMP6	3
-#define SO_EE_ORIGIN_TIMESTAMPING 4
+#define SO_EE_ORIGIN_TXSTATUS	4
+#define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
 
 #define SO_EE_OFFENDER(ee)	((struct sockaddr*)((ee)+1))
 
--- a/include/linux/skbuff.h	2011-10-21 10:20:39.000000000 +0200
+++ b/include/linux/skbuff.h	2011-10-21 12:07:43.000000000 +0200
@@ -190,6 +190,9 @@ enum {
 
 	/* device driver supports TX zero-copy buffers */
 	SKBTX_DEV_ZEROCOPY = 1 << 4,
+
+	/* generate wifi status information (where possible) */
+	SKBTX_WIFI_STATUS = 1 << 5,
 };
 
 /*
@@ -322,6 +325,8 @@ typedef unsigned char *sk_buff_data_t;
  *	@queue_mapping: Queue mapping for multiqueue devices
  *	@ndisc_nodetype: router type (from link layer)
  *	@ooo_okay: allow the mapping of a socket to a queue to be changed
+ *	@wifi_acked_valid: wifi_acked was set
+ *	@wifi_acked: whether frame was acked on wifi or not
  *	@dma_cookie: a cookie to one of several possible DMA operations
  *		done by skb DMA functions
  *	@secmark: security marking
@@ -414,10 +419,11 @@ struct sk_buff {
 	__u8			ndisc_nodetype:2;
 #endif
 	__u8			ooo_okay:1;
+	__u8			wifi_acked_valid:1;
+	__u8			wifi_acked:1;
+	/* 11/13 bit hole (depending on nodetype presence) */
 	kmemcheck_bitfield_end(flags2);
 
-	/* 0/13 bit hole */
-
 #ifdef CONFIG_NET_DMA
 	dma_cookie_t		dma_cookie;
 #endif
@@ -2062,6 +2068,15 @@ static inline void skb_tx_timestamp(stru
 	sw_tx_timestamp(skb);
 }
 
+/**
+ * skb_complete_wifi_ack - deliver skb with wifi status
+ *
+ * @skb: the original outgoing packet
+ * @acked: ack status
+ *
+ */
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked);
+
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
 
--- a/net/core/skbuff.c	2011-10-21 10:20:39.000000000 +0200
+++ b/net/core/skbuff.c	2011-10-21 12:07:43.000000000 +0200
@@ -3150,6 +3150,26 @@ void skb_tstamp_tx(struct sk_buff *orig_
 }
 EXPORT_SYMBOL_GPL(skb_tstamp_tx);
 
+void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
+{
+	struct sock *sk = skb->sk;
+	struct sock_exterr_skb *serr;
+	int err;
+
+	skb->wifi_acked_valid = 1;
+	skb->wifi_acked = acked;
+
+	serr = SKB_EXT_ERR(skb);
+	memset(serr, 0, sizeof(*serr));
+	serr->ee.ee_errno = ENOMSG;
+	serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
+
+	err = sock_queue_err_skb(sk, skb);
+	if (err)
+		kfree_skb(skb);
+}
+EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
+
 
 /**
  * skb_partial_csum_set - set up and verify partial csum values for packet
--- a/net/socket.c	2011-10-21 10:20:39.000000000 +0200
+++ b/net/socket.c	2011-10-21 12:07:43.000000000 +0200
@@ -531,6 +531,7 @@ void sock_release(struct socket *sock)
 }
 EXPORT_SYMBOL(sock_release);
 
+/* XXX: rename this function now */
 int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
 {
 	*tx_flags = 0;
@@ -538,6 +539,8 @@ int sock_tx_timestamp(struct sock *sk, _
 		*tx_flags |= SKBTX_HW_TSTAMP;
 	if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
 		*tx_flags |= SKBTX_SW_TSTAMP;
+	if (sock_flag(sk, SOCK_WIFI_STATUS))
+		*tx_flags |= SKBTX_WIFI_STATUS;
 	return 0;
 }
 EXPORT_SYMBOL(sock_tx_timestamp);
@@ -674,6 +677,22 @@ void __sock_recv_timestamp(struct msghdr
 }
 EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
 
+void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+	struct sk_buff *skb)
+{
+	int ack;
+
+	if (!sock_flag(sk, SOCK_WIFI_STATUS))
+		return;
+	if (!skb->wifi_acked_valid)
+		return;
+
+	ack = skb->wifi_acked;
+
+	put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
+}
+EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
+
 static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
 				   struct sk_buff *skb)
 {



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

* [RFC v2 09/12] nl80211: advertise socket TX status capability
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (7 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 08/12] net: add wireless TX status socket option Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 10/12] mac80211: implement wifi TX status Johannes Berg
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

The new wifi socket TX capability should be
supported by wifi drivers, let them advertise
whether they do or not.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |   15 +++++++++++++++
 include/net/cfg80211.h  |    3 ++-
 net/wireless/nl80211.c  |    2 ++
 3 files changed, 19 insertions(+), 1 deletion(-)

--- a/include/linux/nl80211.h	2011-10-21 12:07:42.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-21 12:07:45.000000000 +0200
@@ -1137,6 +1137,9 @@ enum nl80211_commands {
  *	with support for the features listed in this attribute, see
  *	&enum nl80211_ap_sme_features.
  *
+ * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
+ *	&enum nl80211_feature_flags and is advertised in wiphy information.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1367,6 +1370,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_DEVICE_AP_MLME,
 
+	NL80211_ATTR_FEATURE_FLAGS,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2693,4 +2698,14 @@ enum nl80211_ap_sme_features {
 	NL80211_AP_SME_WSC	= 1 << 0,
 };
 
+/**
+ * enum nl80211_feature_flags - device/driver features
+ * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
+ *	TX status to the socket error queue when requested with the
+ *	socket option.
+ */
+enum nl80211_feature_flags {
+	NL80211_FEATURE_SK_TX_STATUS	= 1 << 0,
+};
+
 #endif /* __LINUX_NL80211_H */
--- a/include/net/cfg80211.h	2011-10-21 12:07:42.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-21 12:07:45.000000000 +0200
@@ -1873,6 +1873,7 @@ struct wiphy_wowlan_support {
  * @software_iftypes: bitmask of software interface types, these are not
  *	subject to any restrictions since they are purely managed in SW.
  * @flags: wiphy flags, see &enum wiphy_flags
+ * @features: features advertised to nl80211, see &enum nl80211_feature_flags.
  * @bss_priv_size: each BSS struct has private data allocated with it,
  *	this variable determines its size
  * @max_scan_ssids: maximum number of SSIDs the device can scan for in
@@ -1934,7 +1935,7 @@ struct wiphy {
 	/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
 	u16 interface_modes;
 
-	u32 flags;
+	u32 flags, features;
 
 	u32 ap_sme_capa;
 
--- a/net/wireless/nl80211.c	2011-10-21 12:07:42.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-21 12:07:45.000000000 +0200
@@ -1013,6 +1013,8 @@ static int nl80211_send_wiphy(struct sk_
 		NLA_PUT_U32(msg, NL80211_ATTR_DEVICE_AP_MLME,
 			    dev->wiphy.ap_sme_capa);
 
+	NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:



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

* [RFC v2 10/12] mac80211: implement wifi TX status
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (8 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 09/12] nl80211: advertise socket TX status capability Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 11/12] cfg80211: allow registering to beacons Johannes Berg
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Implement the socket wifi TX status error
queue reflection in mac80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211.h     |    5 +---
 net/mac80211/ieee80211_i.h |    4 +++
 net/mac80211/main.c        |   18 ++++++++++++++
 net/mac80211/status.c      |   38 ++++++++++++++++++++++++++++++
 net/mac80211/tx.c          |   56 ++++++++++++++++++++++++++++++++++++++++++---
 5 files changed, 115 insertions(+), 6 deletions(-)

--- a/net/mac80211/status.c	2011-10-21 12:07:42.000000000 +0200
+++ b/net/mac80211/status.c	2011-10-21 12:07:46.000000000 +0200
@@ -548,6 +548,24 @@ void ieee80211_tx_status(struct ieee8021
 		}
 	}
 
+	if (unlikely(info->ack_frame_id)) {
+		struct sk_buff *ack_skb;
+		unsigned long flags;
+
+		spin_lock_irqsave(&local->ack_status_lock, flags);
+		ack_skb = idr_find(&local->ack_status_frames,
+				   info->ack_frame_id);
+		if (ack_skb)
+			idr_remove(&local->ack_status_frames,
+				   info->ack_frame_id);
+		spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+		/* consumes ack_skb */
+		if (ack_skb)
+			skb_complete_wifi_ack(ack_skb,
+				info->flags & IEEE80211_TX_STAT_ACK);
+	}
+
 	/* this was a transmitted frame, but now we want to reuse it */
 	skb_orphan(skb);
 
@@ -621,6 +639,26 @@ EXPORT_SYMBOL(ieee80211_report_low_ack);
 
 void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
+	struct ieee80211_local *local = hw_to_local(hw);
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	if (unlikely(info->ack_frame_id)) {
+		struct sk_buff *ack_skb;
+		unsigned long flags;
+
+		spin_lock_irqsave(&local->ack_status_lock, flags);
+		ack_skb = idr_find(&local->ack_status_frames,
+				   info->ack_frame_id);
+		if (ack_skb)
+			idr_remove(&local->ack_status_frames,
+				   info->ack_frame_id);
+		spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+		/* consumes ack_skb */
+		if (ack_skb)
+			dev_kfree_skb_any(ack_skb);
+	}
+
 	dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL(ieee80211_free_txskb);
--- a/net/mac80211/tx.c	2011-10-21 10:20:38.000000000 +0200
+++ b/net/mac80211/tx.c	2011-10-21 12:07:46.000000000 +0200
@@ -1684,8 +1684,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	int nh_pos, h_pos;
 	struct sta_info *sta = NULL;
 	bool wme_sta = false, authorized = false, tdls_auth = false;
-	struct sk_buff *tmp_skb;
 	bool tdls_direct = false;
+	bool multicast;
+	u32 info_flags = 0;
+	u16 info_id = 0;
 
 	if (unlikely(skb->len < ETH_HLEN)) {
 		ret = NETDEV_TX_OK;
@@ -1872,7 +1874,8 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	 * if it is a multicast address (which can only happen
 	 * in AP mode)
 	 */
-	if (!is_multicast_ether_addr(hdr.addr1)) {
+	multicast = is_multicast_ether_addr(hdr.addr1);
+	if (!multicast) {
 		rcu_read_lock();
 		sta = sta_info_get(sdata, hdr.addr1);
 		if (sta) {
@@ -1913,11 +1916,54 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 		goto fail;
 	}
 
+	if (unlikely(!multicast && skb->sk &&
+		     skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS)) {
+		struct sk_buff *orig_skb = skb;
+
+		skb = skb_clone(skb, GFP_ATOMIC);
+		if (skb) {
+			unsigned long flags;
+			int id, r;
+
+			spin_lock_irqsave(&local->ack_status_lock, flags);
+			r = idr_get_new_above(&local->ack_status_frames,
+					      orig_skb, 1, &id);
+			if (r == -EAGAIN) {
+				idr_pre_get(&local->ack_status_frames,
+					    GFP_ATOMIC);
+				r = idr_get_new_above(&local->ack_status_frames,
+						      orig_skb, 1, &id);
+			}
+			if (WARN_ON(!id) || id > 0xffff) {
+				idr_remove(&local->ack_status_frames, id);
+				r = -ERANGE;
+			}
+			spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+			if (!r) {
+				info_id = id;
+				info_flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
+			} else if (skb_shared(skb)) {
+				kfree_skb(orig_skb);
+			} else {
+				kfree_skb(skb);
+				skb = orig_skb;
+			}
+		} else {
+			/* couldn't clone -- lose tx status ... */
+			skb = orig_skb;
+		}
+	}
+
 	/*
 	 * If the skb is shared we need to obtain our own copy.
 	 */
 	if (skb_shared(skb)) {
-		tmp_skb = skb;
+		struct sk_buff *tmp_skb = skb;
+
+		/* can't happen -- skb is a clone if info_id != 0 */
+		WARN_ON(info_id);
+
 		skb = skb_clone(skb, GFP_ATOMIC);
 		kfree_skb(tmp_skb);
 
@@ -2018,6 +2064,10 @@ netdev_tx_t ieee80211_subif_start_xmit(s
 	memset(info, 0, sizeof(*info));
 
 	dev->trans_start = jiffies;
+
+	info->flags = info_flags;
+	info->ack_frame_id = info_id;
+
 	ieee80211_xmit(sdata, skb);
 
 	return NETDEV_TX_OK;
--- a/include/net/mac80211.h	2011-10-21 12:07:38.000000000 +0200
+++ b/include/net/mac80211.h	2011-10-21 12:07:46.000000000 +0200
@@ -518,7 +518,7 @@ struct ieee80211_tx_rate {
  * @flags: transmit info flags, defined above
  * @band: the band to transmit on (use for checking for races)
  * @antenna_sel_tx: antenna to use, 0 for automatic diversity
- * @pad: padding, ignore
+ * @ack_frame_id: internal frame ID for TX status, used internally
  * @control: union for control data
  * @status: union for status data
  * @driver_data: array of driver_data pointers
@@ -535,8 +535,7 @@ struct ieee80211_tx_info {
 
 	u8 antenna_sel_tx;
 
-	/* 2 byte hole */
-	u8 pad[2];
+	u16 ack_frame_id;
 
 	union {
 		struct {
--- a/net/mac80211/ieee80211_i.h	2011-10-21 12:07:37.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h	2011-10-21 12:07:46.000000000 +0200
@@ -24,6 +24,7 @@
 #include <linux/spinlock.h>
 #include <linux/etherdevice.h>
 #include <linux/leds.h>
+#include <linux/idr.h>
 #include <net/ieee80211_radiotap.h>
 #include <net/cfg80211.h>
 #include <net/mac80211.h>
@@ -1013,6 +1014,9 @@ struct ieee80211_local {
 	u32 hw_roc_cookie;
 	bool hw_roc_for_tx;
 
+	struct idr ack_status_frames;
+	spinlock_t ack_status_lock;
+
 	/* dummy netdev for use w/ NAPI */
 	struct net_device napi_dev;
 
--- a/net/mac80211/main.c	2011-10-21 10:20:37.000000000 +0200
+++ b/net/mac80211/main.c	2011-10-21 12:07:46.000000000 +0200
@@ -597,6 +597,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 			WIPHY_FLAG_4ADDR_AP |
 			WIPHY_FLAG_4ADDR_STATION;
 
+	wiphy->features = NL80211_FEATURE_SK_TX_STATUS;
+
 	if (!ops->set_key)
 		wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
 
@@ -670,6 +672,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 	INIT_WORK(&local->sched_scan_stopped_work,
 		  ieee80211_sched_scan_stopped_work);
 
+	spin_lock_init(&local->ack_status_lock);
+	idr_init(&local->ack_status_frames);
+	/* preallocate at least one entry */
+	idr_pre_get(&local->ack_status_frames, GFP_KERNEL);
+
 	sta_info_init(local);
 
 	for (i = 0; i < IEEE80211_MAX_QUEUES; i++) {
@@ -1045,6 +1052,13 @@ void ieee80211_unregister_hw(struct ieee
 }
 EXPORT_SYMBOL(ieee80211_unregister_hw);
 
+static int ieee80211_free_ack_frame(int id, void *p, void *data)
+{
+	WARN_ONCE(1, "Have pending ack frames!\n");
+	kfree_skb(p);
+	return 0;
+}
+
 void ieee80211_free_hw(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -1055,6 +1069,10 @@ void ieee80211_free_hw(struct ieee80211_
 	if (local->wiphy_ciphers_allocated)
 		kfree(local->hw.wiphy->cipher_suites);
 
+	idr_for_each(&local->ack_status_frames,
+		     ieee80211_free_ack_frame, NULL);
+	idr_destroy(&local->ack_status_frames);
+
 	wiphy_free(local->hw.wiphy);
 }
 EXPORT_SYMBOL(ieee80211_free_hw);



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

* [RFC v2 11/12] cfg80211: allow registering to beacons
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (9 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 10/12] mac80211: implement wifi TX status Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-21 14:23 ` [RFC v2 12/12] mac80211: report OBSS beacons Johannes Berg
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

Add the ability to register to received beacon frames
to allow implementing OLBC logic in userspace. The
registration is per wiphy since there's no point in
receiving the same frame multiple times.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/nl80211.h |    7 ++++
 include/net/cfg80211.h  |   20 +++++++++++++
 net/wireless/core.h     |    2 +
 net/wireless/nl80211.c  |   70 +++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 98 insertions(+), 1 deletion(-)

--- a/net/wireless/core.h	2011-10-21 12:07:56.000000000 +0200
+++ b/net/wireless/core.h	2011-10-21 13:10:17.000000000 +0200
@@ -54,6 +54,8 @@ struct cfg80211_registered_device {
 	int opencount; /* also protected by devlist_mtx */
 	wait_queue_head_t dev_wait;
 
+	u32 ap_beacons_nlpid;
+
 	/* BSSes/scanning */
 	spinlock_t bss_lock;
 	struct list_head bss_list;
--- a/include/linux/nl80211.h	2011-10-21 12:07:45.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-21 13:15:22.000000000 +0200
@@ -528,6 +528,11 @@
  *	up the event with the request. The event includes the same data and
  *	has %NL80211_ATTR_ACK set if the frame was ACKed.
  *
+ * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from
+ *	other BSSes when any interfaces are in AP mode. This helps implement
+ *	OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME
+ *	messages. Note that per PHY only one application may register.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -661,6 +666,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_PROBE_CLIENT,
 
+	NL80211_CMD_REGISTER_BEACONS,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
--- a/net/wireless/nl80211.c	2011-10-21 12:07:45.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-21 13:56:35.000000000 +0200
@@ -892,6 +892,10 @@ static int nl80211_send_wiphy(struct sk_
 	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
 		CMD(sched_scan_start, START_SCHED_SCAN);
 	CMD(probe_client, PROBE_CLIENT);
+	if (dev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS) {
+		i++;
+		NLA_PUT_U32(msg, i, NL80211_CMD_REGISTER_BEACONS);
+	}
 
 #undef CMD
 
@@ -5904,6 +5908,21 @@ static int nl80211_probe_client(struct s
 	return err;
 }
 
+static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+
+	if (!(rdev->wiphy.flags & WIPHY_FLAG_REPORTS_OBSS))
+		return -EOPNOTSUPP;
+
+	if (rdev->ap_beacons_nlpid)
+		return -EBUSY;
+
+	rdev->ap_beacons_nlpid = info->snd_pid;
+
+	return 0;
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -6475,6 +6494,14 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_REGISTER_BEACONS,
+		.doit = nl80211_register_beacons,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_WIPHY |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -7638,6 +7665,44 @@ void cfg80211_probe_status(struct net_de
 }
 EXPORT_SYMBOL(cfg80211_probe_status);
 
+void cfg80211_report_obss_beacon(struct wiphy *wiphy,
+				 const u8 *frame, size_t len,
+				 int freq, gfp_t gfp)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+	u32 nlpid = ACCESS_ONCE(rdev->ap_beacons_nlpid);
+
+	if (!nlpid)
+		return;
+
+	msg = nlmsg_new(len + 100, gfp);
+	if (!msg)
+		return;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FRAME);
+	if (!hdr) {
+		nlmsg_free(msg);
+		return;
+	}
+
+	NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+	if (freq)
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq);
+	NLA_PUT(msg, NL80211_ATTR_FRAME, len, frame);
+
+	genlmsg_end(msg, hdr);
+
+	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlpid);
+	return;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+	nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_report_obss_beacon);
+
 static int nl80211_netlink_notify(struct notifier_block * nb,
 				  unsigned long state,
 				  void *_notify)
@@ -7651,9 +7716,12 @@ static int nl80211_netlink_notify(struct
 
 	rcu_read_lock();
 
-	list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list)
+	list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
 		list_for_each_entry_rcu(wdev, &rdev->netdev_list, list)
 			cfg80211_mlme_unregister_socket(wdev, notify->pid);
+		if (rdev->ap_beacons_nlpid == notify->pid)
+			rdev->ap_beacons_nlpid = 0;
+	}
 
 	rcu_read_unlock();
 
--- a/include/net/cfg80211.h	2011-10-21 12:07:45.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-21 13:30:37.000000000 +0200
@@ -1682,6 +1682,9 @@ struct cfg80211_ops {
  *	command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
  *	used for asking the driver/firmware to perform a TDLS operation.
  * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
+ * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
+ *	when there are virtual interfaces in AP mode by calling
+ *	cfg80211_report_obss_beacon().
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1701,6 +1704,7 @@ enum wiphy_flags {
 	WIPHY_FLAG_SUPPORTS_TDLS		= BIT(15),
 	WIPHY_FLAG_TDLS_EXTERNAL_SETUP		= BIT(16),
 	WIPHY_FLAG_HAVE_AP_SME			= BIT(17),
+	WIPHY_FLAG_REPORTS_OBSS			= BIT(18),
 };
 
 /**
@@ -3228,6 +3232,22 @@ bool cfg80211_rx_spurious_frame(struct n
 void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
 			   u64 cookie, bool acked, gfp_t gfp);
 
+/**
+ * cfg80211_report_obss_beacon - report beacon from other APs
+ * @wiphy: The wiphy that received the beacon
+ * @frame: the frame
+ * @len: length of the frame
+ * @freq: frequency the frame was received on
+ * @gfp: allocation flags
+ *
+ * Use this function to report to userspace when a beacon was
+ * received. It is not useful to call this when there is no
+ * netdev that is in AP/GO mode.
+ */
+void cfg80211_report_obss_beacon(struct wiphy *wiphy,
+				 const u8 *frame, size_t len,
+				 int freq, gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */



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

* [RFC v2 12/12] mac80211: report OBSS beacons
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (10 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 11/12] cfg80211: allow registering to beacons Johannes Berg
@ 2011-10-21 14:23 ` Johannes Berg
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
  12 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-21 14:23 UTC (permalink / raw)
  To: linux-wireless

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

If there's an interface in AP mode, OBSS beacons
are needed by hostapd/wpa_s to implement logic to
enable/disable protection etc. Report the frames
and set the capability flag.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ieee80211_i.h |    3 +++
 net/mac80211/main.c        |    3 ++-
 net/mac80211/rx.c          |   12 ++++++++++++
 3 files changed, 17 insertions(+), 1 deletion(-)

--- a/net/mac80211/ieee80211_i.h	2011-10-21 13:45:46.000000000 +0200
+++ b/net/mac80211/ieee80211_i.h	2011-10-21 15:30:40.000000000 +0200
@@ -185,12 +185,15 @@ enum ieee80211_packet_rx_flags {
  * enum ieee80211_rx_flags - RX data flags
  *
  * @IEEE80211_RX_CMNTR: received on cooked monitor already
+ * @IEEE80211_RX_BEACON_REPORTED: This frame was already reported
+ *	to cfg80211_report_obss_beacon().
  *
  * These flags are used across handling multiple interfaces
  * for a single frame.
  */
 enum ieee80211_rx_flags {
 	IEEE80211_RX_CMNTR		= BIT(0),
+	IEEE80211_RX_BEACON_REPORTED	= BIT(1),
 };
 
 struct ieee80211_rx_data {
--- a/net/mac80211/main.c	2011-10-21 13:45:46.000000000 +0200
+++ b/net/mac80211/main.c	2011-10-21 15:30:40.000000000 +0200
@@ -595,7 +595,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(
 
 	wiphy->flags |= WIPHY_FLAG_NETNS_OK |
 			WIPHY_FLAG_4ADDR_AP |
-			WIPHY_FLAG_4ADDR_STATION;
+			WIPHY_FLAG_4ADDR_STATION |
+			WIPHY_FLAG_REPORTS_OBSS;
 
 	wiphy->features = NL80211_FEATURE_SK_TX_STATUS;
 
--- a/net/mac80211/rx.c	2011-10-21 13:45:46.000000000 +0200
+++ b/net/mac80211/rx.c	2011-10-21 16:19:29.000000000 +0200
@@ -2177,6 +2177,18 @@ ieee80211_rx_h_mgmt_check(struct ieee802
 	if (!ieee80211_is_mgmt(mgmt->frame_control))
 		return RX_DROP_MONITOR;
 
+	if (rx->sdata->vif.type == NL80211_IFTYPE_AP &&
+	    ieee80211_is_beacon(mgmt->frame_control) &&
+	    !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
+		struct ieee80211_rx_status *status;
+
+		status = IEEE80211_SKB_RXCB(rx->skb);
+		cfg80211_report_obss_beacon(rx->local->hw.wiphy,
+					    rx->skb->data, rx->skb->len,
+					    status->freq, GFP_ATOMIC);
+		rx->flags |= IEEE80211_RX_BEACON_REPORTED;
+	}
+
 	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
 		return RX_DROP_MONITOR;
 



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

* Re: [RFC v2 05/12] nl80211: advertise device AP SME
  2011-10-21 14:23 ` [RFC v2 05/12] nl80211: advertise device AP SME Johannes Berg
@ 2011-10-25 10:13   ` Eliad Peller
  0 siblings, 0 replies; 31+ messages in thread
From: Eliad Peller @ 2011-10-25 10:13 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On Fri, Oct 21, 2011 at 4:23 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Add the ability to advertise that the device
> contains the AP SME and what features it can
> support.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
[...]
> --- a/include/linux/nl80211.h   2011-10-21 12:07:39.000000000 +0200
> +++ b/include/linux/nl80211.h   2011-10-21 12:07:41.000000000 +0200
> @@ -1122,6 +1122,11 @@ enum nl80211_commands {
>  *     %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
>  *     used for asking the driver to perform a TDLS operation.
>  *
> + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices
> + *     that have AP support to indicate that the have the AP SME integrated
s/the/they

> + *     with support for the features listed in this attribute, see
> + *     &enum nl80211_ap_sme_features.
> + *

>  * @NL80211_ATTR_MAX: highest attribute number currently defined
>  * @__NL80211_ATTR_AFTER_LAST: internal use
>  */
> @@ -1350,6 +1355,8 @@ enum nl80211_attrs {
>        NL80211_ATTR_TDLS_SUPPORT,
>        NL80211_ATTR_TDLS_EXTERNAL_SETUP,
>
> +       NL80211_ATTR_DEVICE_AP_MLME,
> +

the attribute name is different from the documented one (SME/MLME)

Eliad.

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

* Re: [RFC v2 08/12] net: add wireless TX status socket option
  2011-10-21 14:23 ` [RFC v2 08/12] net: add wireless TX status socket option Johannes Berg
@ 2011-10-25 10:40   ` Eliad Peller
  0 siblings, 0 replies; 31+ messages in thread
From: Eliad Peller @ 2011-10-25 10:40 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On Fri, Oct 21, 2011 at 4:23 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> The 802.1X EAPOL handshake hostapd does requires
> knowing whether the frame was ack'ed by the peer.
> Currently, we fudge this pretty badly by not even
> transmitting the frame as a normal data frame but
> injecting it with radiotap and getting the status
> out of radiotap monitor as well. This is rather
> complex, confuses users (mon.wlan0 presence) and
> doesn't work with all hardware.
>
> To get rid of that hack, introduce a real wifi TX
> status option for data frame transmissions.
>
> This works similar to the existing TX timestamping
> in that it reflects the SKB back to the socket's
> error queue with a SCM_WIFI_STATUS cmsg that has
> an int indicating ACK status (0/1).
>
> Since it is possible that at some point we will
> want to have TX timestamping and wifi status in a
> single errqueue SKB (there's little point in not
> doing that), redefine SO_EE_ORIGIN_TIMESTAMPING
> to SO_EE_ORIGIN_TXSTATUS which can collect more
> than just the timestamp; keep the old constant
> as an alias of course. Currently the internal APIs
> don't make that possible, but it wouldn't be hard
> to split them up in a way that makes it possible.
>
> Thanks to Neil Horman for helping me figure out
> the functions that add the control messages.
>
> TODO:
>  * sock_tx_timestamp() function should be renamed,
>   maybe to sock_tx_status()?
>  * sock_recv_timestamp() should also be renamed,
>   I had a hard time figuring out the difference
>   between that and sock_recv_ts_and_drops(). The
>   former is generic, while the latter adds RX
>   information only, maybe that should be reflected
>   in new names?
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
[...]
>        __u8                    ooo_okay:1;
> +       __u8                    wifi_acked_valid:1;
> +       __u8                    wifi_acked:1;
> +       /* 11/13 bit hole (depending on nodetype presence) */
>        kmemcheck_bitfield_end(flags2);
>
>
> +void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
> +{
> +       struct sock *sk = skb->sk;
> +       struct sock_exterr_skb *serr;
> +       int err;
> +
> +       skb->wifi_acked_valid = 1;
> +       skb->wifi_acked = acked;
> +

i'm not sure it's an actual issue, but setting (u8:1) = (bool) seems wrong?

Eliad.

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

* [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
                   ` (11 preceding siblings ...)
  2011-10-21 14:23 ` [RFC v2 12/12] mac80211: report OBSS beacons Johannes Berg
@ 2011-10-27 19:32 ` Johannes Berg
  2011-10-27 22:44   ` Eliad Peller
                     ` (3 more replies)
  12 siblings, 4 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-27 19:32 UTC (permalink / raw)
  To: linux-wireless

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

For probe responses it can be useful to not wait for ACK
to save airtime, so allow userspace to request not waiting
with a new nl80211 flag.

Since mac80211 needs to be updated for the new function
prototype anyway implement it right away -- it's just a
few lines of code.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/ath/ath6kl/cfg80211.c |    3 +-
 include/linux/nl80211.h                    |    7 ++++
 include/net/cfg80211.h                     |    2 -
 net/mac80211/cfg.c                         |   11 +++++--
 net/wireless/core.h                        |    2 -
 net/wireless/mlme.c                        |    5 ++-
 net/wireless/nl80211.c                     |   43 +++++++++++++++++------------
 7 files changed, 48 insertions(+), 25 deletions(-)

--- a/include/linux/nl80211.h	2011-10-27 21:08:01.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-27 21:13:13.000000000 +0200
@@ -1147,6 +1147,11 @@ enum nl80211_commands {
  * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
  *	&enum nl80211_feature_flags and is advertised in wiphy information.
  *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ *	the driver to not wait for an acknowledgement. Note that due to this,
+ *	it will also not give a status callback nor return a cookie. This is
+ *	mostly useful for probe responses to save airtime.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1379,6 +1384,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_FEATURE_FLAGS,
 
+	NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
--- a/net/wireless/core.h	2011-10-27 21:08:01.000000000 +0200
+++ b/net/wireless/core.h	2011-10-27 21:12:23.000000000 +0200
@@ -378,7 +378,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie);
+			  bool dont_wait_for_ack, u64 *cookie);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
--- a/net/wireless/mlme.c	2011-10-27 21:08:01.000000000 +0200
+++ b/net/wireless/mlme.c	2011-10-27 21:13:52.000000000 +0200
@@ -904,7 +904,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie)
+			  bool dont_wait_for_ack, u64 *cookie)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	const struct ieee80211_mgmt *mgmt;
@@ -995,7 +995,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 	/* Transmit the Action frame as requested by user space */
 	return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
 				  channel_type, channel_type_valid,
-				  wait, buf, len, no_cck, cookie);
+				  wait, buf, len, no_cck, dont_wait_for_ack,
+				  cookie);
 }
 
 bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
--- a/net/wireless/nl80211.c	2011-10-27 21:08:01.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-27 21:14:45.000000000 +0200
@@ -197,6 +197,7 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+	[NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -5279,10 +5280,11 @@ static int nl80211_tx_mgmt(struct sk_buf
 	int err;
 	void *hdr;
 	u64 cookie;
-	struct sk_buff *msg;
+	struct sk_buff *msg = NULL;
 	unsigned int wait = 0;
-	bool offchan;
-	bool no_cck;
+	bool offchan, no_cck, dont_wait_for_ack;
+
+	dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
 
 	if (!info->attrs[NL80211_ATTR_FRAME] ||
 	    !info->attrs[NL80211_ATTR_WIPHY_FREQ])
@@ -5326,29 +5328,36 @@ static int nl80211_tx_mgmt(struct sk_buf
 	if (chan == NULL)
 		return -EINVAL;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
-			     NL80211_CMD_FRAME);
-
-	if (IS_ERR(hdr)) {
-		err = PTR_ERR(hdr);
-		goto free_msg;
+	if (!dont_wait_for_ack) {
+		msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+		if (!msg)
+			return -ENOMEM;
+
+		hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+				     NL80211_CMD_FRAME);
+
+		if (IS_ERR(hdr)) {
+			err = PTR_ERR(hdr);
+			goto free_msg;
+		}
 	}
+
 	err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
 				    channel_type_valid, wait,
 				    nla_data(info->attrs[NL80211_ATTR_FRAME]),
 				    nla_len(info->attrs[NL80211_ATTR_FRAME]),
-				    no_cck, &cookie);
+				    no_cck, dont_wait_for_ack, &cookie);
 	if (err)
 		goto free_msg;
 
-	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+	if (msg) {
+		NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
 
-	genlmsg_end(msg, hdr);
-	return genlmsg_reply(msg, info);
+		genlmsg_end(msg, hdr);
+		return genlmsg_reply(msg, info);
+	}
+
+	return 0;
 
  nla_put_failure:
 	err = -ENOBUFS;
--- a/include/net/cfg80211.h	2011-10-27 21:08:01.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-27 21:15:55.000000000 +0200
@@ -1584,7 +1584,7 @@ struct cfg80211_ops {
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie);
+			  bool dont_wait_for_ack, u64 *cookie);
 	int	(*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       u64 cookie);
--- a/net/mac80211/cfg.c	2011-10-27 21:08:01.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-27 21:23:44.000000000 +0200
@@ -1936,7 +1936,7 @@ static int ieee80211_mgmt_tx(struct wiph
 			     enum nl80211_channel_type channel_type,
 			     bool channel_type_valid, unsigned int wait,
 			     const u8 *buf, size_t len, bool no_cck,
-			     u64 *cookie)
+			     bool dont_wait_for_ack, u64 *cookie)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
@@ -1944,10 +1944,15 @@ static int ieee80211_mgmt_tx(struct wiph
 	struct sta_info *sta;
 	struct ieee80211_work *wk;
 	const struct ieee80211_mgmt *mgmt = (void *)buf;
-	u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
-		    IEEE80211_TX_CTL_REQ_TX_STATUS;
+	u32 flags;
 	bool is_offchan = false;
 
+	if (!dont_wait_for_ack)
+		flags = IEEE80211_TX_CTL_NO_ACK;
+	else
+		flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
+			IEEE80211_TX_CTL_REQ_TX_STATUS;
+
 	/* Check that we are on the requested channel for transmission */
 	if (chan != local->tmp_channel &&
 	    chan != local->oper_channel)
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c	2011-10-12 19:22:47.000000000 +0200
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c	2011-10-27 21:21:11.000000000 +0200
@@ -1732,7 +1732,8 @@ static int ath6kl_mgmt_tx(struct wiphy *
 			  struct ieee80211_channel *chan, bool offchan,
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
-			  const u8 *buf, size_t len, bool no_cck, u64 *cookie)
+			  const u8 *buf, size_t len, bool no_cck,
+			  bool dont_wait_for_ack, u64 *cookie)
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	u32 id;



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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
@ 2011-10-27 22:44   ` Eliad Peller
  2011-10-28  8:02     ` Johannes Berg
  2011-10-28  6:09   ` Helmut Schaa
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 31+ messages in thread
From: Eliad Peller @ 2011-10-27 22:44 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On Thu, Oct 27, 2011 at 9:32 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> For probe responses it can be useful to not wait for ACK
> to save airtime, so allow userspace to request not waiting
> with a new nl80211 flag.
>
> Since mac80211 needs to be updated for the new function
> prototype anyway implement it right away -- it's just a
> few lines of code.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
[RFC v2 13/12] ? :)

>        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
>        struct ieee80211_local *local = sdata->local;
> @@ -1944,10 +1944,15 @@ static int ieee80211_mgmt_tx(struct wiph
>        struct sta_info *sta;
>        struct ieee80211_work *wk;
>        const struct ieee80211_mgmt *mgmt = (void *)buf;
> -       u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
> -                   IEEE80211_TX_CTL_REQ_TX_STATUS;
> +       u32 flags;
>        bool is_offchan = false;
>
> +       if (!dont_wait_for_ack)
> +               flags = IEEE80211_TX_CTL_NO_ACK;
> +       else
> +               flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
> +                       IEEE80211_TX_CTL_REQ_TX_STATUS;
> +

shouldn't it be the other way around? (i.e. set NO_ACK if dont_wait_for_ack)

Eliad.

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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
  2011-10-27 22:44   ` Eliad Peller
@ 2011-10-28  6:09   ` Helmut Schaa
  2011-10-28  7:34     ` Johannes Berg
  2011-10-28  7:48   ` Arend Van Spriel
  2011-10-28  9:18   ` [RFC v3 " Johannes Berg
  3 siblings, 1 reply; 31+ messages in thread
From: Helmut Schaa @ 2011-10-28  6:09 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On Thu, Oct 27, 2011 at 9:32 PM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> For probe responses it can be useful to not wait for ACK
> to save airtime, so allow userspace to request not waiting
> with a new nl80211 flag.
>
> Since mac80211 needs to be updated for the new function
> prototype anyway implement it right away -- it's just a
> few lines of code.

Ah, nice!

I'll adjust my hostad patch to make use of this instead of the
radiotap flag (or maybe both, need to look into this further).

Helmut

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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  6:09   ` Helmut Schaa
@ 2011-10-28  7:34     ` Johannes Berg
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-28  7:34 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: linux-wireless

On Fri, 2011-10-28 at 08:09 +0200, Helmut Schaa wrote:
> On Thu, Oct 27, 2011 at 9:32 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> >
> > For probe responses it can be useful to not wait for ACK
> > to save airtime, so allow userspace to request not waiting
> > with a new nl80211 flag.
> >
> > Since mac80211 needs to be updated for the new function
> > prototype anyway implement it right away -- it's just a
> > few lines of code.
> 
> Ah, nice!
> 
> I'll adjust my hostad patch to make use of this instead of the
> radiotap flag (or maybe both, need to look into this further).

If you just do the radiotap part I'll add the rest with my other
patchset.

johannes


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

* RE: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
  2011-10-27 22:44   ` Eliad Peller
  2011-10-28  6:09   ` Helmut Schaa
@ 2011-10-28  7:48   ` Arend Van Spriel
  2011-10-28  7:52     ` Helmut Schaa
  2011-10-28  8:01     ` Johannes Berg
  2011-10-28  9:18   ` [RFC v3 " Johannes Berg
  3 siblings, 2 replies; 31+ messages in thread
From: Arend Van Spriel @ 2011-10-28  7:48 UTC (permalink / raw)
  To: Johannes Berg, linux-wireless

PiBTZW50OiBkb25kZXJkYWcgMjcgb2t0b2JlciAyMDExIDIxOjMzDQo+IEZyb206IEpvaGFubmVz
IEJlcmcgPGpvaGFubmVzLmJlcmdAaW50ZWwuY29tPg0KPiANCj4gRm9yIHByb2JlIHJlc3BvbnNl
cyBpdCBjYW4gYmUgdXNlZnVsIHRvIG5vdCB3YWl0IGZvciBBQ0sNCj4gdG8gc2F2ZSBhaXJ0aW1l
LCBzbyBhbGxvdyB1c2Vyc3BhY2UgdG8gcmVxdWVzdCBub3Qgd2FpdGluZw0KPiB3aXRoIGEgbmV3
IG5sODAyMTEgZmxhZy4NCj4gDQo+IFNpbmNlIG1hYzgwMjExIG5lZWRzIHRvIGJlIHVwZGF0ZWQg
Zm9yIHRoZSBuZXcgZnVuY3Rpb24NCj4gcHJvdG90eXBlIGFueXdheSBpbXBsZW1lbnQgaXQgcmln
aHQgYXdheSAtLSBpdCdzIGp1c3QgYQ0KPiBmZXcgbGluZXMgb2YgY29kZS4NCj4gDQo+IFNpZ25l
ZC1vZmYtYnk6IEpvaGFubmVzIEJlcmcgPGpvaGFubmVzLmJlcmdAaW50ZWwuY29tPg0KPiAtLS0N
Cg0KSGkgSm9oYW5uZXMsDQoNCkkgd291bGQgZXhwZWN0IHRoaXMgdG8gYWZmZWN0IHRoZSBkdXJh
dGlvbiBmaWVsZCBpbiB0aGUNCjgwMi4xMSBoZWFkZXIgdG8gaW5kaWNhdGUgdGhlIHNob3J0ZXIg
dXNlIG9mIHRoZSBtZWRpdW0uDQpHb2luZyB0aHJvdWdoIHlvdXIgcGF0Y2ggSSBhbSBub3Qgc3Vy
ZSB0aGlzIGlzIGRvbmUuDQoNCkdyLiBBdlMNCg==


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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  7:48   ` Arend Van Spriel
@ 2011-10-28  7:52     ` Helmut Schaa
  2011-10-28  9:07       ` Arend Van Spriel
  2011-10-28  8:01     ` Johannes Berg
  1 sibling, 1 reply; 31+ messages in thread
From: Helmut Schaa @ 2011-10-28  7:52 UTC (permalink / raw)
  To: Arend Van Spriel; +Cc: Johannes Berg, linux-wireless

On Fri, Oct 28, 2011 at 9:48 AM, Arend Van Spriel <arend@broadcom.com> wrote:
> I would expect this to affect the duration field in the
> 802.11 header to indicate the shorter use of the medium.
> Going through your patch I am not sure this is done.

I don't think so since the frame will still be acked by the peer as it is
a unicast management frame. But this will advise the hardware that it
does not need to wait for the ack to happen since we're not interested
in retrying it.

Helmut

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

* RE: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  7:48   ` Arend Van Spriel
  2011-10-28  7:52     ` Helmut Schaa
@ 2011-10-28  8:01     ` Johannes Berg
  2011-10-28  9:10       ` Arend Van Spriel
  1 sibling, 1 reply; 31+ messages in thread
From: Johannes Berg @ 2011-10-28  8:01 UTC (permalink / raw)
  To: Arend Van Spriel; +Cc: linux-wireless

On Fri, 2011-10-28 at 00:48 -0700, Arend Van Spriel wrote:
> > Sent: donderdag 27 oktober 2011 21:33
> > From: Johannes Berg <johannes.berg@intel.com>
> > 
> > For probe responses it can be useful to not wait for ACK
> > to save airtime, so allow userspace to request not waiting
> > with a new nl80211 flag.
> > 
> > Since mac80211 needs to be updated for the new function
> > prototype anyway implement it right away -- it's just a
> > few lines of code.

> I would expect this to affect the duration field in the
> 802.11 header to indicate the shorter use of the medium.
> Going through your patch I am not sure this is done.

Hmmm. You're right, but that's something we already need to fix in many
cases -- as the duration field is overwritten by most hardware these
days, we haven't always maintained it very well.

Your driver seems to be the exception to this -- maybe you can look into
fixing up the duration calculations? Also for 11n which isn't taken into
account at all today.

johannes


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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-27 22:44   ` Eliad Peller
@ 2011-10-28  8:02     ` Johannes Berg
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-28  8:02 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless

On Fri, 2011-10-28 at 00:44 +0200, Eliad Peller wrote:
> On Thu, Oct 27, 2011 at 9:32 PM, Johannes Berg
> <johannes@sipsolutions.net> wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> >
> > For probe responses it can be useful to not wait for ACK
> > to save airtime, so allow userspace to request not waiting
> > with a new nl80211 flag.
> >
> > Since mac80211 needs to be updated for the new function
> > prototype anyway implement it right away -- it's just a
> > few lines of code.
> >
> > Signed-off-by: Johannes Berg <johannes.berg@intel.com>

> [RFC v2 13/12] ? :)

Too lazy to send a new patchset and it really belonged with this :-)

> > +       if (!dont_wait_for_ack)
> > +               flags = IEEE80211_TX_CTL_NO_ACK;
> > +       else
> > +               flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
> > +                       IEEE80211_TX_CTL_REQ_TX_STATUS;
> > +
> 
> shouldn't it be the other way around? (i.e. set NO_ACK if dont_wait_for_ack)

Doh, of course, thanks. I was editing this code a few times -- guess I
lost track.

johannes


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

* RE: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  7:52     ` Helmut Schaa
@ 2011-10-28  9:07       ` Arend Van Spriel
  2011-10-28  9:15         ` Johannes Berg
  0 siblings, 1 reply; 31+ messages in thread
From: Arend Van Spriel @ 2011-10-28  9:07 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Johannes Berg, linux-wireless

> From: Helmut Schaa [mailto:helmut.schaa@googlemail.com]
> Sent: vrijdag 28 oktober 2011 9:52
> 
> On Fri, Oct 28, 2011 at 9:48 AM, Arend Van Spriel <arend@broadcom.com>
> wrote:
> > I would expect this to affect the duration field in the
> > 802.11 header to indicate the shorter use of the medium.
> > Going through your patch I am not sure this is done.
> 
> I don't think so since the frame will still be acked by the peer as it
> is
> a unicast management frame. But this will advise the hardware that it
> does not need to wait for the ack to happen since we're not interested
> in retrying it.
> 
> Helmut

Hi Helmut,

I understand. However, the commit message of this patch suggests we are
saving airtime, which does not seem the case if the duration field is
not taken into account. If the ACK is still transmitted we should not
touch the duration field so I guess my comment is only on the commit
message itself.

The whole duration field usage is another topic.

Gr. AvS


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

* RE: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  8:01     ` Johannes Berg
@ 2011-10-28  9:10       ` Arend Van Spriel
  2011-10-28  9:28         ` Helmut Schaa
  0 siblings, 1 reply; 31+ messages in thread
From: Arend Van Spriel @ 2011-10-28  9:10 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

PiBGcm9tOiBKb2hhbm5lcyBCZXJnIFttYWlsdG86am9oYW5uZXNAc2lwc29sdXRpb25zLm5ldF0N
Cj4gU2VudDogdnJpamRhZyAyOCBva3RvYmVyIDIwMTEgMTA6MDENCj4gDQo+IE9uIEZyaSwgMjAx
MS0xMC0yOCBhdCAwMDo0OCAtMDcwMCwgQXJlbmQgVmFuIFNwcmllbCB3cm90ZToNCj4gPiA+IFNl
bnQ6IGRvbmRlcmRhZyAyNyBva3RvYmVyIDIwMTEgMjE6MzMNCj4gPiA+IEZyb206IEpvaGFubmVz
IEJlcmcgPGpvaGFubmVzLmJlcmdAaW50ZWwuY29tPg0KPiA+ID4NCj4gPiA+IEZvciBwcm9iZSBy
ZXNwb25zZXMgaXQgY2FuIGJlIHVzZWZ1bCB0byBub3Qgd2FpdCBmb3IgQUNLDQo+ID4gPiB0byBz
YXZlIGFpcnRpbWUsIHNvIGFsbG93IHVzZXJzcGFjZSB0byByZXF1ZXN0IG5vdCB3YWl0aW5nDQo+
ID4gPiB3aXRoIGEgbmV3IG5sODAyMTEgZmxhZy4NCj4gPiA+DQo+ID4gPiBTaW5jZSBtYWM4MDIx
MSBuZWVkcyB0byBiZSB1cGRhdGVkIGZvciB0aGUgbmV3IGZ1bmN0aW9uDQo+ID4gPiBwcm90b3R5
cGUgYW55d2F5IGltcGxlbWVudCBpdCByaWdodCBhd2F5IC0tIGl0J3MganVzdCBhDQo+ID4gPiBm
ZXcgbGluZXMgb2YgY29kZS4NCj4gDQo+ID4gSSB3b3VsZCBleHBlY3QgdGhpcyB0byBhZmZlY3Qg
dGhlIGR1cmF0aW9uIGZpZWxkIGluIHRoZQ0KPiA+IDgwMi4xMSBoZWFkZXIgdG8gaW5kaWNhdGUg
dGhlIHNob3J0ZXIgdXNlIG9mIHRoZSBtZWRpdW0uDQo+ID4gR29pbmcgdGhyb3VnaCB5b3VyIHBh
dGNoIEkgYW0gbm90IHN1cmUgdGhpcyBpcyBkb25lLg0KPiANCj4gSG1tbS4gWW91J3JlIHJpZ2h0
LCBidXQgdGhhdCdzIHNvbWV0aGluZyB3ZSBhbHJlYWR5IG5lZWQgdG8gZml4IGluIG1hbnkNCj4g
Y2FzZXMgLS0gYXMgdGhlIGR1cmF0aW9uIGZpZWxkIGlzIG92ZXJ3cml0dGVuIGJ5IG1vc3QgaGFy
ZHdhcmUgdGhlc2UNCj4gZGF5cywgd2UgaGF2ZW4ndCBhbHdheXMgbWFpbnRhaW5lZCBpdCB2ZXJ5
IHdlbGwuDQoNCklmIHRoZSBzdGF0aW9uIHN0aWxsIGRvZXMgdGhlIEFDSyB3ZSBzaG91bGQgbm90
IHRvdWNoIHRoZSBkdXJhdGlvbiBmaWVsZA0KaW4gdGhpcyBjYXNlIChzZWUgbXkgcmVwbHkgdG8g
SGVsbXV0KS4NCg0KPiBZb3VyIGRyaXZlciBzZWVtcyB0byBiZSB0aGUgZXhjZXB0aW9uIHRvIHRo
aXMgLS0gbWF5YmUgeW91IGNhbiBsb29rDQo+IGludG8NCj4gZml4aW5nIHVwIHRoZSBkdXJhdGlv
biBjYWxjdWxhdGlvbnM/IEFsc28gZm9yIDExbiB3aGljaCBpc24ndCB0YWtlbg0KPiBpbnRvDQo+
IGFjY291bnQgYXQgYWxsIHRvZGF5Lg0KPiANCj4gam9oYW5uZXMNCj4gDQoNCkkgd2lsbCBzZWUg
d2hldGhlciB3ZSBjYW4gY29udHJpYnV0ZSB0byBtYWM4MDIxMSBmb3IgdGhpcy4gQnV0IHRoZXJl
DQphcmUgb25seSB0d28gb2YgdXMgd29ya2luZyBvbiB0aGlzIGFuZCB0aGVyZSBhcmUgc29tZSBt
b3JlIGl0ZW1zIG9uDQpvdXIgdG9kbyBsaXN0LiBXaGVuIHdlIHdpbGwgYWRkcmVzcyBpdCB3ZSBz
dXJlIHdpbGwgdGFrZSAxMW4gaW50bw0KYWNjb3VudC4NCg0KR3IuIEF2Uw0K


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

* RE: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  9:07       ` Arend Van Spriel
@ 2011-10-28  9:15         ` Johannes Berg
  0 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-28  9:15 UTC (permalink / raw)
  To: Arend Van Spriel; +Cc: Helmut Schaa, linux-wireless

On Fri, 2011-10-28 at 02:07 -0700, Arend Van Spriel wrote:
> > From: Helmut Schaa [mailto:helmut.schaa@googlemail.com]
> > Sent: vrijdag 28 oktober 2011 9:52
> > 
> > On Fri, Oct 28, 2011 at 9:48 AM, Arend Van Spriel <arend@broadcom.com>
> > wrote:
> > > I would expect this to affect the duration field in the
> > > 802.11 header to indicate the shorter use of the medium.
> > > Going through your patch I am not sure this is done.
> > 
> > I don't think so since the frame will still be acked by the peer as it
> > is
> > a unicast management frame. But this will advise the hardware that it
> > does not need to wait for the ack to happen since we're not interested
> > in retrying it.

> I understand. However, the commit message of this patch suggests we are
> saving airtime, which does not seem the case if the duration field is
> not taken into account. If the ACK is still transmitted we should not
> touch the duration field so I guess my comment is only on the commit
> message itself.

Oh good points ...
The reason we save airtime is that often the frame will be retransmitted
a lot if the station is no longer paying attention.

johannes


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

* [RFC v3 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
                     ` (2 preceding siblings ...)
  2011-10-28  7:48   ` Arend Van Spriel
@ 2011-10-28  9:18   ` Johannes Berg
  3 siblings, 0 replies; 31+ messages in thread
From: Johannes Berg @ 2011-10-28  9:18 UTC (permalink / raw)
  To: linux-wireless

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

For probe responses it can be useful to not wait for ACK to
avoid retransmissions if the station that sent the probe is
already on the next channel, so allow userspace to request
not caring about the ACK with a new nl80211 flag.

Since mac80211 needs to be updated for the new function
prototype anyway implement it right away -- it's just a
few lines of code.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: accidentally sent as v2 instead of v1
v3: update commit log (Arend) and fix bug (Eliad)

 drivers/net/wireless/ath/ath6kl/cfg80211.c |    3 +-
 include/linux/nl80211.h                    |    7 ++++
 include/net/cfg80211.h                     |    2 -
 net/mac80211/cfg.c                         |   11 +++++--
 net/wireless/core.h                        |    2 -
 net/wireless/mlme.c                        |    5 ++-
 net/wireless/nl80211.c                     |   43 +++++++++++++++++------------
 7 files changed, 48 insertions(+), 25 deletions(-)

--- a/include/linux/nl80211.h	2011-10-28 11:03:50.000000000 +0200
+++ b/include/linux/nl80211.h	2011-10-28 11:08:02.000000000 +0200
@@ -1147,6 +1147,11 @@ enum nl80211_commands {
  * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from
  *	&enum nl80211_feature_flags and is advertised in wiphy information.
  *
+ * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells
+ *	the driver to not wait for an acknowledgement. Note that due to this,
+ *	it will also not give a status callback nor return a cookie. This is
+ *	mostly useful for probe responses to save airtime.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1379,6 +1384,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_FEATURE_FLAGS,
 
+	NL80211_ATTR_DONT_WAIT_FOR_ACK,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
--- a/net/wireless/core.h	2011-10-28 11:03:50.000000000 +0200
+++ b/net/wireless/core.h	2011-10-28 11:03:51.000000000 +0200
@@ -378,7 +378,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie);
+			  bool dont_wait_for_ack, u64 *cookie);
 
 /* SME */
 int __cfg80211_connect(struct cfg80211_registered_device *rdev,
--- a/net/wireless/mlme.c	2011-10-28 11:03:42.000000000 +0200
+++ b/net/wireless/mlme.c	2011-10-28 11:03:51.000000000 +0200
@@ -904,7 +904,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie)
+			  bool dont_wait_for_ack, u64 *cookie)
 {
 	struct wireless_dev *wdev = dev->ieee80211_ptr;
 	const struct ieee80211_mgmt *mgmt;
@@ -995,7 +995,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg8021
 	/* Transmit the Action frame as requested by user space */
 	return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan,
 				  channel_type, channel_type_valid,
-				  wait, buf, len, no_cck, cookie);
+				  wait, buf, len, no_cck, dont_wait_for_ack,
+				  cookie);
 }
 
 bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf,
--- a/net/wireless/nl80211.c	2011-10-28 11:03:50.000000000 +0200
+++ b/net/wireless/nl80211.c	2011-10-28 11:03:51.000000000 +0200
@@ -197,6 +197,7 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
 	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+	[NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -5279,10 +5280,11 @@ static int nl80211_tx_mgmt(struct sk_buf
 	int err;
 	void *hdr;
 	u64 cookie;
-	struct sk_buff *msg;
+	struct sk_buff *msg = NULL;
 	unsigned int wait = 0;
-	bool offchan;
-	bool no_cck;
+	bool offchan, no_cck, dont_wait_for_ack;
+
+	dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
 
 	if (!info->attrs[NL80211_ATTR_FRAME] ||
 	    !info->attrs[NL80211_ATTR_WIPHY_FREQ])
@@ -5326,29 +5328,36 @@ static int nl80211_tx_mgmt(struct sk_buf
 	if (chan == NULL)
 		return -EINVAL;
 
-	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-	if (!msg)
-		return -ENOMEM;
-
-	hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
-			     NL80211_CMD_FRAME);
-
-	if (IS_ERR(hdr)) {
-		err = PTR_ERR(hdr);
-		goto free_msg;
+	if (!dont_wait_for_ack) {
+		msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+		if (!msg)
+			return -ENOMEM;
+
+		hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
+				     NL80211_CMD_FRAME);
+
+		if (IS_ERR(hdr)) {
+			err = PTR_ERR(hdr);
+			goto free_msg;
+		}
 	}
+
 	err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type,
 				    channel_type_valid, wait,
 				    nla_data(info->attrs[NL80211_ATTR_FRAME]),
 				    nla_len(info->attrs[NL80211_ATTR_FRAME]),
-				    no_cck, &cookie);
+				    no_cck, dont_wait_for_ack, &cookie);
 	if (err)
 		goto free_msg;
 
-	NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
+	if (msg) {
+		NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie);
 
-	genlmsg_end(msg, hdr);
-	return genlmsg_reply(msg, info);
+		genlmsg_end(msg, hdr);
+		return genlmsg_reply(msg, info);
+	}
+
+	return 0;
 
  nla_put_failure:
 	err = -ENOBUFS;
--- a/include/net/cfg80211.h	2011-10-28 11:03:50.000000000 +0200
+++ b/include/net/cfg80211.h	2011-10-28 11:03:51.000000000 +0200
@@ -1584,7 +1584,7 @@ struct cfg80211_ops {
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
 			  const u8 *buf, size_t len, bool no_cck,
-			  u64 *cookie);
+			  bool dont_wait_for_ack, u64 *cookie);
 	int	(*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
 				       struct net_device *dev,
 				       u64 cookie);
--- a/net/mac80211/cfg.c	2011-10-28 11:03:45.000000000 +0200
+++ b/net/mac80211/cfg.c	2011-10-28 11:03:51.000000000 +0200
@@ -1936,7 +1936,7 @@ static int ieee80211_mgmt_tx(struct wiph
 			     enum nl80211_channel_type channel_type,
 			     bool channel_type_valid, unsigned int wait,
 			     const u8 *buf, size_t len, bool no_cck,
-			     u64 *cookie)
+			     bool dont_wait_for_ack, u64 *cookie)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
@@ -1944,10 +1944,15 @@ static int ieee80211_mgmt_tx(struct wiph
 	struct sta_info *sta;
 	struct ieee80211_work *wk;
 	const struct ieee80211_mgmt *mgmt = (void *)buf;
-	u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
-		    IEEE80211_TX_CTL_REQ_TX_STATUS;
+	u32 flags;
 	bool is_offchan = false;
 
+	if (dont_wait_for_ack)
+		flags = IEEE80211_TX_CTL_NO_ACK;
+	else
+		flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX |
+			IEEE80211_TX_CTL_REQ_TX_STATUS;
+
 	/* Check that we are on the requested channel for transmission */
 	if (chan != local->tmp_channel &&
 	    chan != local->oper_channel)
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c	2011-10-28 11:02:13.000000000 +0200
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c	2011-10-28 11:03:51.000000000 +0200
@@ -1732,7 +1732,8 @@ static int ath6kl_mgmt_tx(struct wiphy *
 			  struct ieee80211_channel *chan, bool offchan,
 			  enum nl80211_channel_type channel_type,
 			  bool channel_type_valid, unsigned int wait,
-			  const u8 *buf, size_t len, bool no_cck, u64 *cookie)
+			  const u8 *buf, size_t len, bool no_cck,
+			  bool dont_wait_for_ack, u64 *cookie)
 {
 	struct ath6kl *ar = ath6kl_priv(dev);
 	u32 id;



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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  9:10       ` Arend Van Spriel
@ 2011-10-28  9:28         ` Helmut Schaa
  2011-10-28 13:34           ` Kalle Valo
  2011-10-28 17:22           ` Arend van Spriel
  0 siblings, 2 replies; 31+ messages in thread
From: Helmut Schaa @ 2011-10-28  9:28 UTC (permalink / raw)
  To: Arend Van Spriel; +Cc: Johannes Berg, linux-wireless

On Fri, Oct 28, 2011 at 11:10 AM, Arend Van Spriel <arend@broadcom.com> wrote:
>> > I would expect this to affect the duration field in the
>> > 802.11 header to indicate the shorter use of the medium.
>> > Going through your patch I am not sure this is done.
>>
>> Hmmm. You're right, but that's something we already need to fix in many
>> cases -- as the duration field is overwritten by most hardware these
>> days, we haven't always maintained it very well.
>
> If the station still does the ACK we should not touch the duration field
> in this case (see my reply to Helmut).

The reason is the following: if you're running a mac80211 AP with multiple
bssids, hostapd will answer to broadcast probe requests sent by STAs with
one probe response per bssid (unicast of course). And since some clients
stay only for a short amount of time on the scan-channel (a few ms) under
some circumstances the probe responses aren't sent out yet before the
scanning STA leaves the channel and thus retried till the maximum retry
limit is reached. And these retries consume quite a lot of airtime. And to
avoid this we just don't want to retry the probe responses in that case.

Helmut

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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  9:28         ` Helmut Schaa
@ 2011-10-28 13:34           ` Kalle Valo
  2011-10-29 12:01             ` Helmut Schaa
  2011-10-28 17:22           ` Arend van Spriel
  1 sibling, 1 reply; 31+ messages in thread
From: Kalle Valo @ 2011-10-28 13:34 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Arend Van Spriel, Johannes Berg, linux-wireless

Helmut Schaa <helmut.schaa@googlemail.com> writes:

> The reason is the following: if you're running a mac80211 AP with multiple
> bssids, hostapd will answer to broadcast probe requests sent by STAs with
> one probe response per bssid (unicast of course). And since some clients
> stay only for a short amount of time on the scan-channel (a few ms) under
> some circumstances the probe responses aren't sent out yet before the
> scanning STA leaves the channel and thus retried till the maximum retry
> limit is reached. And these retries consume quite a lot of airtime. And to
> avoid this we just don't want to retry the probe responses in that case.

This is all good. But doesn't it also mean that this change increases
probability that the client doesn't receive the probe response, for
example due to interference where retransmission would help, and hence
the AP isn't included in the client's scan results?

-- 
Kalle Valo

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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28  9:28         ` Helmut Schaa
  2011-10-28 13:34           ` Kalle Valo
@ 2011-10-28 17:22           ` Arend van Spriel
  1 sibling, 0 replies; 31+ messages in thread
From: Arend van Spriel @ 2011-10-28 17:22 UTC (permalink / raw)
  To: Helmut Schaa; +Cc: Johannes Berg, linux-wireless

On 10/28/2011 11:28 AM, Helmut Schaa wrote:
> On Fri, Oct 28, 2011 at 11:10 AM, Arend Van Spriel <arend@broadcom.com> wrote:
>>>> I would expect this to affect the duration field in the
>>>> 802.11 header to indicate the shorter use of the medium.
>>>> Going through your patch I am not sure this is done.
>>>
>>> Hmmm. You're right, but that's something we already need to fix in many
>>> cases -- as the duration field is overwritten by most hardware these
>>> days, we haven't always maintained it very well.
>>
>> If the station still does the ACK we should not touch the duration field
>> in this case (see my reply to Helmut).
> 
> The reason is the following: if you're running a mac80211 AP with multiple
> bssids, hostapd will answer to broadcast probe requests sent by STAs with
> one probe response per bssid (unicast of course). And since some clients
> stay only for a short amount of time on the scan-channel (a few ms) under
> some circumstances the probe responses aren't sent out yet before the
> scanning STA leaves the channel and thus retried till the maximum retry
> limit is reached. And these retries consume quite a lot of airtime. And to
> avoid this we just don't want to retry the probe responses in that case.
> 
> Helmut
> 

Hi Helmut,

That makes perfect sense. Indeed not doing retries will obviously save
airtime. Thanks for taking time to explain the scenario.

Gr. AvS


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

* Re: [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK
  2011-10-28 13:34           ` Kalle Valo
@ 2011-10-29 12:01             ` Helmut Schaa
  0 siblings, 0 replies; 31+ messages in thread
From: Helmut Schaa @ 2011-10-29 12:01 UTC (permalink / raw)
  To: Kalle Valo; +Cc: Arend Van Spriel, Johannes Berg, linux-wireless

On Fri, Oct 28, 2011 at 3:34 PM, Kalle Valo <kvalo@adurom.com> wrote:
> Helmut Schaa <helmut.schaa@googlemail.com> writes:
>
>> The reason is the following: if you're running a mac80211 AP with multiple
>> bssids, hostapd will answer to broadcast probe requests sent by STAs with
>> one probe response per bssid (unicast of course). And since some clients
>> stay only for a short amount of time on the scan-channel (a few ms) under
>> some circumstances the probe responses aren't sent out yet before the
>> scanning STA leaves the channel and thus retried till the maximum retry
>> limit is reached. And these retries consume quite a lot of airtime. And to
>> avoid this we just don't want to retry the probe responses in that case.
>
> This is all good. But doesn't it also mean that this change increases
> probability that the client doesn't receive the probe response, for
> example due to interference where retransmission would help, and hence
> the AP isn't included in the client's scan results?

Correct. The probability to find the AP during a scan is lower then with
retries. However, some commercial APs (Aruba for example) do exactly this
and in some cases I noticed (on a mac80211 AP with 8 BSSIDs) one
scanning client took around 50ms of airtime :)

Also in a multi BSS scenario the probability of finding the second, third etc.
BSSID gets lower if probe responses are retried.

I've got a patch for hostapd to implement the don't-wait-for-ack behavior
only for broadcast probe responses that contain the wildcard ssid. But maybe
it makes sense to make this a configuration option? So it is up to the user
to decide about the behavior.

Helmut

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

end of thread, other threads:[~2011-10-29 12:01 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-10-21 14:23 [RFC v2 00/12] get rid of AP mode monitor interfaces Johannes Berg
2011-10-21 14:23 ` [RFC v2 01/12] mac80211: add helper to free TX skb Johannes Berg
2011-10-21 14:23 ` [RFC v2 02/12] mac80211: add support for control port protocol in AP mode Johannes Berg
2011-10-21 14:23 ` [RFC v2 03/12] nl80211: allow subscribing to unexpected class3 frames Johannes Berg
2011-10-21 14:23 ` [RFC v2 04/12] mac80211: support spurious class3 event Johannes Berg
2011-10-21 14:23 ` [RFC v2 05/12] nl80211: advertise device AP SME Johannes Berg
2011-10-25 10:13   ` Eliad Peller
2011-10-21 14:23 ` [RFC v2 06/12] nl80211: add API to probe a client Johannes Berg
2011-10-21 14:23 ` [RFC v2 07/12] mac80211: support client probe Johannes Berg
2011-10-21 14:23 ` [RFC v2 08/12] net: add wireless TX status socket option Johannes Berg
2011-10-25 10:40   ` Eliad Peller
2011-10-21 14:23 ` [RFC v2 09/12] nl80211: advertise socket TX status capability Johannes Berg
2011-10-21 14:23 ` [RFC v2 10/12] mac80211: implement wifi TX status Johannes Berg
2011-10-21 14:23 ` [RFC v2 11/12] cfg80211: allow registering to beacons Johannes Berg
2011-10-21 14:23 ` [RFC v2 12/12] mac80211: report OBSS beacons Johannes Berg
2011-10-27 19:32 ` [RFC v2 13/12] cfg80211/mac80211: allow management TX to not wait for ACK Johannes Berg
2011-10-27 22:44   ` Eliad Peller
2011-10-28  8:02     ` Johannes Berg
2011-10-28  6:09   ` Helmut Schaa
2011-10-28  7:34     ` Johannes Berg
2011-10-28  7:48   ` Arend Van Spriel
2011-10-28  7:52     ` Helmut Schaa
2011-10-28  9:07       ` Arend Van Spriel
2011-10-28  9:15         ` Johannes Berg
2011-10-28  8:01     ` Johannes Berg
2011-10-28  9:10       ` Arend Van Spriel
2011-10-28  9:28         ` Helmut Schaa
2011-10-28 13:34           ` Kalle Valo
2011-10-29 12:01             ` Helmut Schaa
2011-10-28 17:22           ` Arend van Spriel
2011-10-28  9:18   ` [RFC v3 " 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.