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);
next prev 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).