linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sreenath <sreenats@broadcom.com>
To: "Johannes Berg" <johannes@sipsolutions.net>
Cc: linux-wireless@vger.kernel.org,
	"Johannes Berg" <johannes.berg@intel.com>
Subject: Re: [RFC v4] cfg80211: Android P2P-Device workaround
Date: Tue, 30 Apr 2013 19:08:27 +0530	[thread overview]
Message-ID: <517FC953.3010206@broadcom.com> (raw)
In-Reply-To: <1367238384-26722-1-git-send-email-johannes@sipsolutions.net>

Hello Johannes,

As per this patch, the dummy 'p2p0' interface will be created only if 
new interface creation request is for interface type - 
NL80211_IFTYPE_P2P_DEVICE. Does that mean that this P2P hack will work 
only with wpa_supplicant patches submitted by David Spinadel or similar 
changes have to be done in wpa_supplicant? Because with current version 
of wpa_supplicant there won't be any interface creation request for 
NL80211_IFTYPE_P2P_DEVICE as the interface type.

Moreover with David Spinadel's wpa_supplicant patches, the dummy 
interface name will be 'p2p-dev-<WLAN_PRIMARY_IF_NAME>' not 'p2p0'. So 
please provide more clarity on how this patch can be tested.

Regards,
Sreenath

On 04/29/2013 05:56 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Android requires a "p2p0" netdev to exist for P2P Device
> functionality, and will even set it "UP" to start the P2P
> Device functionality.
>
> This is a hack to provide it so not only is Android happy
> but also the current version of wpa_supplicant can work
> with P2P-Device functionality without needing changes to
> support the P2P-Device commands, just a little bit to not
> attempt to change the interface type to station.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>   include/net/cfg80211.h |   4 ++
>   net/wireless/Kconfig   |   7 +++
>   net/wireless/Makefile  |   1 +
>   net/wireless/android.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++
>   net/wireless/core.c    |  14 +++++
>   net/wireless/core.h    |   6 ++
>   net/wireless/nl80211.c |  63 +++++++++++++++++++++
>   7 files changed, 242 insertions(+)
>   create mode 100644 net/wireless/android.c
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 87f7e1d..6e312ef 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -2924,6 +2924,10 @@ struct wireless_dev {
>   		bool prev_bssid_valid;
>   	} wext;
>   #endif
> +
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	struct net_device *p2pdev;
> +#endif
>   };
>   
>   static inline u8 *wdev_address(struct wireless_dev *wdev)
> diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
> index 16d08b3..7c2981c 100644
> --- a/net/wireless/Kconfig
> +++ b/net/wireless/Kconfig
> @@ -139,6 +139,13 @@ config CFG80211_WEXT
>   	  Enable this option if you need old userspace for wireless
>   	  extensions with cfg80211-based drivers.
>   
> +config CFG80211_ANDROID_P2P_HACK
> +	bool "Android P2P netdevice hack"
> +	depends on CFG80211
> +	depends on !CFG80211_WEXT
> +	help
> +	  Enable this option for Android P2P w/ P2P Device.
> +
>   config LIB80211
>   	tristate
>   	default n
> diff --git a/net/wireless/Makefile b/net/wireless/Makefile
> index a761670..2800e67 100644
> --- a/net/wireless/Makefile
> +++ b/net/wireless/Makefile
> @@ -14,6 +14,7 @@ cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
>   cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
>   cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
>   cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
> +cfg80211-$(CONFIG_CFG80211_ANDROID_P2P_HACK) += android.o
>   
>   CFLAGS_trace.o := -I$(src)
>   
> diff --git a/net/wireless/android.c b/net/wireless/android.c
> new file mode 100644
> index 0000000..e24c764
> --- /dev/null
> +++ b/net/wireless/android.c
> @@ -0,0 +1,147 @@
> +/******************************************************************************
> + *
> + * This file is provided under the GPLv2 license.
> + *
> + * GPL LICENSE SUMMARY
> + *
> + * Copyright(c) 2013 Intel Corporation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of version 2 of the GNU General Public License as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
> + * USA
> + *
> + * The full GNU General Public License is included in this distribution
> + * in the file called COPYING.
> + *
> + * Contact Information:
> + *  Intel Linux Wireless <ilw@linux.intel.com>
> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
> + *
> + * Author: Johannes Berg <johannes.berg@intel.com>
> + *
> + *****************************************************************************/
> +#include <linux/kernel.h>
> +#include <linux/netdevice.h>
> +#include <linux/rtnetlink.h>
> +#include <net/cfg80211.h>
> +#include "core.h"
> +#include "rdev-ops.h"
> +
> +static int cfg80211_android_p2pdev_open(struct net_device *dev)
> +{
> +	struct wireless_dev *wdev = dev->ieee80211_ptr;
> +	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> +	int err;
> +
> +	if (!rdev->ops->start_p2p_device)
> +		return -EOPNOTSUPP;
> +
> +	if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
> +		return -EOPNOTSUPP;
> +
> +	if (wdev->p2p_started)
> +		return 0;
> +
> +	mutex_lock(&rdev->devlist_mtx);
> +	err = cfg80211_can_add_interface(rdev, wdev->iftype);
> +	mutex_unlock(&rdev->devlist_mtx);
> +	if (err)
> +		return err;
> +
> +	err = rdev_start_p2p_device(rdev, wdev);
> +	if (err)
> +		return err;
> +
> +	wdev->p2p_started = true;
> +	mutex_lock(&rdev->devlist_mtx);
> +	rdev->opencount++;
> +	mutex_unlock(&rdev->devlist_mtx);
> +
> +	return 0;
> +}
> +
> +static int cfg80211_android_p2pdev_stop(struct net_device *dev)
> +{
> +	struct wireless_dev *wdev = dev->ieee80211_ptr;
> +	struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
> +
> +	if (!wdev->p2p_started)
> +		return 0;
> +
> +	mutex_lock(&rdev->devlist_mtx);
> +	mutex_lock(&rdev->sched_scan_mtx);
> +	cfg80211_stop_p2p_device(rdev, wdev);
> +	mutex_unlock(&rdev->sched_scan_mtx);
> +	mutex_unlock(&rdev->devlist_mtx);
> +
> +	return 0;
> +}
> +
> +static netdev_tx_t cfg80211_android_p2pdev_start_xmit(struct sk_buff *skb,
> +						      struct net_device *dev)
> +{
> +	dev_kfree_skb(skb);
> +	return NETDEV_TX_OK;
> +}
> +
> +static const struct net_device_ops cfg80211_android_p2pdev_ops = {
> +	.ndo_open = cfg80211_android_p2pdev_open,
> +	.ndo_stop = cfg80211_android_p2pdev_stop,
> +	.ndo_start_xmit = cfg80211_android_p2pdev_start_xmit,
> +};
> +
> +static void cfg80211_android_p2pdev_setup(struct net_device *dev)
> +{
> +	ether_setup(dev);
> +	dev->features |= NETIF_F_NETNS_LOCAL;
> +	dev->netdev_ops = &cfg80211_android_p2pdev_ops;
> +	dev->destructor = free_netdev;
> +}
> +
> +void cfg80211_android_create_p2p_device(struct wireless_dev *wdev,
> +					const char *name)
> +{
> +	if (WARN_ON(wdev->p2pdev))
> +		return;
> +
> +	wdev->p2pdev = alloc_netdev(0, name, cfg80211_android_p2pdev_setup);
> +	if (WARN(!wdev->p2pdev,
> +		 "Failed to allocate P2P-Device netdev, things will fail!\n"))
> +		return;
> +
> +	memcpy(wdev->p2pdev->dev_addr, wdev->address, ETH_ALEN);
> +	wdev->p2pdev->ieee80211_ptr = wdev;
> +
> +	if (WARN(register_netdevice(wdev->p2pdev),
> +		 "Failed to register P2P-Device netdev, things will fail!\n")) {
> +		free_netdev(wdev->p2pdev);
> +		return;
> +	}
> +
> +	if (sysfs_create_link(&wdev->p2pdev->dev.kobj, &wdev->wiphy->dev.kobj,
> +			      "phy80211"))
> +		pr_err("failed to add phy80211 symlink to netdev!\n");
> +}
> +
> +void cfg80211_android_destroy_p2p_device(struct wireless_dev *wdev)
> +{
> +	ASSERT_RTNL();
> +
> +	if (!wdev->p2pdev)
> +		return;
> +
> +	dev_close(wdev->p2pdev);
> +	wdev->p2pdev->ieee80211_ptr = NULL;
> +	unregister_netdevice(wdev->p2pdev);
> +	wdev->p2pdev = NULL;
> +}
> diff --git a/net/wireless/core.c b/net/wireless/core.c
> index 84c9ad7..59da6df 100644
> --- a/net/wireless/core.c
> +++ b/net/wireless/core.c
> @@ -170,6 +170,12 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
>   		return -EOPNOTSUPP;
>   
>   	list_for_each_entry(wdev, &rdev->wdev_list, list) {
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +		if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
> +			err = -EBUSY;
> +			break;
> +		}
> +#endif
>   		if (!wdev->netdev)
>   			continue;
>   		wdev->netdev->features &= ~NETIF_F_NETNS_LOCAL;
> @@ -818,6 +824,9 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
>   	switch (wdev->iftype) {
>   	case NL80211_IFTYPE_P2P_DEVICE:
>   		cfg80211_stop_p2p_device(rdev, wdev);
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +		cfg80211_android_destroy_p2p_device(wdev);
> +#endif
>   		break;
>   	default:
>   		WARN_ON_ONCE(1);
> @@ -898,6 +907,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
>   
>   	WARN_ON(wdev->iftype == NL80211_IFTYPE_UNSPECIFIED);
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE)
> +		return NOTIFY_DONE;
> +#endif
> +
>   	switch (state) {
>   	case NETDEV_POST_INIT:
>   		SET_NETDEV_DEVTYPE(dev, &wiphy_type);
> diff --git a/net/wireless/core.h b/net/wireless/core.h
> index fd35dae..0cc74d5 100644
> --- a/net/wireless/core.h
> +++ b/net/wireless/core.h
> @@ -522,4 +522,10 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
>   #define CFG80211_DEV_WARN_ON(cond)	({bool __r = (cond); __r; })
>   #endif
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +void cfg80211_android_create_p2p_device(struct wireless_dev *wdev,
> +					const char *name);
> +void cfg80211_android_destroy_p2p_device(struct wireless_dev *wdev);
> +#endif
> +
>   #endif /* __NET_WIRELESS_CORE_H */
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index f687a8d..732a29b 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -87,6 +87,13 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
>   				result = wdev;
>   				break;
>   			}
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +			if (have_ifidx && wdev->p2pdev &&
> +			    wdev->p2pdev->ifindex == ifidx) {
> +				result = wdev;
> +				break;
> +			}
> +#endif
>   			if (have_wdev_id && wdev->identifier == (u32)wdev_id) {
>   				result = wdev;
>   				break;
> @@ -2350,6 +2357,14 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
>   			return -EINVAL;
>   	}
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (otype == NL80211_IFTYPE_P2P_DEVICE) {
> +		if (ntype == NL80211_IFTYPE_P2P_DEVICE)
> +			return 0;
> +		return -EINVAL;
> +	}
> +#endif
> +
>   	if (info->attrs[NL80211_ATTR_MESH_ID]) {
>   		struct wireless_dev *wdev = dev->ieee80211_ptr;
>   
> @@ -2479,6 +2494,10 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
>   		INIT_LIST_HEAD(&wdev->mgmt_registrations);
>   		spin_lock_init(&wdev->mgmt_registrations_lock);
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +		cfg80211_android_create_p2p_device(wdev,
> +			nla_data(info->attrs[NL80211_ATTR_IFNAME]));
> +#endif
>   		mutex_lock(&rdev->devlist_mtx);
>   		wdev->identifier = ++rdev->wdev_id;
>   		list_add_rcu(&wdev->list, &rdev->wdev_list);
> @@ -5624,6 +5643,11 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
>   	if (wdev->netdev &&
>   	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
>   		goto nla_put_failure;
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->p2pdev &&
> +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->p2pdev->ifindex))
> +		goto nla_put_failure;
> +#endif
>   	if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
>   		goto nla_put_failure;
>   
> @@ -8183,6 +8207,11 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
>   		return err;
>   
>   	wdev->p2p_started = true;
> +
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	WARN_ON(wdev->p2pdev && dev_open(wdev->p2pdev));
> +#endif
> +
>   	mutex_lock(&rdev->devlist_mtx);
>   	rdev->opencount++;
>   	mutex_unlock(&rdev->devlist_mtx);
> @@ -8207,6 +8236,10 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
>   	mutex_unlock(&rdev->sched_scan_mtx);
>   	mutex_unlock(&rdev->devlist_mtx);
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	WARN_ON(wdev->p2pdev && dev_close(wdev->p2pdev));
> +#endif
> +
>   	return 0;
>   }
>   
> @@ -8361,6 +8394,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
>   		dev = wdev->netdev;
>   		rdev = wiphy_to_dev(wdev->wiphy);
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +		if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
> +		    info->genlhdr->cmd == NL80211_CMD_SET_INTERFACE)
> +			dev = wdev->p2pdev;
> +#endif
> +
>   		if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
>   			if (!dev) {
>   				mutex_unlock(&cfg80211_mutex);
> @@ -9118,6 +9157,12 @@ static int nl80211_send_scan_msg(struct sk_buff *msg,
>   	    nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
>   		goto nla_put_failure;
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->p2pdev &&
> +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->p2pdev->ifindex))
> +		goto nla_put_failure;
> +#endif
> +
>   	/* ignore errors and send incomplete event anyway */
>   	nl80211_add_scan_req(msg, rdev);
>   
> @@ -9764,6 +9809,12 @@ static void nl80211_send_remain_on_chan_event(
>   	    nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
>   		goto nla_put_failure;
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->p2pdev &&
> +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->p2pdev->ifindex))
> +		goto nla_put_failure;
> +#endif
> +
>   	if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
>   	    nla_put_u32(msg, NL80211_ATTR_DURATION, duration))
>   		goto nla_put_failure;
> @@ -10014,6 +10065,12 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
>   	    nla_put(msg, NL80211_ATTR_FRAME, len, buf))
>   		goto nla_put_failure;
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->p2pdev &&
> +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->p2pdev->ifindex))
> +		goto nla_put_failure;
> +#endif
> +
>   	genlmsg_end(msg, hdr);
>   
>   	return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid);
> @@ -10053,6 +10110,12 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
>   	    (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
>   		goto nla_put_failure;
>   
> +#ifdef CONFIG_CFG80211_ANDROID_P2P_HACK
> +	if (wdev->p2pdev &&
> +	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->p2pdev->ifindex))
> +		goto nla_put_failure;
> +#endif
> +
>   	genlmsg_end(msg, hdr);
>   
>   	genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);



  parent reply	other threads:[~2013-04-30 13:41 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-29 12:26 [RFC v4] cfg80211: Android P2P-Device workaround Johannes Berg
2013-04-29 13:50 ` Arend van Spriel
2013-04-29 13:53   ` Johannes Berg
2013-04-29 16:32 ` Marcel Holtmann
2013-04-30 13:38 ` Sreenath [this message]
2013-04-30 13:43   ` Johannes Berg
2013-05-02 10:03 ` Arend van Spriel
2013-05-02 10:06   ` Johannes Berg
2013-05-02 19:17     ` Arend van Spriel
2013-05-07 10:20       ` Johannes Berg
2013-05-23  3:18         ` YanBo
2013-05-23  9:40           ` Johannes Berg
2013-05-23 14:40             ` YanBo
2013-05-23 16:08               ` Johannes Berg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=517FC953.3010206@broadcom.com \
    --to=sreenats@broadcom.com \
    --cc=johannes.berg@intel.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).