2016-09-16 08:33:32

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 0/9] Add support for Neighbor Awareness Networking

From: Luca Coelho <[email protected]>

Hi,

This is v2 of the NAN patches that Emmanuel sent a while back[1]. In
this version, we squashed some patches and took care of some comments
after reviews (both internal and public).

NAN was described in the original post[2].

I hope they're good for merging now, because I'm tired of carrying
this changes forward in our internal trees. :P

Nevertheless, comments are welcome, as always.

[1] http://mid.gmane.org/[email protected]
[2] http://mid.gmane.org/[email protected]

Cheers,
Luca.


Ayala Beker (9):
cfg80211: add start / stop NAN commands
mac80211: add boilerplate code for start / stop NAN
cfg80211: add add_nan_func / rm_nan_func
cfg80211: allow the user space to change current NAN configuration
cfg80211: provide a function to report a match for NAN
cfg80211: Provide an API to report NAN function termination
mac80211: implement nan_change_conf
mac80211: Implement add_nan_func and rm_nan_func
mac80211: Add API to report NAN function match

include/net/cfg80211.h | 184 ++++++++++++-
include/net/mac80211.h | 65 +++++
include/uapi/linux/nl80211.h | 258 +++++++++++++++++
net/mac80211/cfg.c | 208 ++++++++++++++
net/mac80211/chan.c | 6 +
net/mac80211/driver-ops.h | 82 +++++-
net/mac80211/ieee80211_i.h | 17 ++
net/mac80211/iface.c | 28 +-
net/mac80211/main.c | 8 +
net/mac80211/offchannel.c | 4 +-
net/mac80211/rx.c | 3 +
net/mac80211/trace.h | 133 +++++++++
net/mac80211/util.c | 50 +++-
net/wireless/chan.c | 2 +
net/wireless/core.c | 35 +++
net/wireless/core.h | 3 +
net/wireless/mlme.c | 1 +
net/wireless/nl80211.c | 642 ++++++++++++++++++++++++++++++++++++++++++-
net/wireless/rdev-ops.h | 58 ++++
net/wireless/trace.h | 90 ++++++
net/wireless/util.c | 28 +-
21 files changed, 1894 insertions(+), 11 deletions(-)

--
2.9.3


2016-09-16 10:58:45

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> This allows user space to start/stop NAN interface.
> A NAN interface is like P2P device in a few aspects: it
> doesn't have a netdev associated to it.
> Add the new interface type and prevent operations that
> can't be executed on NAN interface like scan.
>
> Define several attributes that may be configured by user space
> when starting NAN functionality (master preference and dual
> band operation)
>
> Signed-off-by: Andrei Otcheretianski <[email protected]>
> Signed-off-by: Emmanuel Grumbach <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>
> ---
> include/net/cfg80211.h | 21 +++++++++-
> include/uapi/linux/nl80211.h | 52 +++++++++++++++++++++++++
> net/mac80211/cfg.c | 2 +
> net/mac80211/chan.c | 3 ++
> net/mac80211/iface.c | 4 ++
> net/mac80211/offchannel.c | 1 +
> net/mac80211/rx.c | 3 ++
> net/mac80211/util.c | 1 +
> net/wireless/chan.c | 2 +
> net/wireless/core.c | 34 ++++++++++++++++
> net/wireless/core.h | 3 ++
> net/wireless/mlme.c | 1 +
> net/wireless/nl80211.c | 93 ++++++++++++++++++++++++++++++++++++++++++--
> net/wireless/rdev-ops.h | 20 ++++++++++
> net/wireless/trace.h | 27 +++++++++++++
> net/wireless/util.c | 6 ++-
> 16 files changed, 267 insertions(+), 6 deletions(-)
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index d5e7f69..ca64d69 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -2293,6 +2293,19 @@ struct cfg80211_qos_map {
> };

[...]

> +/**
> + * enum nl80211_nan_dual_band_conf - NAN dual band configuration
> + *
> + * Defines the NAN dual band mode of operation

Does it make sense to have such a notion of bands in use. And what does
5.2GHz mean. Is this a subband within 5G channels? Probably I should
read the NAN spec to understand what is meant here. I would consider
5.2G as lower 5G, ie. discovery on channel 44 but not sure if that is
meant here.

> + * @NL80211_NAN_BAND_DEFAULT: device default mode
> + * @NL80211_NAN_BAND_SINGLE: 2.4GHz only mode
> + * @NL80211_NAN_BAND_DUAL: 2.4GHz and 5.2GHz mode
> + */
> +enum nl80211_nan_dual_band_conf {
> + NL80211_NAN_BAND_DEFAULT,
> + NL80211_NAN_BAND_SINGLE,
> + NL80211_NAN_BAND_DUAL,
> +
> + /* keep last */
> + __NL80211_NAN_BAND_AFTER_LAST,
> + NL80211_NAN_BAND_MAX =
> + __NL80211_NAN_BAND_AFTER_LAST - 1,
> +};
> +
> #endif /* __LINUX_NL80211_H */
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index e29ff57..a74027f 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -257,6 +257,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
> case NL80211_IFTYPE_WDS:
> case NL80211_IFTYPE_MONITOR:
> case NL80211_IFTYPE_P2P_DEVICE:
> + case NL80211_IFTYPE_NAN:
> case NL80211_IFTYPE_UNSPECIFIED:
> case NUM_NL80211_IFTYPES:

Huh? What is this doing here? Not yours but weird still.

> case NL80211_IFTYPE_P2P_CLIENT:
> @@ -2036,6 +2037,7 @@ static int ieee80211_scan(struct wiphy *wiphy,
> !(req->flags & NL80211_SCAN_FLAG_AP)))
> return -EOPNOTSUPP;
> break;
> + case NL80211_IFTYPE_NAN:
> default:
> return -EOPNOTSUPP;
> }
> diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
> index 74142d0..acb50f8 100644
> --- a/net/mac80211/chan.c
> +++ b/net/mac80211/chan.c
> @@ -274,6 +274,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
> ieee80211_get_max_required_bw(sdata));
> break;
> case NL80211_IFTYPE_P2P_DEVICE:
> + case NL80211_IFTYPE_NAN:
> continue;
> case NL80211_IFTYPE_ADHOC:
> case NL80211_IFTYPE_WDS:
> @@ -718,6 +719,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
>
> switch (sdata->vif.type) {
> case NL80211_IFTYPE_P2P_DEVICE:
> + case NL80211_IFTYPE_NAN:
> continue;
> case NL80211_IFTYPE_STATION:
> if (!sdata->u.mgd.associated)
> @@ -981,6 +983,7 @@ ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
> case NL80211_IFTYPE_P2P_GO:
> case NL80211_IFTYPE_P2P_DEVICE:
> case NUM_NL80211_IFTYPES:

I think NUM_NL80211_IFTYPES should not be in the switch. If it must I
would leave it as last one here.

> + case NL80211_IFTYPE_NAN:
> WARN_ON(1);
> break;
> }

Regards,
Arend

2016-09-19 07:27:03

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 1/9] cfg80211: add start / stop NAN commands

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 21:54
> To: Otcheretianski, Andrei <[email protected]>; Luca Coelho
> <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Grumbach, Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands
>
> On 18-9-2016 9:44, Otcheretianski, Andrei wrote:
> >> -----Original Message-----
> >> From: Arend Van Spriel [mailto:[email protected]]
> >> Sent: Friday, September 16, 2016 13:59
> >> To: Luca Coelho <[email protected]>; [email protected]
> >> Cc: [email protected]; Beker, Ayala
> >> <[email protected]>; Otcheretianski, Andrei
> >> <[email protected]>; Grumbach, Emmanuel
> >> <[email protected]>; Coelho, Luciano
> >> <[email protected]>
> >> Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands
> >>
> >> On 16-9-2016 10:33, Luca Coelho wrote:
> >>> From: Ayala Beker <[email protected]>
> >>>
> >>> This allows user space to start/stop NAN interface.
> >>> A NAN interface is like P2P device in a few aspects: it doesn't have
> >>> a netdev associated to it.
> >>> Add the new interface type and prevent operations that can't be
> >>> executed on NAN interface like scan.
> >>>
> >>> Define several attributes that may be configured by user space when
> >>> starting NAN functionality (master preference and dual band
> >>> operation)
> >>>
> >>> Signed-off-by: Andrei Otcheretianski
> >>> <[email protected]>
> >>> Signed-off-by: Emmanuel Grumbach <[email protected]>
> >>> Signed-off-by: Luca Coelho <[email protected]>
> >>> ---
> >>> include/net/cfg80211.h | 21 +++++++++-
> >>> include/uapi/linux/nl80211.h | 52 +++++++++++++++++++++++++
> >>> net/mac80211/cfg.c | 2 +
> >>> net/mac80211/chan.c | 3 ++
> >>> net/mac80211/iface.c | 4 ++
> >>> net/mac80211/offchannel.c | 1 +
> >>> net/mac80211/rx.c | 3 ++
> >>> net/mac80211/util.c | 1 +
> >>> net/wireless/chan.c | 2 +
> >>> net/wireless/core.c | 34 ++++++++++++++++
> >>> net/wireless/core.h | 3 ++
> >>> net/wireless/mlme.c | 1 +
> >>> net/wireless/nl80211.c | 93
> >> ++++++++++++++++++++++++++++++++++++++++++--
> >>> net/wireless/rdev-ops.h | 20 ++++++++++
> >>> net/wireless/trace.h | 27 +++++++++++++
> >>> net/wireless/util.c | 6 ++-
> >>> 16 files changed, 267 insertions(+), 6 deletions(-)
> >>>
> >>> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index
> >>> d5e7f69..ca64d69 100644
> >>> --- a/include/net/cfg80211.h
> >>> +++ b/include/net/cfg80211.h
> >>> @@ -2293,6 +2293,19 @@ struct cfg80211_qos_map { };
> >>
> >> [...]
> >>
> >>> +/**
> >>> + * enum nl80211_nan_dual_band_conf - NAN dual band configuration
> >>> + *
> >>> + * Defines the NAN dual band mode of operation
> >>
> >> Does it make sense to have such a notion of bands in use. And what
> >> does 5.2GHz mean. Is this a subband within 5G channels? Probably I
> >> should read the NAN spec to understand what is meant here. I would
> >> consider 5.2G as lower 5G, ie. discovery on channel 44 but not sure if that
> is meant here.
> >>
> >
> > The NAN spec defines single and dual band modes of operation. The
> channels are fixed for each band.
> > On 2.4Ghz is channel 6 and 5GHz is either 44 or 149. Regarding 5.2 - it's just a
> typo. It should be 5G - no deeper meaning.
>
> The thing is that it seems likely other bands will be added so that would kinda
> obsolete this whole enum. So I would propose to have another way to
> configure the bands to use. This enum is not really extensible though it may
> reflect the current state of the spec, which is still in draft if I am not mistaken.
>

I guess you are talking about additional bands that are mentioned in NAN2 spec (like sub-1Ghz etc..).
I'm not sure that these bands will be used for sync or NAN2 specific operations only (like data path or ranging).
Nevertheless, you're right, I guess it doesn't harm to make it a bitmask of supported bands.

> Regards,
> Arend

2016-09-16 08:33:41

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 7/9] mac80211: implement nan_change_conf

From: Ayala Beker <[email protected]>

Implement nan_change_conf callback which allows to change current
NAN configuration (master preference and dual band operation).
Store the current NAN configuration in sdata, so it can be used
both to provide the driver the updated configuration with changes
and also it will be used in hw reconfig flows in next patches.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/mac80211.h | 9 +++++++++
net/mac80211/cfg.c | 31 +++++++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 21 +++++++++++++++++++++
net/mac80211/ieee80211_i.h | 10 ++++++++++
net/mac80211/trace.h | 31 +++++++++++++++++++++++++++++++
5 files changed, 102 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index df9b5cf..ef8d02a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3423,6 +3423,12 @@ enum ieee80211_reconfig_type {
*
* @start_nan: join an existing NAN cluster, or create a new one.
* @stop_nan: leave the NAN cluster.
+ * @nan_change_conf: change NAN configuration. The data in cfg80211_nan_conf
+ * contains full new configuration and changes specify which parameters
+ * are changed with respect to the last NAN config.
+ * The driver gets both full configuration and the changed parameters since
+ * some devices may need the full configuration while others need only the
+ * changed parameters.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3664,6 +3670,9 @@ struct ieee80211_ops {
struct cfg80211_nan_conf *conf);
int (*stop_nan)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+ int (*nan_change_conf)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf, u32 changes);
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9aabb09..38fdb53 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -186,6 +186,36 @@ static void ieee80211_stop_nan(struct wiphy *wiphy,
ieee80211_sdata_stop(sdata);
}

+static int ieee80211_nan_change_conf(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf,
+ u32 changes)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct cfg80211_nan_conf new_conf;
+ int ret = 0;
+
+ if (sdata->vif.type != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (!ieee80211_sdata_running(sdata))
+ return -ENETDOWN;
+
+ new_conf = sdata->u.nan.conf;
+
+ if (changes & CFG80211_NAN_CONF_CHANGED_PREF)
+ new_conf.master_pref = conf->master_pref;
+
+ if (changes & CFG80211_NAN_CONF_CHANGED_DUAL)
+ new_conf.dual = conf->dual;
+
+ ret = drv_nan_change_conf(sdata->local, sdata, &new_conf, changes);
+ if (!ret)
+ sdata->u.nan.conf = new_conf;
+
+ return ret;
+}
+
static int ieee80211_set_noack_map(struct wiphy *wiphy,
struct net_device *dev,
u16 noack_map)
@@ -3500,4 +3530,5 @@ const struct cfg80211_ops mac80211_config_ops = {
.del_tx_ts = ieee80211_del_tx_ts,
.start_nan = ieee80211_start_nan,
.stop_nan = ieee80211_stop_nan,
+ .nan_change_conf = ieee80211_nan_change_conf,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 67b42c8..50aeb3a 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1192,4 +1192,25 @@ static inline void drv_stop_nan(struct ieee80211_local *local,
trace_drv_return_void(local);
}

+static inline int drv_nan_change_conf(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_nan_conf *conf,
+ u32 changes)
+{
+ int ret;
+
+ might_sleep();
+ check_sdata_in_driver(sdata);
+
+ if (!local->ops->nan_change_conf)
+ return -EOPNOTSUPP;
+
+ trace_drv_nan_change_conf(local, sdata, conf, changes);
+ ret = local->ops->nan_change_conf(&local->hw, &sdata->vif, conf,
+ changes);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c71c735..712b20b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -830,6 +830,15 @@ struct ieee80211_if_mntr {
u8 mu_follow_addr[ETH_ALEN] __aligned(2);
};

+/**
+ * struct ieee80211_if_nan - NAN state
+ *
+ * @conf: current NAN configuration
+ */
+struct ieee80211_if_nan {
+ struct cfg80211_nan_conf conf;
+};
+
struct ieee80211_sub_if_data {
struct list_head list;

@@ -929,6 +938,7 @@ struct ieee80211_sub_if_data {
struct ieee80211_if_mesh mesh;
struct ieee80211_if_ocb ocb;
struct ieee80211_if_mntr mntr;
+ struct ieee80211_if_nan nan;
} u;

#ifdef CONFIG_MAC80211_DEBUGFS
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index deefbfb..0bafe11 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1750,6 +1750,37 @@ TRACE_EVENT(drv_stop_nan,
)
);

+TRACE_EVENT(drv_nan_change_conf,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_nan_conf *conf,
+ u32 changes),
+
+ TP_ARGS(local, sdata, conf, changes),
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(u8, master_pref)
+ __field(u8, dual)
+ __field(u32, changes)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->master_pref = conf->master_pref;
+ __entry->dual = conf->dual;
+ __entry->changes = changes;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT
+ ", master preference: %u, dual: %d, changes: 0x%x",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->master_pref,
+ __entry->dual, __entry->changes
+ )
+);
+
/*
* Tracing for API calls that drivers call.
*/
--
2.9.3

2016-09-16 08:33:34

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 1/9] cfg80211: add start / stop NAN commands

From: Ayala Beker <[email protected]>

This allows user space to start/stop NAN interface.
A NAN interface is like P2P device in a few aspects: it
doesn't have a netdev associated to it.
Add the new interface type and prevent operations that
can't be executed on NAN interface like scan.

Define several attributes that may be configured by user space
when starting NAN functionality (master preference and dual
band operation)

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 21 +++++++++-
include/uapi/linux/nl80211.h | 52 +++++++++++++++++++++++++
net/mac80211/cfg.c | 2 +
net/mac80211/chan.c | 3 ++
net/mac80211/iface.c | 4 ++
net/mac80211/offchannel.c | 1 +
net/mac80211/rx.c | 3 ++
net/mac80211/util.c | 1 +
net/wireless/chan.c | 2 +
net/wireless/core.c | 34 ++++++++++++++++
net/wireless/core.h | 3 ++
net/wireless/mlme.c | 1 +
net/wireless/nl80211.c | 93 ++++++++++++++++++++++++++++++++++++++++++--
net/wireless/rdev-ops.h | 20 ++++++++++
net/wireless/trace.h | 27 +++++++++++++
net/wireless/util.c | 6 ++-
16 files changed, 267 insertions(+), 6 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d5e7f69..ca64d69 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2293,6 +2293,19 @@ struct cfg80211_qos_map {
};

/**
+ * struct cfg80211_nan_conf - NAN configuration
+ *
+ * This struct defines NAN configuration parameters
+ *
+ * @master_pref: master preference (1 - 255)
+ * @dual: dual band operation mode
+ */
+struct cfg80211_nan_conf {
+ u8 master_pref;
+ enum nl80211_nan_dual_band_conf dual;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2580,6 +2593,8 @@ struct cfg80211_qos_map {
* and returning to the base channel for communication with the AP.
* @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
* peers must be on the base channel when the call completes.
+ * @start_nan: Start the NAN interface.
+ * @stop_nan: Stop the NAN interface.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2845,6 +2860,9 @@ struct cfg80211_ops {
void (*tdls_cancel_channel_switch)(struct wiphy *wiphy,
struct net_device *dev,
const u8 *addr);
+ int (*start_nan)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf);
+ void (*stop_nan)(struct wiphy *wiphy, struct wireless_dev *wdev);
};

/*
@@ -3602,6 +3620,7 @@ struct cfg80211_cached_keys;
* beacons, 0 when not valid
* @address: The address for this device, valid only if @netdev is %NULL
* @p2p_started: true if this is a P2P Device that has been started
+ * @nan_started: true if this is a NAN interface that has been started
* @cac_started: true if DFS channel availability check has been started
* @cac_start_time: timestamp (jiffies) when the dfs state was entered.
* @cac_time_ms: CAC time in ms
@@ -3633,7 +3652,7 @@ struct wireless_dev {

struct mutex mtx;

- bool use_4addr, p2p_started;
+ bool use_4addr, p2p_started, nan_started;

u8 address[ETH_ALEN] __aligned(sizeof(u16));

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2206941..7ab18c8 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -838,6 +838,16 @@
* not running. The driver indicates the status of the scan through
* cfg80211_scan_done().
*
+ * @NL80211_CMD_START_NAN: Start NAN operation, identified by its
+ * %NL80211_ATTR_WDEV interface. This interface must have been previously
+ * created with %NL80211_CMD_NEW_INTERFACE. After it has been started, the
+ * NAN interface will create or join a cluster. This command must have a
+ * valid %NL80211_ATTR_NAN_MASTER_PREF attribute and optional
+ * %NL80211_ATTR_NAN_DUAL attributes.
+ * After this command NAN functions can be added.
+ * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
+ * its %NL80211_ATTR_WDEV interface.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1026,6 +1036,9 @@ enum nl80211_commands {

NL80211_CMD_ABORT_SCAN,

+ NL80211_CMD_START_NAN,
+ NL80211_CMD_STOP_NAN,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -1733,6 +1746,12 @@ enum nl80211_commands {
* regulatory indoor configuration would be owned by the netlink socket
* that configured the indoor setting, and the indoor operation would be
* cleared when the socket is closed.
+ * If set during NAN interface creation, the interface will be destroyed
+ * if the socket is closed just like any other interface. Moreover, only
+ * the netlink socket that created the interface will be allowed to add
+ * and remove functions. NAN notifications will be sent in unicast to that
+ * socket. Without this attribute, any socket can add functions and the
+ * notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
*
* @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
* the TDLS link initiator.
@@ -1867,6 +1886,14 @@ enum nl80211_commands {
* @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
* used to pull the stored data for mesh peer in power save state.
*
+ * @NL80211_ATTR_NAN_MASTER_PREF: the master preference to be used by
+ * %NL80211_CMD_START_NAN. Its type is u8 and it can't be 0.
+ * Also, values 1 and 255 are reserved for certification purposes and
+ * should not be used during a normal device operation.
+ * @NL80211_ATTR_NAN_DUAL: NAN dual band operation config (see
+ * &enum nl80211_nan_dual_band_conf). This attribute is used with
+ * %NL80211_CMD_START_NAN.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2261,6 +2288,9 @@ enum nl80211_attrs {

NL80211_ATTR_MESH_PEER_AID,

+ NL80211_ATTR_NAN_MASTER_PREF,
+ NL80211_ATTR_NAN_DUAL,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -2339,6 +2369,7 @@ enum nl80211_attrs {
* commands to create and destroy one
* @NL80211_IF_TYPE_OCB: Outside Context of a BSS
* This mode corresponds to the MIB variable dot11OCBActivated=true
+ * @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
@@ -2359,6 +2390,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_P2P_GO,
NL80211_IFTYPE_P2P_DEVICE,
NL80211_IFTYPE_OCB,
+ NL80211_IFTYPE_NAN,

/* keep last */
NUM_NL80211_IFTYPES,
@@ -4855,4 +4887,24 @@ enum nl80211_bss_select_attr {
NL80211_BSS_SELECT_ATTR_MAX = __NL80211_BSS_SELECT_ATTR_AFTER_LAST - 1
};

+/**
+ * enum nl80211_nan_dual_band_conf - NAN dual band configuration
+ *
+ * Defines the NAN dual band mode of operation
+ *
+ * @NL80211_NAN_BAND_DEFAULT: device default mode
+ * @NL80211_NAN_BAND_SINGLE: 2.4GHz only mode
+ * @NL80211_NAN_BAND_DUAL: 2.4GHz and 5.2GHz mode
+ */
+enum nl80211_nan_dual_band_conf {
+ NL80211_NAN_BAND_DEFAULT,
+ NL80211_NAN_BAND_SINGLE,
+ NL80211_NAN_BAND_DUAL,
+
+ /* keep last */
+ __NL80211_NAN_BAND_AFTER_LAST,
+ NL80211_NAN_BAND_MAX =
+ __NL80211_NAN_BAND_AFTER_LAST - 1,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e29ff57..a74027f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -257,6 +257,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_UNSPECIFIED:
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_P2P_CLIENT:
@@ -2036,6 +2037,7 @@ static int ieee80211_scan(struct wiphy *wiphy,
!(req->flags & NL80211_SCAN_FLAG_AP)))
return -EOPNOTSUPP;
break;
+ case NL80211_IFTYPE_NAN:
default:
return -EOPNOTSUPP;
}
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 74142d0..acb50f8 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -274,6 +274,7 @@ ieee80211_get_chanctx_max_required_bw(struct ieee80211_local *local,
ieee80211_get_max_required_bw(sdata));
break;
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
continue;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
@@ -718,6 +719,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,

switch (sdata->vif.type) {
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
continue;
case NL80211_IFTYPE_STATION:
if (!sdata->u.mgd.associated)
@@ -981,6 +983,7 @@ ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata)
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
case NUM_NL80211_IFTYPES:
+ case NL80211_IFTYPE_NAN:
WARN_ON(1);
break;
}
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b0abddc7..e694ca2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -545,6 +545,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_OCB:
+ case NL80211_IFTYPE_NAN:
/* no special treatment */
break;
case NL80211_IFTYPE_UNSPECIFIED:
@@ -660,6 +661,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
break;
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
break;
default:
/* not reached */
@@ -948,6 +950,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* relies on synchronize_rcu() below */
RCU_INIT_POINTER(local->p2p_sdata, NULL);
/* fall through */
+ case NL80211_IFTYPE_NAN:
default:
cancel_work_sync(&sdata->work);
/*
@@ -1457,6 +1460,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
break;
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 55a9c5b..75d5c96 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -838,6 +838,7 @@ int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
case NL80211_IFTYPE_P2P_DEVICE:
need_offchan = true;
break;
+ case NL80211_IFTYPE_NAN:
default:
return -EOPNOTSUPP;
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e796060..c9489a8 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3586,6 +3586,9 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
ieee80211_is_probe_req(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
ieee80211_is_beacon(hdr->frame_control);
+ case NL80211_IFTYPE_NAN:
+ /* Currently no frames on NAN interface are allowed */
+ return false;
default:
break;
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index b6865d8..2c78541 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1975,6 +1975,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 0f50622..5497d022 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -372,6 +372,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NUM_NL80211_IFTYPES:
@@ -946,6 +947,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
/* these interface types don't really have a channel */
return;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 4911cd9..0139872 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -225,6 +225,23 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
}
}

+void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ ASSERT_RTNL();
+
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN))
+ return;
+
+ if (!wdev->nan_started)
+ return;
+
+ rdev_stop_nan(rdev, wdev);
+ wdev->nan_started = false;
+
+ rdev->opencount--;
+}
+
void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
@@ -242,6 +259,9 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
case NL80211_IFTYPE_P2P_DEVICE:
cfg80211_stop_p2p_device(rdev, wdev);
break;
+ case NL80211_IFTYPE_NAN:
+ cfg80211_stop_nan(rdev, wdev);
+ break;
default:
break;
}
@@ -537,6 +557,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
c->limits[j].max > 1))
return -EINVAL;

+ /* Only a single NAN can be allowed */
+ if (WARN_ON(types & BIT(NL80211_IFTYPE_NAN) &&
+ c->limits[j].max > 1))
+ return -EINVAL;
+
cnt += c->limits[j].max;
/*
* Don't advertise an unsupported type
@@ -579,6 +604,10 @@ int wiphy_register(struct wiphy *wiphy)
!rdev->ops->tdls_cancel_channel_switch)))
return -EINVAL;

+ if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) &&
+ (!rdev->ops->start_nan || !rdev->ops->stop_nan)))
+ return -EINVAL;
+
/*
* if a wiphy has unsupported modes for regulatory channel enforcement,
* opt-out of enforcement checking
@@ -589,6 +618,7 @@ int wiphy_register(struct wiphy *wiphy)
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_P2P_DEVICE) |
+ BIT(NL80211_IFTYPE_NAN) |
BIT(NL80211_IFTYPE_AP_VLAN) |
BIT(NL80211_IFTYPE_MONITOR)))
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
@@ -916,6 +946,9 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
cfg80211_mlme_purge_registrations(wdev);
cfg80211_stop_p2p_device(rdev, wdev);
break;
+ case NL80211_IFTYPE_NAN:
+ cfg80211_stop_nan(rdev, wdev);
+ break;
default:
WARN_ON_ONCE(1);
break;
@@ -979,6 +1012,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
/* must be handled by mac80211/driver, has no APIs */
break;
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
/* cannot happen, has no netdev */
break;
case NL80211_IFTYPE_AP_VLAN:
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 5555e3c..9cdca5e 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -488,6 +488,9 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev);

+void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev);
+
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10

#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index d6abb07..cbb48e2 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -634,6 +634,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
* fall through, P2P device only supports
* public action frames
*/
+ case NL80211_IFTYPE_NAN:
default:
err = -EOPNOTSUPP;
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 887c4c1..90580f9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -409,6 +409,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
.len = VHT_MUMIMO_GROUPS_DATA_LEN
},
[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
+ [NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
+ [NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 },
};

/* policy for the key attributes */
@@ -934,6 +936,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_MONITOR:
+ case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_P2P_DEVICE:
case NL80211_IFTYPE_WDS:
case NUM_NL80211_IFTYPES:
@@ -2819,7 +2822,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
!(rdev->wiphy.interface_modes & (1 << type)))
return -EOPNOTSUPP;

- if ((type == NL80211_IFTYPE_P2P_DEVICE ||
+ if ((type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN ||
rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
info->attrs[NL80211_ATTR_MAC]) {
nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
@@ -2875,9 +2878,10 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
wdev->mesh_id_up_len);
wdev_unlock(wdev);
break;
+ case NL80211_IFTYPE_NAN:
case NL80211_IFTYPE_P2P_DEVICE:
/*
- * P2P Device doesn't have a netdev, so doesn't go
+ * P2P Device and NAN do not have a netdev, so don't go
* through the netdev notifier and must be added here
*/
mutex_init(&wdev->mtx);
@@ -6138,6 +6142,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)

wiphy = &rdev->wiphy;

+ if (wdev->iftype == NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
if (!rdev->ops->scan)
return -EOPNOTSUPP;

@@ -8898,6 +8905,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
break;
+ case NL80211_IFTYPE_NAN:
default:
return -EOPNOTSUPP;
}
@@ -8943,6 +8951,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_P2P_GO:
break;
+ case NL80211_IFTYPE_NAN:
default:
return -EOPNOTSUPP;
}
@@ -9059,6 +9068,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
break;
+ case NL80211_IFTYPE_NAN:
default:
return -EOPNOTSUPP;
}
@@ -10414,6 +10424,60 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
return 0;
}

+static int nl80211_start_nan(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ struct cfg80211_nan_conf conf = {};
+ int err;
+
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (wdev->nan_started)
+ return -EEXIST;
+
+ if (rfkill_blocked(rdev->rfkill))
+ return -ERFKILL;
+
+ if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF])
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_NAN_DUAL])
+ return -EINVAL;
+
+ conf.master_pref =
+ nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
+ if (!conf.master_pref)
+ return -EINVAL;
+
+ conf.dual = nla_get_u8(info->attrs[NL80211_ATTR_NAN_DUAL]);
+ if (conf.dual > NL80211_NAN_BAND_MAX)
+ return -EINVAL;
+
+ err = rdev_start_nan(rdev, wdev, &conf);
+ if (err)
+ return err;
+
+ wdev->nan_started = true;
+ rdev->opencount++;
+
+ return 0;
+}
+
+static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ cfg80211_stop_nan(rdev, wdev);
+
+ return 0;
+}
+
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{
@@ -11115,7 +11179,14 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,

dev_hold(dev);
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
- if (!wdev->p2p_started) {
+ if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE &&
+ !wdev->p2p_started) {
+ if (rtnl)
+ rtnl_unlock();
+ return -ENETDOWN;
+ }
+ if (wdev->iftype == NL80211_IFTYPE_NAN &&
+ !wdev->nan_started) {
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
@@ -11749,6 +11820,22 @@ static const struct genl_ops nl80211_ops[] = {
NL80211_FLAG_NEED_RTNL,
},
{
+ .cmd = NL80211_CMD_START_NAN,
+ .doit = nl80211_start_nan,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_STOP_NAN,
+ .doit = nl80211_stop_nan,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
.cmd = NL80211_CMD_SET_MCAST_RATE,
.doit = nl80211_set_mcast_rate,
.policy = nl80211_policy,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 85ff30b..afb68a8 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -887,6 +887,26 @@ static inline void rdev_stop_p2p_device(struct cfg80211_registered_device *rdev,
trace_rdev_return_void(&rdev->wiphy);
}

+static inline int rdev_start_nan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf)
+{
+ int ret;
+
+ trace_rdev_start_nan(&rdev->wiphy, wdev, conf);
+ ret = rdev->ops->start_nan(&rdev->wiphy, wdev, conf);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_stop_nan(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev)
+{
+ trace_rdev_stop_nan(&rdev->wiphy, wdev);
+ rdev->ops->stop_nan(&rdev->wiphy, wdev);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_acl_data *params)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 72b5255..5f3370f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1889,6 +1889,33 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_p2p_device,
TP_ARGS(wiphy, wdev)
);

+TRACE_EVENT(rdev_start_nan,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf),
+ TP_ARGS(wiphy, wdev, conf),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u8, master_pref)
+ __field(u8, dual);
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->master_pref = conf->master_pref;
+ __entry->dual = conf->dual;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT
+ ", master preference: %u, dual: %d",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->master_pref,
+ __entry->dual)
+);
+
+DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_nan,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+ TP_ARGS(wiphy, wdev)
+);
+
TRACE_EVENT(rdev_set_mac_acl,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_acl_data *params),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 9e6e2aa..91868e0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1008,8 +1008,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
if (otype == NL80211_IFTYPE_AP_VLAN)
return -EOPNOTSUPP;

- /* cannot change into P2P device type */
- if (ntype == NL80211_IFTYPE_P2P_DEVICE)
+ /* cannot change into P2P device or NAN */
+ if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
+ ntype == NL80211_IFTYPE_NAN)
return -EOPNOTSUPP;

if (!rdev->ops->change_virtual_intf ||
@@ -1088,6 +1089,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
/* not happening */
break;
case NL80211_IFTYPE_P2P_DEVICE:
+ case NL80211_IFTYPE_NAN:
WARN_ON(1);
break;
}
--
2.9.3

2016-09-16 08:33:44

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 9/9] mac80211: Add API to report NAN function match

From: Ayala Beker <[email protected]>

Provide an API to report NAN function match. Mac80211 will lookup the
corresponding cookie and report the match to cfg80211.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/mac80211.h | 16 ++++++++++++++++
net/mac80211/cfg.c | 25 +++++++++++++++++++++++++
2 files changed, 41 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5b74229..1b6271e 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -5777,4 +5777,20 @@ void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
u8 inst_id,
enum nl80211_nan_func_term_reason reason,
gfp_t gfp);
+
+/**
+ * ieee80211_nan_func_match - notify about NAN function match event.
+ *
+ * This function is used to notify mac80211 about NAN function match. The
+ * cookie inside the match struct will be assigned by mac80211.
+ * Note that this function can't be called from hard irq.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @match: match event information
+ * @gfp: allocation flags
+ */
+void ieee80211_nan_func_match(struct ieee80211_vif *vif,
+ struct cfg80211_nan_match_params *match,
+ gfp_t gfp);
+
#endif /* MAC80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index aee0e25c..20ac00f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3555,6 +3555,31 @@ void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
}
EXPORT_SYMBOL(ieee80211_nan_func_terminated);

+void ieee80211_nan_func_match(struct ieee80211_vif *vif,
+ struct cfg80211_nan_match_params *match,
+ gfp_t gfp)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct cfg80211_nan_func *func;
+
+ if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
+ return;
+
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ func = idr_find(&sdata->u.nan.function_inst_ids, match->inst_id);
+ if (WARN_ON(!func)) {
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+ return;
+ }
+ match->cookie = func->cookie;
+
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+
+ cfg80211_nan_match(ieee80211_vif_to_wdev(vif), match, gfp);
+}
+EXPORT_SYMBOL(ieee80211_nan_func_match);
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
--
2.9.3

2016-09-16 11:09:01

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> This code doesn't do much besides allowing to start and
> stop the vif.
>
> Signed-off-by: Andrei Otcheretianski <[email protected]>
> Signed-off-by: Emmanuel Grumbach <[email protected]>
> Signed-off-by: Ayala Beker <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>
> ---
> include/net/mac80211.h | 9 +++++++++
> net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
> net/mac80211/chan.c | 3 +++
> net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
> net/mac80211/iface.c | 8 ++++++--
> net/mac80211/main.c | 5 +++++
> net/mac80211/offchannel.c | 3 ++-
> net/mac80211/trace.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++
> net/mac80211/util.c | 3 ++-
> 9 files changed, 141 insertions(+), 5 deletions(-)

[...]

> diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
> index fe35a1c..67b42c8 100644
> --- a/net/mac80211/driver-ops.h
> +++ b/net/mac80211/driver-ops.h
> @@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,
>
> if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
> (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
> - !sdata->vif.mu_mimo_owner)))
> + !sdata->vif.mu_mimo_owner) ||
> + sdata->vif.type == NL80211_IFTYPE_NAN))

Might be more clear to move this up right after P2P_DEVICE check.

> return;
>
> if (!check_sdata_in_driver(sdata))
> @@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
> local->ops->wake_tx_queue(&local->hw, &txq->txq);
> }
>
> +static inline int drv_start_nan(struct ieee80211_local *local,
> + struct ieee80211_sub_if_data *sdata,
> + struct cfg80211_nan_conf *conf)
> +{
> + int ret;
> +
> + might_sleep();
> + check_sdata_in_driver(sdata);
> +
> + trace_drv_start_nan(local, sdata, conf);
> + ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
> + trace_drv_return_int(local, ret);
> + return ret;
> +}
> +
> +static inline void drv_stop_nan(struct ieee80211_local *local,
> + struct ieee80211_sub_if_data *sdata)
> +{
> + might_sleep();
> + check_sdata_in_driver(sdata);
> +
> + trace_drv_stop_nan(local, sdata);
> + local->ops->stop_nan(&local->hw, &sdata->vif);
> + trace_drv_return_void(local);
> +}
> +
> #endif /* __MAC80211_DRIVER_OPS */
> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
> index e694ca2..507f46a 100644
> --- a/net/mac80211/iface.c
> +++ b/net/mac80211/iface.c
> @@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
> int n_queues = sdata->local->hw.queues;
> int i;
>
> + if (iftype == NL80211_IFTYPE_NAN)
> + return 0;
> +
> if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
> @@ -647,7 +650,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
> local->fif_probe_req++;
> }
>
> - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
> + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
> + sdata->vif.type != NL80211_IFTYPE_NAN)

similar check keeps reoccuring in various places so maybe we can create
a helper function for it.

> changed |= ieee80211_reset_erp_info(sdata);
> ieee80211_bss_info_change_notify(sdata, changed);
>

Regards,
Arend

2016-09-16 08:33:36

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

From: Ayala Beker <[email protected]>

This code doesn't do much besides allowing to start and
stop the vif.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Ayala Beker <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/mac80211.h | 9 +++++++++
net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
net/mac80211/chan.c | 3 +++
net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
net/mac80211/iface.c | 8 ++++++--
net/mac80211/main.c | 5 +++++
net/mac80211/offchannel.c | 3 ++-
net/mac80211/trace.h | 50 +++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/util.c | 3 ++-
9 files changed, 141 insertions(+), 5 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5296100..df9b5cf 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3420,6 +3420,9 @@ enum ieee80211_reconfig_type {
* synchronization which is needed in case driver has in its RSS queues
* pending frames that were received prior to the control path action
* currently taken (e.g. disassociation) but are not processed yet.
+ *
+ * @start_nan: join an existing NAN cluster, or create a new one.
+ * @stop_nan: leave the NAN cluster.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3655,6 +3658,12 @@ struct ieee80211_ops {
void (*wake_tx_queue)(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
void (*sync_rx_queues)(struct ieee80211_hw *hw);
+
+ int (*start_nan)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_nan_conf *conf);
+ int (*stop_nan)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a74027f..9aabb09 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3,6 +3,7 @@
*
* Copyright 2006-2010 Johannes Berg <[email protected]>
* Copyright 2013-2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2015-2016 Intel Deutschland GmbH
*
* This file is GPLv2 as found in COPYING.
*/
@@ -152,6 +153,39 @@ static void ieee80211_stop_p2p_device(struct wiphy *wiphy,
ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev));
}

+static int ieee80211_start_nan(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ int ret;
+
+ mutex_lock(&sdata->local->chanctx_mtx);
+ ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
+ mutex_unlock(&sdata->local->chanctx_mtx);
+ if (ret < 0)
+ return ret;
+
+ ret = ieee80211_do_open(wdev, true);
+ if (ret)
+ return ret;
+
+ ret = drv_start_nan(sdata->local, sdata, conf);
+ if (ret)
+ ieee80211_sdata_stop(sdata);
+
+ return ret;
+}
+
+static void ieee80211_stop_nan(struct wiphy *wiphy,
+ struct wireless_dev *wdev)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+
+ drv_stop_nan(sdata->local, sdata);
+ ieee80211_sdata_stop(sdata);
+}
+
static int ieee80211_set_noack_map(struct wiphy *wiphy,
struct net_device *dev,
u16 noack_map)
@@ -3464,4 +3498,6 @@ const struct cfg80211_ops mac80211_config_ops = {
.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
.add_tx_ts = ieee80211_add_tx_ts,
.del_tx_ts = ieee80211_del_tx_ts,
+ .start_nan = ieee80211_start_nan,
+ .stop_nan = ieee80211_stop_nan,
};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index acb50f8..e4d147e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -647,6 +647,9 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
struct ieee80211_chanctx *curr_ctx = NULL;
int ret = 0;

+ if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN))
+ return -ENOTSUPP;
+
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
lockdep_is_held(&local->chanctx_mtx));

diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index fe35a1c..67b42c8 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local,

if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
(sdata->vif.type == NL80211_IFTYPE_MONITOR &&
- !sdata->vif.mu_mimo_owner)))
+ !sdata->vif.mu_mimo_owner) ||
+ sdata->vif.type == NL80211_IFTYPE_NAN))
return;

if (!check_sdata_in_driver(sdata))
@@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
local->ops->wake_tx_queue(&local->hw, &txq->txq);
}

+static inline int drv_start_nan(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_nan_conf *conf)
+{
+ int ret;
+
+ might_sleep();
+ check_sdata_in_driver(sdata);
+
+ trace_drv_start_nan(local, sdata, conf);
+ ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
+static inline void drv_stop_nan(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
+{
+ might_sleep();
+ check_sdata_in_driver(sdata);
+
+ trace_drv_stop_nan(local, sdata);
+ local->ops->stop_nan(&local->hw, &sdata->vif);
+ trace_drv_return_void(local);
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index e694ca2..507f46a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
int n_queues = sdata->local->hw.queues;
int i;

+ if (iftype == NL80211_IFTYPE_NAN)
+ return 0;
+
if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
@@ -647,7 +650,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
local->fif_probe_req++;
}

- if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
+ if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+ sdata->vif.type != NL80211_IFTYPE_NAN)
changed |= ieee80211_reset_erp_info(sdata);
ieee80211_bss_info_change_notify(sdata, changed);

@@ -1726,7 +1730,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

ASSERT_RTNL();

- if (type == NL80211_IFTYPE_P2P_DEVICE) {
+ if (type == NL80211_IFTYPE_P2P_DEVICE || type == NL80211_IFTYPE_NAN) {
struct wireless_dev *wdev;

sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size,
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ac053a9..b5cf2c5 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -821,6 +821,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
!local->ops->tdls_recv_channel_switch))
return -EOPNOTSUPP;

+ if (WARN_ON(local->hw.wiphy->interface_modes &
+ BIT(NL80211_IFTYPE_NAN) &&
+ (!local->ops->start_nan || !local->ops->stop_nan)))
+ return -EINVAL;
+
#ifdef CONFIG_PM
if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
return -EINVAL;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 75d5c96..c3f610b 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -128,7 +128,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
if (!ieee80211_sdata_running(sdata))
continue;

- if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
+ if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
+ sdata->vif.type == NL80211_IFTYPE_NAN)
continue;

if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 77e4c53..deefbfb 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1700,6 +1700,56 @@ TRACE_EVENT(drv_get_expected_throughput,
)
);

+TRACE_EVENT(drv_start_nan,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_nan_conf *conf),
+
+ TP_ARGS(local, sdata, conf),
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(u8, master_pref)
+ __field(u8, dual)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->master_pref = conf->master_pref;
+ __entry->dual = conf->dual;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT
+ ", master preference: %u, dual: %d",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->master_pref,
+ __entry->dual
+ )
+);
+
+TRACE_EVENT(drv_stop_nan,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+
+ TP_ARGS(local, sdata),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT,
+ LOCAL_PR_ARG, VIF_PR_ARG
+ )
+);
+
/*
* Tracing for API calls that drivers call.
*/
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2c78541..5b57fca 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1209,7 +1209,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
}

if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
- sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) {
+ sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
+ sdata->vif.type != NL80211_IFTYPE_NAN) {
sdata->vif.bss_conf.qos = enable_qos;
if (bss_notify)
ieee80211_bss_info_change_notify(sdata,
--
2.9.3

2016-09-18 19:43:15

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 4/9] cfg80211: allow the user space to change current NAN configuration

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> Some NAN configuration paramaters may change during the operation of
> the NaN device. For example, a user may want to update master preference

typo: NAN iso NaN.

Regards,
Arend

2016-09-16 08:33:43

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 8/9] mac80211: Implement add_nan_func and rm_nan_func

From: Ayala Beker <[email protected]>

Implement add/rm_nan_func functions and handle NAN function
termination notifications. Handle instance_id allocation for
NAN functions and implement the reconfig flow.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/mac80211.h | 31 ++++++++++++
net/mac80211/cfg.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 32 +++++++++++++
net/mac80211/ieee80211_i.h | 7 +++
net/mac80211/iface.c | 20 +++++++-
net/mac80211/main.c | 3 ++
net/mac80211/trace.h | 52 +++++++++++++++++++++
net/mac80211/util.c | 48 ++++++++++++++++++-
8 files changed, 304 insertions(+), 3 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ef8d02a..5b74229 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2177,6 +2177,8 @@ enum ieee80211_hw_flags {
* @n_cipher_schemes: a size of an array of cipher schemes definitions.
* @cipher_schemes: a pointer to an array of cipher scheme definitions
* supported by HW.
+ * @max_nan_de_entries: maximum number of NAN DE functions supported by the
+ * device.
*/
struct ieee80211_hw {
struct ieee80211_conf conf;
@@ -2211,6 +2213,7 @@ struct ieee80211_hw {
u8 uapsd_max_sp_len;
u8 n_cipher_schemes;
const struct ieee80211_cipher_scheme *cipher_schemes;
+ u8 max_nan_de_entries;
};

static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
@@ -3429,6 +3432,12 @@ enum ieee80211_reconfig_type {
* The driver gets both full configuration and the changed parameters since
* some devices may need the full configuration while others need only the
* changed parameters.
+ * @add_nan_func: Add a NAN function. Returns 0 on success. The data in
+ * cfg80211_nan_func must not be referenced outside the scope of
+ * this call.
+ * @rm_nan_func: Remove a NAN function. The driver must call
+ * ieee80211_nan_func_terminated() with
+ * NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3673,6 +3682,12 @@ struct ieee80211_ops {
int (*nan_change_conf)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_nan_conf *conf, u32 changes);
+ int (*add_nan_func)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ const struct cfg80211_nan_func *nan_func);
+ void (*rm_nan_func)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u8 instance_id);
};

/**
@@ -5746,4 +5761,20 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
unsigned long *frame_cnt,
unsigned long *byte_cnt);
+
+/**
+ * ieee80211_nan_func_terminated - notify about NAN function termination.
+ *
+ * This function is used to notify mac80211 about NAN function termination.
+ * Note that this function can't be called from hard irq.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @inst_id: the local instance id
+ * @reason: termination reason (one of the NL80211_NAN_FUNC_TERM_REASON_*)
+ * @gfp: allocation flags
+ */
+void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
+ u8 inst_id,
+ enum nl80211_nan_func_term_reason reason,
+ gfp_t gfp);
#endif /* MAC80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 38fdb53..aee0e25c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -174,6 +174,8 @@ static int ieee80211_start_nan(struct wiphy *wiphy,
if (ret)
ieee80211_sdata_stop(sdata);

+ sdata->u.nan.conf = *conf;
+
return ret;
}

@@ -216,6 +218,84 @@ static int ieee80211_nan_change_conf(struct wiphy *wiphy,
return ret;
}

+static int ieee80211_add_nan_func(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_func *nan_func)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ int ret;
+
+ if (sdata->vif.type != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (!ieee80211_sdata_running(sdata))
+ return -ENETDOWN;
+
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ ret = idr_alloc(&sdata->u.nan.function_inst_ids,
+ nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
+ GFP_ATOMIC);
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+
+ if (ret < 0)
+ return ret;
+
+ nan_func->instance_id = ret;
+
+ WARN_ON(nan_func->instance_id == 0);
+
+ ret = drv_add_nan_func(sdata->local, sdata, nan_func);
+ if (ret) {
+ spin_lock_bh(&sdata->u.nan.func_lock);
+ idr_remove(&sdata->u.nan.function_inst_ids,
+ nan_func->instance_id);
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+ }
+
+ return ret;
+}
+
+static struct cfg80211_nan_func *
+ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
+ u64 cookie)
+{
+ struct cfg80211_nan_func *func;
+ int id;
+
+ lockdep_assert_held(&sdata->u.nan.func_lock);
+
+ idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
+ if (func->cookie == cookie)
+ return func;
+ }
+
+ return NULL;
+}
+
+static void ieee80211_rm_nan_func(struct wiphy *wiphy,
+ struct wireless_dev *wdev, u64 cookie)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct cfg80211_nan_func *func;
+ u8 instance_id = 0;
+
+ if (sdata->vif.type != NL80211_IFTYPE_NAN ||
+ !ieee80211_sdata_running(sdata))
+ return;
+
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
+ if (func)
+ instance_id = func->instance_id;
+
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+
+ if (instance_id)
+ drv_rm_nan_func(sdata->local, sdata, instance_id);
+}
+
static int ieee80211_set_noack_map(struct wiphy *wiphy,
struct net_device *dev,
u16 noack_map)
@@ -3443,6 +3523,38 @@ static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
return -ENOENT;
}

+void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
+ u8 inst_id,
+ enum nl80211_nan_func_term_reason reason,
+ gfp_t gfp)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct cfg80211_nan_func *func;
+ u64 cookie;
+
+ if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
+ return;
+
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
+ if (WARN_ON(!func)) {
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+ return;
+ }
+
+ cookie = func->cookie;
+ idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
+
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+
+ cfg80211_free_nan_func(func);
+
+ cfg80211_nan_func_terminated(ieee80211_vif_to_wdev(vif), inst_id,
+ reason, cookie, gfp);
+}
+EXPORT_SYMBOL(ieee80211_nan_func_terminated);
+
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3531,4 +3643,6 @@ const struct cfg80211_ops mac80211_config_ops = {
.start_nan = ieee80211_start_nan,
.stop_nan = ieee80211_stop_nan,
.nan_change_conf = ieee80211_nan_change_conf,
+ .add_nan_func = ieee80211_add_nan_func,
+ .rm_nan_func = ieee80211_rm_nan_func,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 50aeb3a..ff1066b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1213,4 +1213,36 @@ static inline int drv_nan_change_conf(struct ieee80211_local *local,
return ret;
}

+static inline int drv_add_nan_func(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_nan_func *nan_func)
+{
+ int ret;
+
+ might_sleep();
+ check_sdata_in_driver(sdata);
+
+ if (!local->ops->add_nan_func)
+ return -EOPNOTSUPP;
+
+ trace_drv_add_nan_func(local, sdata, nan_func);
+ ret = local->ops->add_nan_func(&local->hw, &sdata->vif, nan_func);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
+static inline void drv_rm_nan_func(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ u8 instance_id)
+{
+ might_sleep();
+ check_sdata_in_driver(sdata);
+
+ trace_drv_rm_nan_func(local, sdata, instance_id);
+ if (local->ops->rm_nan_func)
+ local->ops->rm_nan_func(&local->hw, &sdata->vif, instance_id);
+ trace_drv_return_void(local);
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 712b20b..2b391f2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -86,6 +86,8 @@ struct ieee80211_local;

#define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */)

+#define IEEE80211_MAX_NAN_INSTANCE_ID 255
+
struct ieee80211_fragment_entry {
struct sk_buff_head skb_list;
unsigned long first_frag_time;
@@ -834,9 +836,14 @@ struct ieee80211_if_mntr {
* struct ieee80211_if_nan - NAN state
*
* @conf: current NAN configuration
+ * @func_ids: a bitmap of available instance_id's
*/
struct ieee80211_if_nan {
struct cfg80211_nan_conf conf;
+
+ /* protects function_inst_ids */
+ spinlock_t func_lock;
+ struct idr function_inst_ids;
};

struct ieee80211_sub_if_data {
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 507f46a..638ec07 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -798,6 +798,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
struct ps_data *ps;
struct cfg80211_chan_def chandef;
bool cancel_scan;
+ struct cfg80211_nan_func *func;

clear_bit(SDATA_STATE_RUNNING, &sdata->state);

@@ -950,11 +951,22 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,

ieee80211_adjust_monitor_flags(sdata, -1);
break;
+ case NL80211_IFTYPE_NAN:
+ /* clean all the functions */
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, i) {
+ idr_remove(&sdata->u.nan.function_inst_ids, i);
+ cfg80211_free_nan_func(func);
+ }
+ idr_destroy(&sdata->u.nan.function_inst_ids);
+
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+ break;
case NL80211_IFTYPE_P2P_DEVICE:
/* relies on synchronize_rcu() below */
RCU_INIT_POINTER(local->p2p_sdata, NULL);
/* fall through */
- case NL80211_IFTYPE_NAN:
default:
cancel_work_sync(&sdata->work);
/*
@@ -1462,9 +1474,13 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_WDS:
sdata->vif.bss_conf.bssid = NULL;
break;
+ case NL80211_IFTYPE_NAN:
+ idr_init(&sdata->u.nan.function_inst_ids);
+ spin_lock_init(&sdata->u.nan.func_lock);
+ sdata->vif.bss_conf.bssid = sdata->vif.addr;
+ break;
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_DEVICE:
- case NL80211_IFTYPE_NAN:
sdata->vif.bss_conf.bssid = sdata->vif.addr;
break;
case NL80211_IFTYPE_UNSPECIFIED:
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index b5cf2c5..1075ac2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1063,6 +1063,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)

local->dynamic_ps_forced_timeout = -1;

+ if (!local->hw.max_nan_de_entries)
+ local->hw.max_nan_de_entries = IEEE80211_MAX_NAN_INSTANCE_ID;
+
result = ieee80211_wep_init(local);
if (result < 0)
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 0bafe11..e6bed8a 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1781,6 +1781,58 @@ TRACE_EVENT(drv_nan_change_conf,
)
);

+TRACE_EVENT(drv_add_nan_func,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ const struct cfg80211_nan_func *func),
+
+ TP_ARGS(local, sdata, func),
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(u8, type)
+ __field(u8, inst_id)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->type = func->type;
+ __entry->inst_id = func->instance_id;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT
+ ", type: %u, inst_id: %u",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->type, __entry->inst_id
+ )
+);
+
+TRACE_EVENT(drv_rm_nan_func,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ u8 instance_id),
+
+ TP_ARGS(local, sdata, instance_id),
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ __field(u8, instance_id)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ __entry->instance_id = instance_id;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT
+ ", instance_id: %u",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->instance_id
+ )
+);
+
/*
* Tracing for API calls that drivers call.
*/
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 5b57fca..91754c8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1749,6 +1749,46 @@ static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
mutex_unlock(&local->sta_mtx);
}

+static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
+{
+ struct cfg80211_nan_func *func, **funcs;
+ int res, id, i = 0;
+
+ res = drv_start_nan(sdata->local, sdata,
+ &sdata->u.nan.conf);
+ if (WARN_ON(res))
+ return res;
+
+ funcs = kzalloc((sdata->local->hw.max_nan_de_entries + 1) *
+ sizeof(*funcs), GFP_KERNEL);
+ if (!funcs)
+ return -ENOMEM;
+
+ /* Add all the functions:
+ * This is a little bit ugly. We need to call a potentially sleeping
+ * callback for each NAN function, so we can't hold the spinlock.
+ */
+ spin_lock_bh(&sdata->u.nan.func_lock);
+
+ idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id)
+ funcs[i++] = func;
+
+ spin_unlock_bh(&sdata->u.nan.func_lock);
+
+ for (i = 0; funcs[i]; i++) {
+ res = drv_add_nan_func(sdata->local, sdata, funcs[i]);
+ if (WARN_ON(res))
+ ieee80211_nan_func_terminated(&sdata->vif,
+ funcs[i]->instance_id,
+ NL80211_NAN_FUNC_TERM_REASON_ERROR,
+ GFP_KERNEL);
+ }
+
+ kfree(funcs);
+
+ return 0;
+}
+
int ieee80211_reconfig(struct ieee80211_local *local)
{
struct ieee80211_hw *hw = &local->hw;
@@ -1972,11 +2012,17 @@ int ieee80211_reconfig(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(sdata, changed);
}
break;
+ case NL80211_IFTYPE_NAN:
+ res = ieee80211_reconfig_nan(sdata);
+ if (res < 0) {
+ ieee80211_handle_reconfig_failure(local);
+ return res;
+ }
+ break;
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_P2P_DEVICE:
- case NL80211_IFTYPE_NAN:
/* nothing to do */
break;
case NL80211_IFTYPE_UNSPECIFIED:
--
2.9.3

2016-09-16 08:33:39

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 5/9] cfg80211: provide a function to report a match for NAN

From: Ayala Beker <[email protected]>

Provide a function the driver can call to report a match.
This will send the event to the user space.
If the NAN instance is tied to the owner, the notifications will be
sent to the socket that started the NAN interface only.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 37 +++++++++++++++++++++
include/uapi/linux/nl80211.h | 31 ++++++++++++++++++
net/wireless/nl80211.c | 78 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 146 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b819e32..a08d7da 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5639,6 +5639,43 @@ wiphy_ext_feature_isset(struct wiphy *wiphy,
*/
void cfg80211_free_nan_func(struct cfg80211_nan_func *f);

+/**
+ * struct cfg80211_nan_match_params - NAN match parameters
+ * @type: the type of the function that triggered a match. If it is
+ * %NL80211_NAN_FUNC_SUBSCRIBE it means that we replied to a subscriber.
+ * If it is %NL80211_NAN_FUNC_PUBLISH, it means that we got a discovery
+ * result.
+ * If it is %NL80211_NAN_FUNC_FOLLOW_UP, we received a follow up.
+ * @inst_id: the local instance id
+ * @peer_inst_id: the instance id of the peer's function
+ * @addr: the MAC address of the peer
+ * @info_len: the length of the &info
+ * @info: the Service Specific Info from the peer (if any)
+ * @cookie: unique identifier of the corresponding function
+ */
+struct cfg80211_nan_match_params {
+ enum nl80211_nan_function_type type;
+ u8 inst_id;
+ u8 peer_inst_id;
+ const u8 *addr;
+ u8 info_len;
+ const u8 *info;
+ u64 cookie;
+};
+
+/**
+ * cfg80211_nan_match - report a match for a NAN function.
+ * @wdev: the wireless device reporting the match
+ * @match: match notification parameters
+ * @gfp: allocation flags
+ *
+ * This function reports that the a NAN function had a match. This
+ * can be a subscribe that had a match or a solicited publish that
+ * was sent. It can also be a follow up that was received.
+ */
+void cfg80211_nan_match(struct wireless_dev *wdev,
+ struct cfg80211_nan_match_params *match, gfp_t gfp);
+
/* ethtool helper */
void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9cf1744..badb4a6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -48,6 +48,7 @@
#define NL80211_MULTICAST_GROUP_REG "regulatory"
#define NL80211_MULTICAST_GROUP_MLME "mlme"
#define NL80211_MULTICAST_GROUP_VENDOR "vendor"
+#define NL80211_MULTICAST_GROUP_NAN "nan"
#define NL80211_MULTICAST_GROUP_TESTMODE "testmode"

/**
@@ -869,6 +870,9 @@
* must be operational (%NL80211_CMD_START_NAN was executed).
* It must contain at least one of the following attributes:
* %NL80211_ATTR_NAN_MASTER_PREF, %NL80211_ATTR_NAN_DUAL.
+ * @NL80211_CMD_NAN_FUNC_MATCH: Notification sent when a match is reported.
+ * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and
+ * %NL80211_ATTR_COOKIE.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -1063,6 +1067,7 @@ enum nl80211_commands {
NL80211_CMD_ADD_NAN_FUNCTION,
NL80211_CMD_RM_NAN_FUNCTION,
NL80211_CMD_CHANGE_NAN_CONFIG,
+ NL80211_CMD_NAN_MATCH,

/* add new commands above here */

@@ -1923,6 +1928,8 @@ enum nl80211_commands {
* @NL80211_ATTR_NAN_FUNC: a function that can be added to NAN. See
* &enum nl80211_nan_func_attributes for description of this nested
* attribute.
+ * @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute.
+ * See &enum nl80211_nan_match_attributes.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2321,6 +2328,7 @@ enum nl80211_attrs {
NL80211_ATTR_NAN_MASTER_PREF,
NL80211_ATTR_NAN_DUAL,
NL80211_ATTR_NAN_FUNC,
+ NL80211_ATTR_NAN_MATCH,

/* add attributes here, update the policy in nl80211.c */

@@ -5067,4 +5075,27 @@ enum nl80211_nan_srf_attributes {
NL80211_NAN_SRF_ATTR_MAX = NUM_NL80211_NAN_SRF_ATTR - 1,
};

+/**
+ * enum nl80211_nan_match_attributes - NAN match attributes
+ * @__NL80211_NAN_MATCH_INVALID: invalid
+ * @NL80211_NAN_MATCH_FUNC_LOCAL: the local function that had the
+ * match. This is a nested attribute.
+ * See &enum nl80211_nan_func_attributes.
+ * @NL80211_NAN_MATCH_FUNC_PEER: the peer function
+ * that caused the match. This is a nested attribute.
+ * See &enum nl80211_nan_func_attributes.
+ *
+ * @NUM_NL80211_NAN_MATCH_ATTR: internal
+ * @NL80211_NAN_MATCH_ATTR_MAX: highest NAN match attribute
+ */
+enum nl80211_nan_match_attributes {
+ __NL80211_NAN_MATCH_INVALID,
+ NL80211_NAN_MATCH_FUNC_LOCAL,
+ NL80211_NAN_MATCH_FUNC_PEER,
+
+ /* keep last */
+ NUM_NL80211_NAN_MATCH_ATTR,
+ NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d627527..4d37717 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -56,6 +56,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_REGULATORY,
NL80211_MCGRP_MLME,
NL80211_MCGRP_VENDOR,
+ NL80211_MCGRP_NAN,
NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
};

@@ -65,6 +66,7 @@ static const struct genl_multicast_group nl80211_mcgrps[] = {
[NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
+ [NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
#ifdef CONFIG_NL80211_TESTMODE
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
#endif
@@ -10867,6 +10869,82 @@ static int nl80211_nan_change_config(struct sk_buff *skb,
return rdev_nan_change_conf(rdev, wdev, &conf, changed);
}

+void cfg80211_nan_match(struct wireless_dev *wdev,
+ struct cfg80211_nan_match_params *match, gfp_t gfp)
+{
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct nlattr *match_attr, *local_func_attr, *peer_func_attr;
+ struct sk_buff *msg;
+ void *hdr;
+
+ if (WARN_ON(!match->inst_id || !match->peer_inst_id || !match->addr))
+ return;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_MATCH);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ wdev->netdev->ifindex)) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
+
+ if (nla_put_u64(msg, NL80211_ATTR_COOKIE, match->cookie) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, match->addr))
+ goto nla_put_failure;
+
+ match_attr = nla_nest_start(msg, NL80211_ATTR_NAN_MATCH);
+ if (!match_attr)
+ goto nla_put_failure;
+
+ local_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_LOCAL);
+ if (!local_func_attr)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->inst_id))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, local_func_attr);
+
+ peer_func_attr = nla_nest_start(msg, NL80211_NAN_MATCH_FUNC_PEER);
+ if (!peer_func_attr)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL80211_NAN_FUNC_TYPE, match->type) ||
+ nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, match->peer_inst_id))
+ goto nla_put_failure;
+
+ if (match->info && match->info_len &&
+ nla_put(msg, NL80211_NAN_FUNC_SERVICE_INFO, match->info_len,
+ match->info))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, peer_func_attr);
+ nla_nest_end(msg, match_attr);
+ genlmsg_end(msg, hdr);
+
+ if (!wdev->owner_nlportid)
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
+ msg, 0, NL80211_MCGRP_NAN, gfp);
+ else
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
+ wdev->owner_nlportid);
+
+ return;
+
+nla_put_failure:
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_nan_match);
+
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{
--
2.9.3

2016-09-18 19:56:27

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 6/9] cfg80211: Provide an API to report NAN function termination

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> Provide a function that reports NAN DE function termination. The function
> may be terminated due to one of the following reasons: user request,
> ttl expiration or failure.
> If the NAN instance is tied to the owner, the notification will be
> sent to the socket that started the NAN interface only

So the driver is supposed to use this function from the .rm_nan_func
callback (or .del_nan_func). How should the driver use this together
with cfg80211_free_nan_func() function.

> Signed-off-by: Andrei Otcheretianski <[email protected]>
> Signed-off-by: Emmanuel Grumbach <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>
> ---
> include/net/cfg80211.h | 16 ++++++++++++
> include/uapi/linux/nl80211.h | 15 ++++++++++++
> net/wireless/nl80211.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 89 insertions(+)
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index a08d7da..81770d6 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -5676,6 +5676,22 @@ struct cfg80211_nan_match_params {
> void cfg80211_nan_match(struct wireless_dev *wdev,
> struct cfg80211_nan_match_params *match, gfp_t gfp);
>
> +/**
> + * cfg80211_nan_func_terminated - notify about NAN function termination.
> + *
> + * @wdev: the wireless device reporting the match
> + * @inst_id: the local instance id
> + * @reason: termination reason (one of the NL80211_NAN_FUNC_TERM_REASON_*)
> + * @cookie: unique NAN function identifier
> + * @gfp: allocation flags
> + *
> + * This function reports that the a NAN function is terminated.
> + */
> +void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
> + u8 inst_id,
> + enum nl80211_nan_func_term_reason reason,
> + u64 cookie, gfp_t gfp);
> +
> /* ethtool helper */
> void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
>
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index badb4a6..fd86be6 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -4978,6 +4978,21 @@ enum nl80211_nan_publish_type {
> NL80211_NAN_UNSOLICITED_PUBLISH = 1 << 1,
> };
>
> +/**
> + * enum nl80211_nan_func_term_reason - NAN functions termination reason
> + *
> + * Defines termination reasons of a NAN function
> + *
> + * @NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST: requested by user
> + * @NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED: timeout
> + * @NL80211_NAN_FUNC_TERM_REASON_ERROR: errored
> + */
> +enum nl80211_nan_func_term_reason {
> + NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST,
> + NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED,
> + NL80211_NAN_FUNC_TERM_REASON_ERROR,
> +};
> +
> #define NL80211_NAN_FUNC_SERVICE_ID_LEN 6
> #define NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN 0xff
> #define NL80211_NAN_FUNC_SRF_MAX_LEN 0xff
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 4d37717..f817105 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -10945,6 +10945,64 @@ nla_put_failure:
> }
> EXPORT_SYMBOL(cfg80211_nan_match);
>
> +void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
> + u8 inst_id,
> + enum nl80211_nan_func_term_reason reason,
> + u64 cookie, gfp_t gfp)
> +{
> + struct wiphy *wiphy = wdev->wiphy;
> + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
> + struct sk_buff *msg;
> + struct nlattr *func_attr;
> + void *hdr;
> +
> + if (WARN_ON(!inst_id))
> + return;
> +
> + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
> + if (!msg)
> + return;
> +
> + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RM_NAN_FUNCTION);
> + if (!hdr) {
> + nlmsg_free(msg);
> + return;
> + }
> +
> + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
> + (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
> + wdev->netdev->ifindex)) ||
> + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
> + goto nla_put_failure;
> +
> + if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
> + goto nla_put_failure;
> +
> + func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);
> + if (!func_attr)
> + goto nla_put_failure;
> +
> + if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
> + nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
> + goto nla_put_failure;
> +
> + nla_nest_end(msg, func_attr);
> + genlmsg_end(msg, hdr);
> +
> + if (!wdev->owner_nlportid)
> + genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
> + msg, 0, NL80211_MCGRP_NAN, gfp);
> + else
> + genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
> + wdev->owner_nlportid);
> +
> + return;
> +
> +nla_put_failure:
> + nlmsg_free(msg);
> +}
> +EXPORT_SYMBOL(cfg80211_nan_func_terminated);
> +
> static int nl80211_get_protocol_features(struct sk_buff *skb,
> struct genl_info *info)
> {
>

2016-09-20 11:48:43

by Beker, Ayala

[permalink] [raw]
Subject: RE: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

-----Original Message-----
From: Arend Van Spriel [mailto:[email protected]]
Sent: Sunday, September 18, 2016 22:01
To: Otcheretianski, Andrei <[email protected]>; Luca Coelho <[email protected]>; [email protected]
Cc: [email protected]; Beker, Ayala <[email protected]>; Grumbach, Emmanuel <[email protected]>; Coelho, Luciano <[email protected]>
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

On 18-9-2016 9:59, Otcheretianski, Andrei wrote:
>> -----Original Message-----
>> From: Arend Van Spriel [mailto:[email protected]]
>> Sent: Friday, September 16, 2016 14:09
>> To: Luca Coelho <[email protected]>; [email protected]
>> Cc: [email protected]; Beker, Ayala
>> <[email protected]>; Otcheretianski, Andrei
>> <[email protected]>; Grumbach, Emmanuel
>> <[email protected]>; Coelho, Luciano
>> <[email protected]>
>> Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start
>> / stop NAN
>>
>> On 16-9-2016 10:33, Luca Coelho wrote:
>>> From: Ayala Beker <[email protected]>
>>>
>>> This code doesn't do much besides allowing to start and stop the vif.
>>>
>>> Signed-off-by: Andrei Otcheretianski
>>> <[email protected]>
>>> Signed-off-by: Emmanuel Grumbach <[email protected]>
>>> Signed-off-by: Ayala Beker <[email protected]>
>>> Signed-off-by: Luca Coelho <[email protected]>
>>> ---
>>> include/net/mac80211.h | 9 +++++++++
>>> net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
>>> net/mac80211/chan.c | 3 +++
>>> net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
>>> net/mac80211/iface.c | 8 ++++++--
>>> net/mac80211/main.c | 5 +++++
>>> net/mac80211/offchannel.c | 3 ++-
>>> net/mac80211/trace.h | 50
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>> net/mac80211/util.c | 3 ++-
>>> 9 files changed, 141 insertions(+), 5 deletions(-)
>>
>> [...]
>>
>>> diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
>>> index fe35a1c..67b42c8 100644
>>> --- a/net/mac80211/driver-ops.h
>>> +++ b/net/mac80211/driver-ops.h
>>> @@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct
>>> ieee80211_local *local,
>>>
>>> if (WARN_ON_ONCE(sdata->vif.type ==
>> NL80211_IFTYPE_P2P_DEVICE ||
>>> (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
>>> - !sdata->vif.mu_mimo_owner)))
>>> + !sdata->vif.mu_mimo_owner) ||
>>> + sdata->vif.type == NL80211_IFTYPE_NAN))
>>
>> Might be more clear to move this up right after P2P_DEVICE check.
>
> Why? It's a completely separate new condition - so it goes to the end.

> I would say readability. Both P2P_DEVICE and NAN checks are single comparisons as opposed to the MONITOR check.

>>
>>> return;
>>>
>>> if (!check_sdata_in_driver(sdata)) @@ -1165,4 +1166,30 @@ static
>>> inline void drv_wake_tx_queue(struct
>> ieee80211_local *local,
>>> local->ops->wake_tx_queue(&local->hw, &txq->txq); }
>>>
>>> +static inline int drv_start_nan(struct ieee80211_local *local,
>>> + struct ieee80211_sub_if_data *sdata,
>>> + struct cfg80211_nan_conf *conf) {
>>> + int ret;
>>> +
>>> + might_sleep();
>>> + check_sdata_in_driver(sdata);
>>> +
>>> + trace_drv_start_nan(local, sdata, conf);
>>> + ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
>>> + trace_drv_return_int(local, ret);
>>> + return ret;
>>> +}
>>> +
>>> +static inline void drv_stop_nan(struct ieee80211_local *local,
>>> + struct ieee80211_sub_if_data *sdata) {
>>> + might_sleep();
>>> + check_sdata_in_driver(sdata);
>>> +
>>> + trace_drv_stop_nan(local, sdata);
>>> + local->ops->stop_nan(&local->hw, &sdata->vif);
>>> + trace_drv_return_void(local);
>>> +}
>>> +
>>> #endif /* __MAC80211_DRIVER_OPS */
>>> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index
>>> e694ca2..507f46a 100644
>>> --- a/net/mac80211/iface.c
>>> +++ b/net/mac80211/iface.c
>>> @@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct
>> ieee80211_sub_if_data *sdata,
>>> int n_queues = sdata->local->hw.queues;
>>> int i;
>>>
>>> + if (iftype == NL80211_IFTYPE_NAN)
>>> + return 0;
>>> +
>>> if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
>>> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
>>> if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == @@
>> -647,7 +650,8 @@ int
>>> ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
>>> local->fif_probe_req++;
>>> }
>>>
>>> - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
>>> + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
>>> + sdata->vif.type != NL80211_IFTYPE_NAN)
>>
>> similar check keeps reoccuring in various places so maybe we can
>> create a helper function for it.
>
> Right, but not sure that it deserves a function.

> If similar new iftypes are anticipated it would make sense as it would mean adding it in one place.

I don't think there is something in common to those interface types that can fit such a function semantically, so I decided not to change it.
Do you have any idea?

> Regards,
> Arend

---------------------------------------------------------------------
A member of the Intel Corporation group of companies

This e-mail and any attachments may contain confidential material for
the sole use of the intended recipient(s). Any review or distribution
by others is strictly prohibited. If you are not the intended
recipient, please contact the sender and delete all copies.

2016-09-18 19:01:15

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

On 18-9-2016 9:59, Otcheretianski, Andrei wrote:
>> -----Original Message-----
>> From: Arend Van Spriel [mailto:[email protected]]
>> Sent: Friday, September 16, 2016 14:09
>> To: Luca Coelho <[email protected]>; [email protected]
>> Cc: [email protected]; Beker, Ayala <[email protected]>;
>> Otcheretianski, Andrei <[email protected]>; Grumbach,
>> Emmanuel <[email protected]>; Coelho, Luciano
>> <[email protected]>
>> Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop
>> NAN
>>
>> On 16-9-2016 10:33, Luca Coelho wrote:
>>> From: Ayala Beker <[email protected]>
>>>
>>> This code doesn't do much besides allowing to start and stop the vif.
>>>
>>> Signed-off-by: Andrei Otcheretianski <[email protected]>
>>> Signed-off-by: Emmanuel Grumbach <[email protected]>
>>> Signed-off-by: Ayala Beker <[email protected]>
>>> Signed-off-by: Luca Coelho <[email protected]>
>>> ---
>>> include/net/mac80211.h | 9 +++++++++
>>> net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
>>> net/mac80211/chan.c | 3 +++
>>> net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
>>> net/mac80211/iface.c | 8 ++++++--
>>> net/mac80211/main.c | 5 +++++
>>> net/mac80211/offchannel.c | 3 ++-
>>> net/mac80211/trace.h | 50
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>> net/mac80211/util.c | 3 ++-
>>> 9 files changed, 141 insertions(+), 5 deletions(-)
>>
>> [...]
>>
>>> diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
>>> index fe35a1c..67b42c8 100644
>>> --- a/net/mac80211/driver-ops.h
>>> +++ b/net/mac80211/driver-ops.h
>>> @@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct
>>> ieee80211_local *local,
>>>
>>> if (WARN_ON_ONCE(sdata->vif.type ==
>> NL80211_IFTYPE_P2P_DEVICE ||
>>> (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
>>> - !sdata->vif.mu_mimo_owner)))
>>> + !sdata->vif.mu_mimo_owner) ||
>>> + sdata->vif.type == NL80211_IFTYPE_NAN))
>>
>> Might be more clear to move this up right after P2P_DEVICE check.
>
> Why? It's a completely separate new condition - so it goes to the end.

I would say readability. Both P2P_DEVICE and NAN checks are single
comparisons as opposed to the MONITOR check.

>>
>>> return;
>>>
>>> if (!check_sdata_in_driver(sdata))
>>> @@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct
>> ieee80211_local *local,
>>> local->ops->wake_tx_queue(&local->hw, &txq->txq); }
>>>
>>> +static inline int drv_start_nan(struct ieee80211_local *local,
>>> + struct ieee80211_sub_if_data *sdata,
>>> + struct cfg80211_nan_conf *conf)
>>> +{
>>> + int ret;
>>> +
>>> + might_sleep();
>>> + check_sdata_in_driver(sdata);
>>> +
>>> + trace_drv_start_nan(local, sdata, conf);
>>> + ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
>>> + trace_drv_return_int(local, ret);
>>> + return ret;
>>> +}
>>> +
>>> +static inline void drv_stop_nan(struct ieee80211_local *local,
>>> + struct ieee80211_sub_if_data *sdata) {
>>> + might_sleep();
>>> + check_sdata_in_driver(sdata);
>>> +
>>> + trace_drv_stop_nan(local, sdata);
>>> + local->ops->stop_nan(&local->hw, &sdata->vif);
>>> + trace_drv_return_void(local);
>>> +}
>>> +
>>> #endif /* __MAC80211_DRIVER_OPS */
>>> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index
>>> e694ca2..507f46a 100644
>>> --- a/net/mac80211/iface.c
>>> +++ b/net/mac80211/iface.c
>>> @@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct
>> ieee80211_sub_if_data *sdata,
>>> int n_queues = sdata->local->hw.queues;
>>> int i;
>>>
>>> + if (iftype == NL80211_IFTYPE_NAN)
>>> + return 0;
>>> +
>>> if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
>>> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
>>> if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == @@
>> -647,7 +650,8 @@ int
>>> ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
>>> local->fif_probe_req++;
>>> }
>>>
>>> - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
>>> + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
>>> + sdata->vif.type != NL80211_IFTYPE_NAN)
>>
>> similar check keeps reoccuring in various places so maybe we can create a
>> helper function for it.
>
> Right, but not sure that it deserves a function.

If similar new iftypes are anticipated it would make sense as it would
mean adding it in one place.

Regards,
Arend

2016-09-16 08:33:38

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 4/9] cfg80211: allow the user space to change current NAN configuration

From: Ayala Beker <[email protected]>

Some NAN configuration paramaters may change during the operation of
the NaN device. For example, a user may want to update master preference
value when the device gets plugged/unplugged to the power.
Add API that allows to do so.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 19 +++++++++++++++++++
include/uapi/linux/nl80211.h | 11 +++++++++--
net/wireless/nl80211.c | 45 ++++++++++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 17 +++++++++++++++++
net/wireless/trace.h | 24 +++++++++++++++++++++++
5 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ced5b8a..b819e32 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2306,6 +2306,18 @@ struct cfg80211_nan_conf {
};

/**
+ * enum cfg80211_nan_conf_changes - indicates changed fields in NAN
+ * configuration
+ *
+ * @CFG80211_NAN_CONF_CHANGED_PREF: master preference
+ * @CFG80211_NAN_CONF_CHANGED_DUAL: dual band operation
+ */
+enum cfg80211_nan_conf_changes {
+ CFG80211_NAN_CONF_CHANGED_PREF = BIT(0),
+ CFG80211_NAN_CONF_CHANGED_DUAL = BIT(1),
+};
+
+/**
* struct cfg80211_nan_func_filter - a NAN function Rx / Tx filter
*
* @filter: the content of the filter
@@ -2670,6 +2682,9 @@ struct cfg80211_nan_func {
* On success the driver should assign an instance_id in the
* provided @nan_func.
* @rm_nan_func: Remove a NAN function.
+ * @nan_change_conf: changes NAN configuration. The changed parameters must
+ * be specified in @changes (using &enum cfg80211_nan_conf_changes);
+ * All other parameters must be ignored.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2942,6 +2957,10 @@ struct cfg80211_ops {
struct cfg80211_nan_func *nan_func);
void (*rm_nan_func)(struct wiphy *wiphy, struct wireless_dev *wdev,
u64 cookie);
+ int (*nan_change_conf)(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf,
+ u32 changes);
};

/*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ab16c8e..9cf1744 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -865,6 +865,10 @@
* This command is also used as a notification sent when a NAN function is
* terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
* and %NL80211_ATTR_COOKIE attributes.
+ * @NL80211_CMD_CHANGE_NAN_CONFIG: Change current NAN configuration. NAN
+ * must be operational (%NL80211_CMD_START_NAN was executed).
+ * It must contain at least one of the following attributes:
+ * %NL80211_ATTR_NAN_MASTER_PREF, %NL80211_ATTR_NAN_DUAL.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -1058,6 +1062,7 @@ enum nl80211_commands {
NL80211_CMD_STOP_NAN,
NL80211_CMD_ADD_NAN_FUNCTION,
NL80211_CMD_RM_NAN_FUNCTION,
+ NL80211_CMD_CHANGE_NAN_CONFIG,

/* add new commands above here */

@@ -1907,12 +1912,14 @@ enum nl80211_commands {
* used to pull the stored data for mesh peer in power save state.
*
* @NL80211_ATTR_NAN_MASTER_PREF: the master preference to be used by
- * %NL80211_CMD_START_NAN. Its type is u8 and it can't be 0.
+ * %NL80211_CMD_START_NAN and optionally with
+ * %NL80211_CMD_CHANGE_NAN_CONFIG. Its type is u8 and it can't be 0.
* Also, values 1 and 255 are reserved for certification purposes and
* should not be used during a normal device operation.
* @NL80211_ATTR_NAN_DUAL: NAN dual band operation config (see
* &enum nl80211_nan_dual_band_conf). This attribute is used with
- * %NL80211_CMD_START_NAN.
+ * %NL80211_CMD_START_NAN and optionally with
+ * %NL80211_CMD_CHANGE_NAN_CONFIG.
* @NL80211_ATTR_NAN_FUNC: a function that can be added to NAN. See
* &enum nl80211_nan_func_attributes for description of this nested
* attribute.
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 58b3127..d627527 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10830,6 +10830,43 @@ static int nl80211_nan_rm_func(struct sk_buff *skb,
return 0;
}

+static int nl80211_nan_change_config(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ struct cfg80211_nan_conf conf = {};
+ u32 changed = 0;
+
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (!wdev->nan_started)
+ return -ENOTCONN;
+
+ if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
+ conf.master_pref =
+ nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
+ if (conf.master_pref <= 1 || conf.master_pref == 255)
+ return -EINVAL;
+
+ changed |= CFG80211_NAN_CONF_CHANGED_PREF;
+ }
+
+ if (info->attrs[NL80211_ATTR_NAN_DUAL]) {
+ conf.dual = nla_get_u8(info->attrs[NL80211_ATTR_NAN_DUAL]);
+ if (conf.dual > NL80211_NAN_BAND_MAX)
+ return -EINVAL;
+
+ changed |= CFG80211_NAN_CONF_CHANGED_DUAL;
+ }
+
+ if (!changed)
+ return -EINVAL;
+
+ return rdev_nan_change_conf(rdev, wdev, &conf, changed);
+}
+
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{
@@ -12204,6 +12241,14 @@ static const struct genl_ops nl80211_ops[] = {
NL80211_FLAG_NEED_RTNL,
},
{
+ .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
+ .doit = nl80211_nan_change_config,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
.cmd = NL80211_CMD_SET_MCAST_RATE,
.doit = nl80211_set_mcast_rate,
.policy = nl80211_policy,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index f42acf4..8b4b9fd 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -928,6 +928,23 @@ static inline void rdev_rm_nan_func(struct cfg80211_registered_device *rdev,
trace_rdev_return_void(&rdev->wiphy);
}

+static inline int
+rdev_nan_change_conf(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf, u32 changes)
+{
+ int ret;
+
+ trace_rdev_nan_change_conf(&rdev->wiphy, wdev, conf, changes);
+ if (rdev->ops->nan_change_conf)
+ ret = rdev->ops->nan_change_conf(&rdev->wiphy, wdev, conf,
+ changes);
+ else
+ ret = -ENOTSUPP;
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_acl_data *params)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 4845fe4..477b7e9 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1911,6 +1911,30 @@ TRACE_EVENT(rdev_start_nan,
__entry->dual)
);

+TRACE_EVENT(rdev_nan_change_conf,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_nan_conf *conf, u32 changes),
+ TP_ARGS(wiphy, wdev, conf, changes),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u8, master_pref)
+ __field(u8, dual);
+ __field(u32, changes);
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->master_pref = conf->master_pref;
+ __entry->dual = conf->dual;
+ __entry->changes = changes;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT
+ ", master preference: %u, dual: %d, changes: %x",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->master_pref,
+ __entry->dual, __entry->changes)
+);
+
DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_nan,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
TP_ARGS(wiphy, wdev)
--
2.9.3

2016-09-20 12:30:02

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

On 20-9-2016 13:45, Beker, Ayala wrote:
> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 22:01
> To: Otcheretianski, Andrei <[email protected]>; Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>; Grumbach, Emmanuel <[email protected]>; Coelho, Luciano <[email protected]>
> Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN
>
> On 18-9-2016 9:59, Otcheretianski, Andrei wrote:
>>> -----Original Message-----
>>> From: Arend Van Spriel [mailto:[email protected]]
>>> Sent: Friday, September 16, 2016 14:09
>>> To: Luca Coelho <[email protected]>; [email protected]
>>> Cc: [email protected]; Beker, Ayala
>>> <[email protected]>; Otcheretianski, Andrei
>>> <[email protected]>; Grumbach, Emmanuel
>>> <[email protected]>; Coelho, Luciano
>>> <[email protected]>
>>> Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start
>>> / stop NAN
>>>
>>> On 16-9-2016 10:33, Luca Coelho wrote:
>>>> From: Ayala Beker <[email protected]>
>>>>
>>>> This code doesn't do much besides allowing to start and stop the vif.
>>>>
>>>> Signed-off-by: Andrei Otcheretianski
>>>> <[email protected]>
>>>> Signed-off-by: Emmanuel Grumbach <[email protected]>
>>>> Signed-off-by: Ayala Beker <[email protected]>
>>>> Signed-off-by: Luca Coelho <[email protected]>
>>>> ---
>>>> include/net/mac80211.h | 9 +++++++++
>>>> net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
>>>> net/mac80211/chan.c | 3 +++
>>>> net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
>>>> net/mac80211/iface.c | 8 ++++++--
>>>> net/mac80211/main.c | 5 +++++
>>>> net/mac80211/offchannel.c | 3 ++-
>>>> net/mac80211/trace.h | 50
>>> +++++++++++++++++++++++++++++++++++++++++++++++
>>>> net/mac80211/util.c | 3 ++-
>>>> 9 files changed, 141 insertions(+), 5 deletions(-)
>>>
>>> [...]
>>>
>>>> diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
>>>> index fe35a1c..67b42c8 100644
>>>> --- a/net/mac80211/driver-ops.h
>>>> +++ b/net/mac80211/driver-ops.h
>>>> @@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct
>>>> ieee80211_local *local,
>>>>
>>>> if (WARN_ON_ONCE(sdata->vif.type ==
>>> NL80211_IFTYPE_P2P_DEVICE ||
>>>> (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
>>>> - !sdata->vif.mu_mimo_owner)))
>>>> + !sdata->vif.mu_mimo_owner) ||
>>>> + sdata->vif.type == NL80211_IFTYPE_NAN))
>>>
>>> Might be more clear to move this up right after P2P_DEVICE check.
>>
>> Why? It's a completely separate new condition - so it goes to the end.
>
>> I would say readability. Both P2P_DEVICE and NAN checks are single comparisons as opposed to the MONITOR check.
>
>>>
>>>> return;
>>>>
>>>> if (!check_sdata_in_driver(sdata)) @@ -1165,4 +1166,30 @@ static
>>>> inline void drv_wake_tx_queue(struct
>>> ieee80211_local *local,
>>>> local->ops->wake_tx_queue(&local->hw, &txq->txq); }
>>>>
>>>> +static inline int drv_start_nan(struct ieee80211_local *local,
>>>> + struct ieee80211_sub_if_data *sdata,
>>>> + struct cfg80211_nan_conf *conf) {
>>>> + int ret;
>>>> +
>>>> + might_sleep();
>>>> + check_sdata_in_driver(sdata);
>>>> +
>>>> + trace_drv_start_nan(local, sdata, conf);
>>>> + ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
>>>> + trace_drv_return_int(local, ret);
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static inline void drv_stop_nan(struct ieee80211_local *local,
>>>> + struct ieee80211_sub_if_data *sdata) {
>>>> + might_sleep();
>>>> + check_sdata_in_driver(sdata);
>>>> +
>>>> + trace_drv_stop_nan(local, sdata);
>>>> + local->ops->stop_nan(&local->hw, &sdata->vif);
>>>> + trace_drv_return_void(local);
>>>> +}
>>>> +
>>>> #endif /* __MAC80211_DRIVER_OPS */
>>>> diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index
>>>> e694ca2..507f46a 100644
>>>> --- a/net/mac80211/iface.c
>>>> +++ b/net/mac80211/iface.c
>>>> @@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct
>>> ieee80211_sub_if_data *sdata,
>>>> int n_queues = sdata->local->hw.queues;
>>>> int i;
>>>>
>>>> + if (iftype == NL80211_IFTYPE_NAN)
>>>> + return 0;
>>>> +
>>>> if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
>>>> for (i = 0; i < IEEE80211_NUM_ACS; i++) {
>>>> if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == @@
>>> -647,7 +650,8 @@ int
>>>> ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
>>>> local->fif_probe_req++;
>>>> }
>>>>
>>>> - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
>>>> + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
>>>> + sdata->vif.type != NL80211_IFTYPE_NAN)
>>>
>>> similar check keeps reoccuring in various places so maybe we can
>>> create a helper function for it.
>>
>> Right, but not sure that it deserves a function.
>
>> If similar new iftypes are anticipated it would make sense as it would mean adding it in one place.
>
> I don't think there is something in common to those interface types that can fit such a function semantically, so I decided not to change it.
> Do you have any idea?

What is common is that these are both non-netdev interface types.

>> Regards,
>> Arend
>
> ---------------------------------------------------------------------
> A member of the Intel Corporation group of companies
>
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.

Maybe better to avoid such disclaimers when you are posting on community
mailing lists.

Regards,
Arend

2016-09-18 20:00:24

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 6/9] cfg80211: Provide an API to report NAN function termination

On 18-9-2016 21:56, Arend Van Spriel wrote:
> On 16-9-2016 10:33, Luca Coelho wrote:
>> From: Ayala Beker <[email protected]>
>>
>> Provide a function that reports NAN DE function termination. The function
>> may be terminated due to one of the following reasons: user request,
>> ttl expiration or failure.
>> If the NAN instance is tied to the owner, the notification will be
>> sent to the socket that started the NAN interface only
>
> So the driver is supposed to use this function from the .rm_nan_func
> callback (or .del_nan_func). How should the driver use this together
> with cfg80211_free_nan_func() function.

Hit Send button too fast. Would it make sense to free the nan func
implicitly in cfg80211_nan_func_terminated() function or would there be
reasons to keep it.

Regards,
Arend

2016-09-16 09:00:53

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 0/9] Add support for Neighbor Awareness Networking

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Luca Coelho <[email protected]>
>
> Hi,
>
> This is v2 of the NAN patches that Emmanuel sent a while back[1]. In
> this version, we squashed some patches and took care of some comments
> after reviews (both internal and public).

Hi Luca,

You may have missed some as I think this should be v4.

Regards,
Arend

[1]
http://mid.gmane.org/[email protected]

> NAN was described in the original post[2].
>
> I hope they're good for merging now, because I'm tired of carrying
> this changes forward in our internal trees. :P
>
> Nevertheless, comments are welcome, as always.
>
> [1] http://mid.gmane.org/[email protected]
> [2] http://mid.gmane.org/[email protected]
>
> Cheers,
> Luca.
>
>
> Ayala Beker (9):
> cfg80211: add start / stop NAN commands
> mac80211: add boilerplate code for start / stop NAN
> cfg80211: add add_nan_func / rm_nan_func
> cfg80211: allow the user space to change current NAN configuration
> cfg80211: provide a function to report a match for NAN
> cfg80211: Provide an API to report NAN function termination
> mac80211: implement nan_change_conf
> mac80211: Implement add_nan_func and rm_nan_func
> mac80211: Add API to report NAN function match
>
> include/net/cfg80211.h | 184 ++++++++++++-
> include/net/mac80211.h | 65 +++++
> include/uapi/linux/nl80211.h | 258 +++++++++++++++++
> net/mac80211/cfg.c | 208 ++++++++++++++
> net/mac80211/chan.c | 6 +
> net/mac80211/driver-ops.h | 82 +++++-
> net/mac80211/ieee80211_i.h | 17 ++
> net/mac80211/iface.c | 28 +-
> net/mac80211/main.c | 8 +
> net/mac80211/offchannel.c | 4 +-
> net/mac80211/rx.c | 3 +
> net/mac80211/trace.h | 133 +++++++++
> net/mac80211/util.c | 50 +++-
> net/wireless/chan.c | 2 +
> net/wireless/core.c | 35 +++
> net/wireless/core.h | 3 +
> net/wireless/mlme.c | 1 +
> net/wireless/nl80211.c | 642 ++++++++++++++++++++++++++++++++++++++++++-
> net/wireless/rdev-ops.h | 58 ++++
> net/wireless/trace.h | 90 ++++++
> net/wireless/util.c | 28 +-
> 21 files changed, 1894 insertions(+), 11 deletions(-)
>

2016-09-16 12:21:29

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

Hi Ayala,

[auto build test WARNING on mac80211-next/master]
[also build test WARNING on next-20160916]
[cannot apply to v4.8-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url: https://github.com/0day-ci/linux/commits/Luca-Coelho/Add-support-for-Neighbor-Awareness-Networking/20160916-164553
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
config: x86_64-randconfig-v0-09161926 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All warnings (new ones prefixed by >>):

In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/uapi/linux/if.h:23,
from net/wireless/nl80211.c:9:
net/wireless/nl80211.c: In function 'nl80211_nan_add_func':
net/wireless/nl80211.c:10588:30: error: implicit declaration of function 'genl_info_snd_portid' [-Werror=implicit-function-declaration]
wdev->owner_nlportid != genl_info_snd_portid(info))
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
>> net/wireless/nl80211.c:10587:2: note: in expansion of macro 'if'
if (wdev->owner_nlportid &&
^~
net/wireless/nl80211.c:10785:6: error: implicit declaration of function 'nla_put_u64' [-Werror=implicit-function-declaration]
if (nla_put_u64(msg, NL80211_ATTR_COOKIE, func->cookie))
^
include/linux/compiler.h:149:30: note: in definition of macro '__trace_if'
if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
^~~~
net/wireless/nl80211.c:10785:2: note: in expansion of macro 'if'
if (nla_put_u64(msg, NL80211_ATTR_COOKIE, func->cookie))
^~
cc1: some warnings being treated as errors

vim +/if +10587 net/wireless/nl80211.c

10571 struct wireless_dev *wdev = info->user_ptr[1];
10572 struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
10573 struct cfg80211_nan_func *func;
10574 struct sk_buff *msg = NULL;
10575 void *hdr = NULL;
10576 int err = 0;
10577
10578 if (wdev->iftype != NL80211_IFTYPE_NAN)
10579 return -EOPNOTSUPP;
10580
10581 if (!wdev->nan_started)
10582 return -ENOTCONN;
10583
10584 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
10585 return -EINVAL;
10586
10587 if (wdev->owner_nlportid &&
10588 wdev->owner_nlportid != genl_info_snd_portid(info))
10589 return -ENOTCONN;
10590
10591 err = nla_parse(tb, NL80211_NAN_FUNC_ATTR_MAX,
10592 nla_data(info->attrs[NL80211_ATTR_NAN_FUNC]),
10593 nla_len(info->attrs[NL80211_ATTR_NAN_FUNC]),
10594 nl80211_nan_func_policy);
10595 if (err)

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (3.40 kB)
.config.gz (22.23 kB)
Download all attachments

2016-09-18 07:44:56

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 1/9] cfg80211: add start / stop NAN commands

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Friday, September 16, 2016 13:59
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands
>
> On 16-9-2016 10:33, Luca Coelho wrote:
> > From: Ayala Beker <[email protected]>
> >
> > This allows user space to start/stop NAN interface.
> > A NAN interface is like P2P device in a few aspects: it doesn't have a
> > netdev associated to it.
> > Add the new interface type and prevent operations that can't be
> > executed on NAN interface like scan.
> >
> > Define several attributes that may be configured by user space when
> > starting NAN functionality (master preference and dual band operation)
> >
> > Signed-off-by: Andrei Otcheretianski <[email protected]>
> > Signed-off-by: Emmanuel Grumbach <[email protected]>
> > Signed-off-by: Luca Coelho <[email protected]>
> > ---
> > include/net/cfg80211.h | 21 +++++++++-
> > include/uapi/linux/nl80211.h | 52 +++++++++++++++++++++++++
> > net/mac80211/cfg.c | 2 +
> > net/mac80211/chan.c | 3 ++
> > net/mac80211/iface.c | 4 ++
> > net/mac80211/offchannel.c | 1 +
> > net/mac80211/rx.c | 3 ++
> > net/mac80211/util.c | 1 +
> > net/wireless/chan.c | 2 +
> > net/wireless/core.c | 34 ++++++++++++++++
> > net/wireless/core.h | 3 ++
> > net/wireless/mlme.c | 1 +
> > net/wireless/nl80211.c | 93
> ++++++++++++++++++++++++++++++++++++++++++--
> > net/wireless/rdev-ops.h | 20 ++++++++++
> > net/wireless/trace.h | 27 +++++++++++++
> > net/wireless/util.c | 6 ++-
> > 16 files changed, 267 insertions(+), 6 deletions(-)
> >
> > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index
> > d5e7f69..ca64d69 100644
> > --- a/include/net/cfg80211.h
> > +++ b/include/net/cfg80211.h
> > @@ -2293,6 +2293,19 @@ struct cfg80211_qos_map { };
>
> [...]
>
> > +/**
> > + * enum nl80211_nan_dual_band_conf - NAN dual band configuration
> > + *
> > + * Defines the NAN dual band mode of operation
>
> Does it make sense to have such a notion of bands in use. And what does
> 5.2GHz mean. Is this a subband within 5G channels? Probably I should read
> the NAN spec to understand what is meant here. I would consider 5.2G as
> lower 5G, ie. discovery on channel 44 but not sure if that is meant here.
>

The NAN spec defines single and dual band modes of operation. The channels are fixed for each band.
On 2.4Ghz is channel 6 and 5GHz is either 44 or 149. Regarding 5.2 - it's just a typo. It should be 5G - no deeper meaning.

> > + * @NL80211_NAN_BAND_DEFAULT: device default mode
> > + * @NL80211_NAN_BAND_SINGLE: 2.4GHz only mode
> > + * @NL80211_NAN_BAND_DUAL: 2.4GHz and 5.2GHz mode
> > + */
> > +enum nl80211_nan_dual_band_conf {
> > + NL80211_NAN_BAND_DEFAULT,
> > + NL80211_NAN_BAND_SINGLE,
> > + NL80211_NAN_BAND_DUAL,
> > +
> > + /* keep last */
> > + __NL80211_NAN_BAND_AFTER_LAST,
> > + NL80211_NAN_BAND_MAX =
> > + __NL80211_NAN_BAND_AFTER_LAST - 1,
> > +};
> > +
> > #endif /* __LINUX_NL80211_H */
> > diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index
> > e29ff57..a74027f 100644
> > --- a/net/mac80211/cfg.c
> > +++ b/net/mac80211/cfg.c
> > @@ -257,6 +257,7 @@ static int ieee80211_add_key(struct wiphy *wiphy,
> struct net_device *dev,
> > case NL80211_IFTYPE_WDS:
> > case NL80211_IFTYPE_MONITOR:
> > case NL80211_IFTYPE_P2P_DEVICE:
> > + case NL80211_IFTYPE_NAN:
> > case NL80211_IFTYPE_UNSPECIFIED:
> > case NUM_NL80211_IFTYPES:
>
> Huh? What is this doing here? Not yours but weird still.
>
> > case NL80211_IFTYPE_P2P_CLIENT:
> > @@ -2036,6 +2037,7 @@ static int ieee80211_scan(struct wiphy *wiphy,
> > !(req->flags & NL80211_SCAN_FLAG_AP)))
> > return -EOPNOTSUPP;
> > break;
> > + case NL80211_IFTYPE_NAN:
> > default:
> > return -EOPNOTSUPP;
> > }
> > diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index
> > 74142d0..acb50f8 100644
> > --- a/net/mac80211/chan.c
> > +++ b/net/mac80211/chan.c
> > @@ -274,6 +274,7 @@ ieee80211_get_chanctx_max_required_bw(struct
> ieee80211_local *local,
> > ieee80211_get_max_required_bw(sdata));
> > break;
> > case NL80211_IFTYPE_P2P_DEVICE:
> > + case NL80211_IFTYPE_NAN:
> > continue;
> > case NL80211_IFTYPE_ADHOC:
> > case NL80211_IFTYPE_WDS:
> > @@ -718,6 +719,7 @@ void ieee80211_recalc_smps_chanctx(struct
> > ieee80211_local *local,
> >
> > switch (sdata->vif.type) {
> > case NL80211_IFTYPE_P2P_DEVICE:
> > + case NL80211_IFTYPE_NAN:
> > continue;
> > case NL80211_IFTYPE_STATION:
> > if (!sdata->u.mgd.associated)
> > @@ -981,6 +983,7 @@
> ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data
> *sdata)
> > case NL80211_IFTYPE_P2P_GO:
> > case NL80211_IFTYPE_P2P_DEVICE:
> > case NUM_NL80211_IFTYPES:
>
> I think NUM_NL80211_IFTYPES should not be in the switch. If it must I would
> leave it as last one here.

Agree that it should go last

>
> > + case NL80211_IFTYPE_NAN:
> > WARN_ON(1);
> > break;
> > }
>
> Regards,
> Arend

2016-09-16 10:46:50

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

Hi Ayala,

[auto build test ERROR on mac80211-next/master]
[also build test ERROR on next-20160916]
[cannot apply to v4.8-rc6]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url: https://github.com/0day-ci/linux/commits/Luca-Coelho/Add-support-for-Neighbor-Awareness-Networking/20160916-164553
base: https://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git master
config: x86_64-lkp (attached as .config)
compiler: gcc-6 (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All errors (new ones prefixed by >>):

net/wireless/nl80211.c: In function 'nl80211_nan_add_func':
>> net/wireless/nl80211.c:10588:30: error: implicit declaration of function 'genl_info_snd_portid' [-Werror=implicit-function-declaration]
wdev->owner_nlportid != genl_info_snd_portid(info))
^~~~~~~~~~~~~~~~~~~~
>> net/wireless/nl80211.c:10785:6: error: implicit declaration of function 'nla_put_u64' [-Werror=implicit-function-declaration]
if (nla_put_u64(msg, NL80211_ATTR_COOKIE, func->cookie))
^~~~~~~~~~~
cc1: some warnings being treated as errors

vim +/genl_info_snd_portid +10588 net/wireless/nl80211.c

10582 return -ENOTCONN;
10583
10584 if (!info->attrs[NL80211_ATTR_NAN_FUNC])
10585 return -EINVAL;
10586
10587 if (wdev->owner_nlportid &&
10588 wdev->owner_nlportid != genl_info_snd_portid(info))
10589 return -ENOTCONN;
10590
10591 err = nla_parse(tb, NL80211_NAN_FUNC_ATTR_MAX,
10592 nla_data(info->attrs[NL80211_ATTR_NAN_FUNC]),
10593 nla_len(info->attrs[NL80211_ATTR_NAN_FUNC]),
10594 nl80211_nan_func_policy);
10595 if (err)
10596 return err;
10597
10598 func = kzalloc(sizeof(*func), GFP_KERNEL);
10599 if (!func)
10600 return -ENOMEM;
10601
10602 func->cookie = wdev->wiphy->cookie_counter++;
10603
10604 if (!tb[NL80211_NAN_FUNC_TYPE] ||
10605 nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {
10606 err = -EINVAL;
10607 goto out;
10608 }
10609
10610
10611 func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
10612
10613 if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
10614 err = -EINVAL;
10615 goto out;
10616 }
10617
10618 memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
10619 sizeof(func->service_id));
10620
10621 func->close_range =
10622 nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
10623
10624 if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
10625 func->serv_spec_info_len =
10626 nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
10627 func->serv_spec_info =
10628 kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
10629 func->serv_spec_info_len,
10630 GFP_KERNEL);
10631 if (!func->serv_spec_info) {
10632 err = -ENOMEM;
10633 goto out;
10634 }
10635 }
10636
10637 if (tb[NL80211_NAN_FUNC_TTL])
10638 func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
10639
10640 switch (func->type) {
10641 case NL80211_NAN_FUNC_PUBLISH:
10642 if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
10643 err = -EINVAL;
10644 goto out;
10645 }
10646
10647 func->publish_type =
10648 nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
10649 func->publish_bcast =
10650 nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
10651
10652 if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
10653 func->publish_bcast) {
10654 err = -EINVAL;
10655 goto out;
10656 }
10657 break;
10658 case NL80211_NAN_FUNC_SUBSCRIBE:
10659 func->subscribe_active =
10660 nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
10661 break;
10662 case NL80211_NAN_FUNC_FOLLOW_UP:
10663 if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
10664 !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]) {
10665 err = -EINVAL;
10666 goto out;
10667 }
10668
10669 func->followup_id =
10670 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
10671 func->followup_reqid =
10672 nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
10673 memcpy(func->followup_dest.addr,
10674 nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
10675 sizeof(func->followup_dest.addr));
10676 if (func->ttl) {
10677 err = -EINVAL;
10678 goto out;
10679 }
10680 break;
10681 default:
10682 err = -EINVAL;
10683 goto out;
10684 }
10685
10686 if (tb[NL80211_NAN_FUNC_SRF]) {
10687 struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
10688
10689 err = nla_parse(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
10690 nla_data(tb[NL80211_NAN_FUNC_SRF]),
10691 nla_len(tb[NL80211_NAN_FUNC_SRF]), NULL);
10692 if (err)
10693 goto out;
10694
10695 func->srf_include =
10696 nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
10697
10698 if (srf_tb[NL80211_NAN_SRF_BF]) {
10699 if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
10700 !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
10701 err = -EINVAL;
10702 goto out;
10703 }
10704
10705 func->srf_bf_len =
10706 nla_len(srf_tb[NL80211_NAN_SRF_BF]);
10707 func->srf_bf =
10708 kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
10709 func->srf_bf_len, GFP_KERNEL);
10710 if (!func->srf_bf) {
10711 err = -ENOMEM;
10712 goto out;
10713 }
10714
10715 func->srf_bf_idx =
10716 nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
10717 } else {
10718 struct nlattr *attr, *mac_attr =
10719 srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
10720 int n_entries, rem, i = 0;
10721
10722 if (!mac_attr) {
10723 err = -EINVAL;
10724 goto out;
10725 }
10726
10727 n_entries = validate_acl_mac_addrs(mac_attr);
10728 if (n_entries <= 0) {
10729 err = -EINVAL;
10730 goto out;
10731 }
10732
10733 func->srf_num_macs = n_entries;
10734 func->srf_macs =
10735 kzalloc(sizeof(*func->srf_macs) * n_entries,
10736 GFP_KERNEL);
10737 if (!func->srf_macs) {
10738 err = -ENOMEM;
10739 goto out;
10740 }
10741
10742 nla_for_each_nested(attr, mac_attr, rem)
10743 memcpy(func->srf_macs[i++].addr, nla_data(attr),
10744 sizeof(*func->srf_macs));
10745 }
10746 }
10747
10748 if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
10749 err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
10750 func, true);
10751 if (err)
10752 goto out;
10753 }
10754
10755 if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
10756 err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
10757 func, false);
10758 if (err)
10759 goto out;
10760 }
10761
10762 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10763 if (!msg) {
10764 err = -ENOMEM;
10765 goto out;
10766 }
10767
10768 hdr = nl80211hdr_put(msg, genl_info_snd_portid(info), info->snd_seq, 0,
10769 NL80211_CMD_ADD_NAN_FUNCTION);
10770 /* This can't really happen - we just allocated 4KB */
10771 if (WARN_ON(!hdr)) {
10772 err = -ENOMEM;
10773 goto out;
10774 }
10775
10776 err = rdev_add_nan_func(rdev, wdev, func);
10777 out:
10778 if (err < 0) {
10779 cfg80211_free_nan_func(func);
10780 nlmsg_free(msg);
10781 return err;
10782 }
10783
10784 /* propagate the instance id and cookie to userspace */
10785 if (nla_put_u64(msg, NL80211_ATTR_COOKIE, func->cookie))
10786 goto nla_put_failure;
10787
10788 func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (7.78 kB)
.config.gz (23.17 kB)
Download all attachments

2016-09-16 10:26:47

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH v2 0/9] Add support for Neighbor Awareness Networking

On Fri, 2016-09-16 at 11:00 +0200, Arend Van Spriel wrote:
> On 16-9-2016 10:33, Luca Coelho wrote:
> >
> > From: Luca Coelho <[email protected]>
> >
> > Hi,
> >
> > This is v2 of the NAN patches that Emmanuel sent a while
> > back[1].  In
> > this version, we squashed some patches and took care of some
> > comments
> > after reviews (both internal and public).
>
> Hi Luca,
>
> You may have missed some as I think this should be v4.

Right... I saw those other ones, but they didn't have a cover-letter,
this series is sort of the v2 of "Add support for Neighbor Awareness
Networking".  Or something... :)

In any case, this new series should include all the changes done on the
way.

--
Luca.

2016-09-19 08:54:31

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 6/9] cfg80211: Provide an API to report NAN function termination

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 23:00
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 6/9] cfg80211: Provide an API to report NAN function
> termination
>
> On 18-9-2016 21:56, Arend Van Spriel wrote:
> > On 16-9-2016 10:33, Luca Coelho wrote:
> >> From: Ayala Beker <[email protected]>
> >>
> >> Provide a function that reports NAN DE function termination. The
> >> function may be terminated due to one of the following reasons: user
> >> request, ttl expiration or failure.
> >> If the NAN instance is tied to the owner, the notification will be
> >> sent to the socket that started the NAN interface only
> >
> > So the driver is supposed to use this function from the .rm_nan_func
> > callback (or .del_nan_func). How should the driver use this together
> > with cfg80211_free_nan_func() function.
>
> Hit Send button too fast. Would it make sense to free the nan func implicitly
> in cfg80211_nan_func_terminated() function or would there be reasons to
> keep it.

Currently when the NAN interface is stopped (ieee80211_do_stop) the termination notification can't be sent, since ieee80211_vif_to_wdev will return NULL after SDATA_STATE_RUNNING bit is cleared.
I guess it's similar not only for mac80211, and in case of interface removal we don't really want to send notifications for each function.

>
> Regards,
> Arend

2016-09-18 18:59:45

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands

On 18-9-2016 9:44, Otcheretianski, Andrei wrote:
>> -----Original Message-----
>> From: Arend Van Spriel [mailto:[email protected]]
>> Sent: Friday, September 16, 2016 13:59
>> To: Luca Coelho <[email protected]>; [email protected]
>> Cc: [email protected]; Beker, Ayala <[email protected]>;
>> Otcheretianski, Andrei <[email protected]>; Grumbach,
>> Emmanuel <[email protected]>; Coelho, Luciano
>> <[email protected]>
>> Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands
>>
>> On 16-9-2016 10:33, Luca Coelho wrote:
>>> From: Ayala Beker <[email protected]>
>>>
>>> This allows user space to start/stop NAN interface.
>>> A NAN interface is like P2P device in a few aspects: it doesn't have a
>>> netdev associated to it.
>>> Add the new interface type and prevent operations that can't be
>>> executed on NAN interface like scan.
>>>
>>> Define several attributes that may be configured by user space when
>>> starting NAN functionality (master preference and dual band operation)
>>>
>>> Signed-off-by: Andrei Otcheretianski <[email protected]>
>>> Signed-off-by: Emmanuel Grumbach <[email protected]>
>>> Signed-off-by: Luca Coelho <[email protected]>
>>> ---
>>> include/net/cfg80211.h | 21 +++++++++-
>>> include/uapi/linux/nl80211.h | 52 +++++++++++++++++++++++++
>>> net/mac80211/cfg.c | 2 +
>>> net/mac80211/chan.c | 3 ++
>>> net/mac80211/iface.c | 4 ++
>>> net/mac80211/offchannel.c | 1 +
>>> net/mac80211/rx.c | 3 ++
>>> net/mac80211/util.c | 1 +
>>> net/wireless/chan.c | 2 +
>>> net/wireless/core.c | 34 ++++++++++++++++
>>> net/wireless/core.h | 3 ++
>>> net/wireless/mlme.c | 1 +
>>> net/wireless/nl80211.c | 93
>> ++++++++++++++++++++++++++++++++++++++++++--
>>> net/wireless/rdev-ops.h | 20 ++++++++++
>>> net/wireless/trace.h | 27 +++++++++++++
>>> net/wireless/util.c | 6 ++-
>>> 16 files changed, 267 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index
>>> d5e7f69..ca64d69 100644
>>> --- a/include/net/cfg80211.h
>>> +++ b/include/net/cfg80211.h
>>> @@ -2293,6 +2293,19 @@ struct cfg80211_qos_map { };
>>
>> [...]
>>
>>> +/**
>>> + * enum nl80211_nan_dual_band_conf - NAN dual band configuration
>>> + *
>>> + * Defines the NAN dual band mode of operation
>>
>> Does it make sense to have such a notion of bands in use. And what does
>> 5.2GHz mean. Is this a subband within 5G channels? Probably I should read
>> the NAN spec to understand what is meant here. I would consider 5.2G as
>> lower 5G, ie. discovery on channel 44 but not sure if that is meant here.
>>
>
> The NAN spec defines single and dual band modes of operation. The channels are fixed for each band.
> On 2.4Ghz is channel 6 and 5GHz is either 44 or 149. Regarding 5.2 - it's just a typo. It should be 5G - no deeper meaning.

The thing is that it seems likely other bands will be added so that
would kinda obsolete this whole enum. So I would propose to have another
way to configure the bands to use. This enum is not really extensible
though it may reflect the current state of the spec, which is still in
draft if I am not mistaken.

Regards,
Arend

2016-09-16 08:33:40

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 6/9] cfg80211: Provide an API to report NAN function termination

From: Ayala Beker <[email protected]>

Provide a function that reports NAN DE function termination. The function
may be terminated due to one of the following reasons: user request,
ttl expiration or failure.
If the NAN instance is tied to the owner, the notification will be
sent to the socket that started the NAN interface only

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 16 ++++++++++++
include/uapi/linux/nl80211.h | 15 ++++++++++++
net/wireless/nl80211.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a08d7da..81770d6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5676,6 +5676,22 @@ struct cfg80211_nan_match_params {
void cfg80211_nan_match(struct wireless_dev *wdev,
struct cfg80211_nan_match_params *match, gfp_t gfp);

+/**
+ * cfg80211_nan_func_terminated - notify about NAN function termination.
+ *
+ * @wdev: the wireless device reporting the match
+ * @inst_id: the local instance id
+ * @reason: termination reason (one of the NL80211_NAN_FUNC_TERM_REASON_*)
+ * @cookie: unique NAN function identifier
+ * @gfp: allocation flags
+ *
+ * This function reports that the a NAN function is terminated.
+ */
+void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
+ u8 inst_id,
+ enum nl80211_nan_func_term_reason reason,
+ u64 cookie, gfp_t gfp);
+
/* ethtool helper */
void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index badb4a6..fd86be6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4978,6 +4978,21 @@ enum nl80211_nan_publish_type {
NL80211_NAN_UNSOLICITED_PUBLISH = 1 << 1,
};

+/**
+ * enum nl80211_nan_func_term_reason - NAN functions termination reason
+ *
+ * Defines termination reasons of a NAN function
+ *
+ * @NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST: requested by user
+ * @NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED: timeout
+ * @NL80211_NAN_FUNC_TERM_REASON_ERROR: errored
+ */
+enum nl80211_nan_func_term_reason {
+ NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST,
+ NL80211_NAN_FUNC_TERM_REASON_TTL_EXPIRED,
+ NL80211_NAN_FUNC_TERM_REASON_ERROR,
+};
+
#define NL80211_NAN_FUNC_SERVICE_ID_LEN 6
#define NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN 0xff
#define NL80211_NAN_FUNC_SRF_MAX_LEN 0xff
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4d37717..f817105 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10945,6 +10945,64 @@ nla_put_failure:
}
EXPORT_SYMBOL(cfg80211_nan_match);

+void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
+ u8 inst_id,
+ enum nl80211_nan_func_term_reason reason,
+ u64 cookie, gfp_t gfp)
+{
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ struct nlattr *func_attr;
+ void *hdr;
+
+ if (WARN_ON(!inst_id))
+ return;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RM_NAN_FUNCTION);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
+ wdev->netdev->ifindex)) ||
+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+ goto nla_put_failure;
+
+ if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+ goto nla_put_failure;
+
+ func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);
+ if (!func_attr)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID, inst_id) ||
+ nla_put_u8(msg, NL80211_NAN_FUNC_TERM_REASON, reason))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, func_attr);
+ genlmsg_end(msg, hdr);
+
+ if (!wdev->owner_nlportid)
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
+ msg, 0, NL80211_MCGRP_NAN, gfp);
+ else
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
+ wdev->owner_nlportid);
+
+ return;
+
+nla_put_failure:
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_nan_func_terminated);
+
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{
--
2.9.3

2016-09-16 11:00:24

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/9] cfg80211: add start / stop NAN commands


> I think NUM_NL80211_IFTYPES should not be in the switch. If it must I
> would leave it as last one here.
>

It just suppresses compiler warnings :)

johannes

2016-09-21 08:00:22

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN



On 20-9-2016 16:36, Luca Coelho wrote:
> Hi Arend,
>
> On Tue, 2016-09-20 at 14:29 +0200, Arend Van Spriel wrote:
>> On 20-9-2016 13:45, Beker, Ayala wrote:
>>> I don't think there is something in common to those interface types
>>> that can fit such a function semantically, so I decided not to
>>> change it.
>>> Do you have any idea?
>>
>> What is common is that these are both non-netdev interface types.
>
> I tend to agree with you. I also thought about an
> ieee80211_has_netdev() function for this, but I didn't check whether
> this was exactly what we need...

Maybe it does not fit all instances, but quite a few checks are there to
skip netdev related stuff.

> In any case, do you mind if we address this in a separate patch?

Fine by me.

Regards,
Arend

> --
> Cheers,
> Luca.
>

2016-09-19 08:07:37

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 4/9] cfg80211: allow the user space to change current NAN configuration

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 22:43
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 4/9] cfg80211: allow the user space to change current
> NAN configuration
>
> On 16-9-2016 10:33, Luca Coelho wrote:
> > From: Ayala Beker <[email protected]>
> >
> > Some NAN configuration paramaters may change during the operation of
> > the NaN device. For example, a user may want to update master
> > preference
>
> typo: NAN iso NaN.

Thanks

>
> Regards,
> Arend

2016-09-18 07:59:56

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Friday, September 16, 2016 14:09
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop
> NAN
>
> On 16-9-2016 10:33, Luca Coelho wrote:
> > From: Ayala Beker <[email protected]>
> >
> > This code doesn't do much besides allowing to start and stop the vif.
> >
> > Signed-off-by: Andrei Otcheretianski <[email protected]>
> > Signed-off-by: Emmanuel Grumbach <[email protected]>
> > Signed-off-by: Ayala Beker <[email protected]>
> > Signed-off-by: Luca Coelho <[email protected]>
> > ---
> > include/net/mac80211.h | 9 +++++++++
> > net/mac80211/cfg.c | 36 ++++++++++++++++++++++++++++++++++
> > net/mac80211/chan.c | 3 +++
> > net/mac80211/driver-ops.h | 29 ++++++++++++++++++++++++++-
> > net/mac80211/iface.c | 8 ++++++--
> > net/mac80211/main.c | 5 +++++
> > net/mac80211/offchannel.c | 3 ++-
> > net/mac80211/trace.h | 50
> +++++++++++++++++++++++++++++++++++++++++++++++
> > net/mac80211/util.c | 3 ++-
> > 9 files changed, 141 insertions(+), 5 deletions(-)
>
> [...]
>
> > diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
> > index fe35a1c..67b42c8 100644
> > --- a/net/mac80211/driver-ops.h
> > +++ b/net/mac80211/driver-ops.h
> > @@ -163,7 +163,8 @@ static inline void drv_bss_info_changed(struct
> > ieee80211_local *local,
> >
> > if (WARN_ON_ONCE(sdata->vif.type ==
> NL80211_IFTYPE_P2P_DEVICE ||
> > (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
> > - !sdata->vif.mu_mimo_owner)))
> > + !sdata->vif.mu_mimo_owner) ||
> > + sdata->vif.type == NL80211_IFTYPE_NAN))
>
> Might be more clear to move this up right after P2P_DEVICE check.

Why? It's a completely separate new condition - so it goes to the end.

>
> > return;
> >
> > if (!check_sdata_in_driver(sdata))
> > @@ -1165,4 +1166,30 @@ static inline void drv_wake_tx_queue(struct
> ieee80211_local *local,
> > local->ops->wake_tx_queue(&local->hw, &txq->txq); }
> >
> > +static inline int drv_start_nan(struct ieee80211_local *local,
> > + struct ieee80211_sub_if_data *sdata,
> > + struct cfg80211_nan_conf *conf)
> > +{
> > + int ret;
> > +
> > + might_sleep();
> > + check_sdata_in_driver(sdata);
> > +
> > + trace_drv_start_nan(local, sdata, conf);
> > + ret = local->ops->start_nan(&local->hw, &sdata->vif, conf);
> > + trace_drv_return_int(local, ret);
> > + return ret;
> > +}
> > +
> > +static inline void drv_stop_nan(struct ieee80211_local *local,
> > + struct ieee80211_sub_if_data *sdata) {
> > + might_sleep();
> > + check_sdata_in_driver(sdata);
> > +
> > + trace_drv_stop_nan(local, sdata);
> > + local->ops->stop_nan(&local->hw, &sdata->vif);
> > + trace_drv_return_void(local);
> > +}
> > +
> > #endif /* __MAC80211_DRIVER_OPS */
> > diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index
> > e694ca2..507f46a 100644
> > --- a/net/mac80211/iface.c
> > +++ b/net/mac80211/iface.c
> > @@ -327,6 +327,9 @@ static int ieee80211_check_queues(struct
> ieee80211_sub_if_data *sdata,
> > int n_queues = sdata->local->hw.queues;
> > int i;
> >
> > + if (iftype == NL80211_IFTYPE_NAN)
> > + return 0;
> > +
> > if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
> > for (i = 0; i < IEEE80211_NUM_ACS; i++) {
> > if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == @@
> -647,7 +650,8 @@ int
> > ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
> > local->fif_probe_req++;
> > }
> >
> > - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE)
> > + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
> > + sdata->vif.type != NL80211_IFTYPE_NAN)
>
> similar check keeps reoccuring in various places so maybe we can create a
> helper function for it.

Right, but not sure that it deserves a function.

>
> > changed |= ieee80211_reset_erp_info(sdata);
> > ieee80211_bss_info_change_notify(sdata, changed);
> >
>
> Regards,
> Arend

2016-09-18 19:54:26

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> A NAN function can be either publish, subscribe or follow
> up. Make all the necessary verifications and just pass the
> request to the driver.
> Allow the user space application that starts NAN to
> forbid any other socket to add or remove functions.
>
> Signed-off-by: Andrei Otcheretianski <[email protected]>
> Signed-off-by: Emmanuel Grumbach <[email protected]>
> Signed-off-by: Ayala Beker <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>
> ---

[...]

> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 7ab18c8..ab16c8e 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -847,6 +847,24 @@
> * After this command NAN functions can be added.
> * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
> * its %NL80211_ATTR_WDEV interface.
> + * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined
> + * with %NL80211_ATTR_NAN_FUNC nested attribute. When called, this
> + * operation returns the strictly positive and unique instance id
> + * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie (%NL80211_ATTR_COOKIE)
> + * of the function upon success.
> + * Since instance ID's can be re-used, this cookie is the right
> + * way to identify the function. This will avoid races when a termination
> + * event is handled by the user space after it has already added a new
> + * function that got the same instance id from the kernel as the one
> + * which just terminated.
> + * This cookie may be used in NAN events even before the command
> + * returns, so userspace shouldn't process NAN events until it processes
> + * the response to this command.
> + * Look at %NL80211_ATTR_SOCKET_OWNER as well.
> + * @NL80211_CMD_RM_NAN_FUNCTION: Remove a NAN function by cookie.
> + * This command is also used as a notification sent when a NAN function is
> + * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
> + * and %NL80211_ATTR_COOKIE attributes.

This patch does not show the notification scenario as it is added in
patch 6. So those three lines could be added by that patch instead to
keep things logically together.

Regards,
Arend

2016-09-20 14:36:50

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH v2 2/9] mac80211: add boilerplate code for start / stop NAN

Hi Arend,

On Tue, 2016-09-20 at 14:29 +0200, Arend Van Spriel wrote:
> On 20-9-2016 13:45, Beker, Ayala wrote:
> > I don't think there is something in common to those interface types
> > that can fit such a function semantically, so I decided not to
> > change it.
> > Do you have any idea?
>
> What is common is that these are both non-netdev interface types.

I tend to agree with you.  I also thought about an
ieee80211_has_netdev() function for this, but I didn't check whether
this was exactly what we need...

In any case, do you mind if we address this in a separate patch?

--
Cheers,
Luca.

2016-09-18 19:29:10

by Arend Van Spriel

[permalink] [raw]
Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

On 16-9-2016 10:33, Luca Coelho wrote:
> From: Ayala Beker <[email protected]>
>
> A NAN function can be either publish, subscribe or follow
> up. Make all the necessary verifications and just pass the
> request to the driver.
> Allow the user space application that starts NAN to
> forbid any other socket to add or remove functions.
>
> Signed-off-by: Andrei Otcheretianski <[email protected]>
> Signed-off-by: Emmanuel Grumbach <[email protected]>
> Signed-off-by: Ayala Beker <[email protected]>
> Signed-off-by: Luca Coelho <[email protected]>
> ---
> include/net/cfg80211.h | 91 +++++++++++
> include/uapi/linux/nl80211.h | 153 ++++++++++++++++++
> net/wireless/core.c | 3 +-
> net/wireless/nl80211.c | 368 +++++++++++++++++++++++++++++++++++++++++++
> net/wireless/rdev-ops.h | 21 +++
> net/wireless/trace.h | 39 +++++
> net/wireless/util.c | 22 +++
> 7 files changed, 696 insertions(+), 1 deletion(-)
>
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index ca64d69..ced5b8a 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -2306,6 +2306,73 @@ struct cfg80211_nan_conf {
> };
>
> /**
> + * struct cfg80211_nan_func_filter - a NAN function Rx / Tx filter
> + *
> + * @filter: the content of the filter
> + * @len: the length of the filter
> + */
> +struct cfg80211_nan_func_filter {
> + const u8 *filter;
> + u8 len;
> +};
> +
> +/**
> + * struct cfg80211_nan_func - a NAN function
> + *
> + * @type: &enum nl80211_nan_function_type
> + * @service_id: the service ID of the function
> + * @publish_type: &nl80211_nan_publish_type
> + * @close_range: if true, the range should be limited. Threshold is
> + * implementation specific.
> + * @publish_bcast: if true, the solicited publish should be broadcasted
> + * @subscribe_active: if true, the subscribe is active
> + * @followup_id: the instance ID for follow up
> + * @followup_reqid: the requestor instance ID for follow up
> + * @followup_dest: MAC address of the recipient of the follow up
> + * @ttl: time to live counter in DW.
> + * @serv_spec_info: Service Specific Info
> + * @serv_spec_info_len: Service Specific Info length
> + * @srf_include: if true, SRF is inclusive
> + * @srf_bf: Bloom Filter
> + * @srf_bf_len: Bloom Filter length
> + * @srf_bf_idx: Bloom Filter index
> + * @srf_macs: SRF MAC addresses
> + * @srf_num_macs: number of MAC addresses in SRF
> + * @rx_filters: rx filters that are matched with corresponding peer's tx_filter
> + * @tx_filters: filters that should be transmitted in the SDF.
> + * @num_rx_filters: length of &rx_filters.
> + * @num_tx_filters: length of &tx_filters.
> + * @instance_id: driver allocated id of the function.
> + * @cookie: unique NAN function identifier.

Might be wrong but it seems a subset of the fields is used depending on
the type of NAN function. Maybe better to separate the function type
specific field in a sub structure defintion.

> + */
> +struct cfg80211_nan_func {
> + enum nl80211_nan_function_type type;
> + u8 service_id[NL80211_NAN_FUNC_SERVICE_ID_LEN];
> + u8 publish_type;
> + bool close_range;
> + bool publish_bcast;
> + bool subscribe_active;
> + u8 followup_id;
> + u8 followup_reqid;
> + struct mac_address followup_dest;
> + u32 ttl;
> + const u8 *serv_spec_info;
> + u8 serv_spec_info_len;
> + bool srf_include;
> + const u8 *srf_bf;
> + u8 srf_bf_len;
> + u8 srf_bf_idx;
> + struct mac_address *srf_macs;
> + int srf_num_macs;
> + struct cfg80211_nan_func_filter *rx_filters;
> + struct cfg80211_nan_func_filter *tx_filters;
> + u8 num_tx_filters;
> + u8 num_rx_filters;
> + u8 instance_id;
> + u64 cookie;
> +};
> +
> +/**
> * struct cfg80211_ops - backend description for wireless configuration
> *
> * This struct is registered by fullmac card drivers and/or wireless stacks
> @@ -2595,6 +2662,14 @@ struct cfg80211_nan_conf {
> * peers must be on the base channel when the call completes.
> * @start_nan: Start the NAN interface.
> * @stop_nan: Stop the NAN interface.
> + * @add_nan_func: Add a NAN function. Returns negative value on failure.
> + * On success @nan_func ownership is transferred to the driver and
> + * it may access it outside of the scope of this function. The driver
> + * should free the @nan_func when no longer needed by calling
> + * cfg80211_free_nan_func().
> + * On success the driver should assign an instance_id in the
> + * provided @nan_func.
> + * @rm_nan_func: Remove a NAN function.

Would prefer del_nan_func here. At least all other add_* callbacks in
this structure have a del_* counter part.

> */
> struct cfg80211_ops {
> int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
> @@ -2863,6 +2938,10 @@ struct cfg80211_ops {
> int (*start_nan)(struct wiphy *wiphy, struct wireless_dev *wdev,
> struct cfg80211_nan_conf *conf);
> void (*stop_nan)(struct wiphy *wiphy, struct wireless_dev *wdev);
> + int (*add_nan_func)(struct wiphy *wiphy, struct wireless_dev *wdev,
> + struct cfg80211_nan_func *nan_func);
> + void (*rm_nan_func)(struct wiphy *wiphy, struct wireless_dev *wdev,
> + u64 cookie);
> };
>
> /*
> @@ -3311,6 +3390,8 @@ struct wiphy_iftype_ext_capab {
> * @bss_select_support: bitmask indicating the BSS selection criteria supported
> * by the driver in the .connect() callback. The bit position maps to the
> * attribute indices defined in &enum nl80211_bss_select_attr.
> + *
> + * @cookie_counter: unique generic cookie counter, used to identify objects.
> */
> struct wiphy {
> /* assign these fields before you register the wiphy */
> @@ -3440,6 +3521,8 @@ struct wiphy {
>
> u32 bss_select_support;
>
> + u64 cookie_counter;
> +
> char priv[0] __aligned(NETDEV_ALIGN);
> };
>
> @@ -5529,6 +5612,14 @@ wiphy_ext_feature_isset(struct wiphy *wiphy,
> return (ft_byte & BIT(ftidx % 8)) != 0;
> }
>
> +/**
> + * cfg80211_free_nan_func - free NAN function
> + * @f: NAN function that should be freed
> + *
> + * Frees all the NAN function and all it's allocated members.
> + */
> +void cfg80211_free_nan_func(struct cfg80211_nan_func *f);
> +
> /* ethtool helper */
> void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
>
> diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
> index 7ab18c8..ab16c8e 100644
> --- a/include/uapi/linux/nl80211.h
> +++ b/include/uapi/linux/nl80211.h
> @@ -847,6 +847,24 @@
> * After this command NAN functions can be added.
> * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
> * its %NL80211_ATTR_WDEV interface.
> + * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined
> + * with %NL80211_ATTR_NAN_FUNC nested attribute. When called, this
> + * operation returns the strictly positive and unique instance id
> + * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie (%NL80211_ATTR_COOKIE)
> + * of the function upon success.
> + * Since instance ID's can be re-used, this cookie is the right
> + * way to identify the function. This will avoid races when a termination
> + * event is handled by the user space after it has already added a new
> + * function that got the same instance id from the kernel as the one
> + * which just terminated.
> + * This cookie may be used in NAN events even before the command
> + * returns, so userspace shouldn't process NAN events until it processes
> + * the response to this command.
> + * Look at %NL80211_ATTR_SOCKET_OWNER as well.
> + * @NL80211_CMD_RM_NAN_FUNCTION: Remove a NAN function by cookie.
> + * This command is also used as a notification sent when a NAN function is
> + * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
> + * and %NL80211_ATTR_COOKIE attributes.
> *
> * @NL80211_CMD_MAX: highest used command number
> * @__NL80211_CMD_AFTER_LAST: internal use
> @@ -1038,6 +1056,8 @@ enum nl80211_commands {
>
> NL80211_CMD_START_NAN,
> NL80211_CMD_STOP_NAN,
> + NL80211_CMD_ADD_NAN_FUNCTION,
> + NL80211_CMD_RM_NAN_FUNCTION,

NL80211_CMD_DEL_NAN_FUNCTION?

Regards,
Arend

2016-09-19 07:56:33

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func



> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 22:29
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func
>
> On 16-9-2016 10:33, Luca Coelho wrote:
> > From: Ayala Beker <[email protected]>
> >
> > A NAN function can be either publish, subscribe or follow up. Make all
> > the necessary verifications and just pass the request to the driver.
> > Allow the user space application that starts NAN to forbid any other
> > socket to add or remove functions.
> >
> > Signed-off-by: Andrei Otcheretianski <[email protected]>
> > Signed-off-by: Emmanuel Grumbach <[email protected]>
> > Signed-off-by: Ayala Beker <[email protected]>
> > Signed-off-by: Luca Coelho <[email protected]>
> > ---
> > include/net/cfg80211.h | 91 +++++++++++
> > include/uapi/linux/nl80211.h | 153 ++++++++++++++++++
> > net/wireless/core.c | 3 +-
> > net/wireless/nl80211.c | 368
> +++++++++++++++++++++++++++++++++++++++++++
> > net/wireless/rdev-ops.h | 21 +++
> > net/wireless/trace.h | 39 +++++
> > net/wireless/util.c | 22 +++
> > 7 files changed, 696 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index
> > ca64d69..ced5b8a 100644
> > --- a/include/net/cfg80211.h
> > +++ b/include/net/cfg80211.h
> > @@ -2306,6 +2306,73 @@ struct cfg80211_nan_conf { };
> >
> > /**
> > + * struct cfg80211_nan_func_filter - a NAN function Rx / Tx filter
> > + *
> > + * @filter: the content of the filter
> > + * @len: the length of the filter
> > + */
> > +struct cfg80211_nan_func_filter {
> > + const u8 *filter;
> > + u8 len;
> > +};
> > +
> > +/**
> > + * struct cfg80211_nan_func - a NAN function
> > + *
> > + * @type: &enum nl80211_nan_function_type
> > + * @service_id: the service ID of the function
> > + * @publish_type: &nl80211_nan_publish_type
> > + * @close_range: if true, the range should be limited. Threshold is
> > + * implementation specific.
> > + * @publish_bcast: if true, the solicited publish should be
> > +broadcasted
> > + * @subscribe_active: if true, the subscribe is active
> > + * @followup_id: the instance ID for follow up
> > + * @followup_reqid: the requestor instance ID for follow up
> > + * @followup_dest: MAC address of the recipient of the follow up
> > + * @ttl: time to live counter in DW.
> > + * @serv_spec_info: Service Specific Info
> > + * @serv_spec_info_len: Service Specific Info length
> > + * @srf_include: if true, SRF is inclusive
> > + * @srf_bf: Bloom Filter
> > + * @srf_bf_len: Bloom Filter length
> > + * @srf_bf_idx: Bloom Filter index
> > + * @srf_macs: SRF MAC addresses
> > + * @srf_num_macs: number of MAC addresses in SRF
> > + * @rx_filters: rx filters that are matched with corresponding peer's
> > +tx_filter
> > + * @tx_filters: filters that should be transmitted in the SDF.
> > + * @num_rx_filters: length of &rx_filters.
> > + * @num_tx_filters: length of &tx_filters.
> > + * @instance_id: driver allocated id of the function.
> > + * @cookie: unique NAN function identifier.
>
> Might be wrong but it seems a subset of the fields is used depending on the
> type of NAN function. Maybe better to separate the function type specific
> field in a sub structure defintion.

Most of the fields are common for all the function types. Of course some combinations aren't valid.
And there are few followup specific fields. The spec defines a single "NAN function" entity (for publish, subscribe and followup) which is represented in an SDA (service descriptor attribute).
This is what this struct tries to reflect.

>
> > + */
> > +struct cfg80211_nan_func {
> > + enum nl80211_nan_function_type type;
> > + u8 service_id[NL80211_NAN_FUNC_SERVICE_ID_LEN];
> > + u8 publish_type;
> > + bool close_range;
> > + bool publish_bcast;
> > + bool subscribe_active;
> > + u8 followup_id;
> > + u8 followup_reqid;
> > + struct mac_address followup_dest;
> > + u32 ttl;
> > + const u8 *serv_spec_info;
> > + u8 serv_spec_info_len;
> > + bool srf_include;
> > + const u8 *srf_bf;
> > + u8 srf_bf_len;
> > + u8 srf_bf_idx;
> > + struct mac_address *srf_macs;
> > + int srf_num_macs;
> > + struct cfg80211_nan_func_filter *rx_filters;
> > + struct cfg80211_nan_func_filter *tx_filters;
> > + u8 num_tx_filters;
> > + u8 num_rx_filters;
> > + u8 instance_id;
> > + u64 cookie;
> > +};
> > +
> > +/**
> > * struct cfg80211_ops - backend description for wireless configuration
> > *
> > * This struct is registered by fullmac card drivers and/or wireless
> > stacks @@ -2595,6 +2662,14 @@ struct cfg80211_nan_conf {
> > * peers must be on the base channel when the call completes.
> > * @start_nan: Start the NAN interface.
> > * @stop_nan: Stop the NAN interface.
> > + * @add_nan_func: Add a NAN function. Returns negative value on
> failure.
> > + * On success @nan_func ownership is transferred to the driver and
> > + * it may access it outside of the scope of this function. The driver
> > + * should free the @nan_func when no longer needed by calling
> > + * cfg80211_free_nan_func().
> > + * On success the driver should assign an instance_id in the
> > + * provided @nan_func.
> > + * @rm_nan_func: Remove a NAN function.
>
> Would prefer del_nan_func here. At least all other add_* callbacks in this
> structure have a del_* counter part.

Hmm.. A little bit nitpicky ;) but ok..
( I personally prefer to use "remove" to reflect removal from a list and del for "erase" like operations - here it does both)

>
> > */
> > struct cfg80211_ops {
> > int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan
> *wow);
> > @@ -2863,6 +2938,10 @@ struct cfg80211_ops {
> > int (*start_nan)(struct wiphy *wiphy, struct wireless_dev
> *wdev,
> > struct cfg80211_nan_conf *conf);
> > void (*stop_nan)(struct wiphy *wiphy, struct wireless_dev
> *wdev);
> > + int (*add_nan_func)(struct wiphy *wiphy, struct wireless_dev
> *wdev,
> > + struct cfg80211_nan_func *nan_func);
> > + void (*rm_nan_func)(struct wiphy *wiphy, struct wireless_dev
> *wdev,
> > + u64 cookie);
> > };
> >
> > /*
> > @@ -3311,6 +3390,8 @@ struct wiphy_iftype_ext_capab {
> > * @bss_select_support: bitmask indicating the BSS selection criteria
> supported
> > * by the driver in the .connect() callback. The bit position maps to the
> > * attribute indices defined in &enum nl80211_bss_select_attr.
> > + *
> > + * @cookie_counter: unique generic cookie counter, used to identify
> objects.
> > */
> > struct wiphy {
> > /* assign these fields before you register the wiphy */ @@ -3440,6
> > +3521,8 @@ struct wiphy {
> >
> > u32 bss_select_support;
> >
> > + u64 cookie_counter;
> > +
> > char priv[0] __aligned(NETDEV_ALIGN); };
> >
> > @@ -5529,6 +5612,14 @@ wiphy_ext_feature_isset(struct wiphy *wiphy,
> > return (ft_byte & BIT(ftidx % 8)) != 0; }
> >
> > +/**
> > + * cfg80211_free_nan_func - free NAN function
> > + * @f: NAN function that should be freed
> > + *
> > + * Frees all the NAN function and all it's allocated members.
> > + */
> > +void cfg80211_free_nan_func(struct cfg80211_nan_func *f);
> > +
> > /* ethtool helper */
> > void cfg80211_get_drvinfo(struct net_device *dev, struct
> > ethtool_drvinfo *info);
> >
> > diff --git a/include/uapi/linux/nl80211.h
> > b/include/uapi/linux/nl80211.h index 7ab18c8..ab16c8e 100644
> > --- a/include/uapi/linux/nl80211.h
> > +++ b/include/uapi/linux/nl80211.h
> > @@ -847,6 +847,24 @@
> > * After this command NAN functions can be added.
> > * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
> > * its %NL80211_ATTR_WDEV interface.
> > + * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The
> function is defined
> > + * with %NL80211_ATTR_NAN_FUNC nested attribute. When called,
> this
> > + * operation returns the strictly positive and unique instance id
> > + * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie
> (%NL80211_ATTR_COOKIE)
> > + * of the function upon success.
> > + * Since instance ID's can be re-used, this cookie is the right
> > + * way to identify the function. This will avoid races when a termination
> > + * event is handled by the user space after it has already added a new
> > + * function that got the same instance id from the kernel as the one
> > + * which just terminated.
> > + * This cookie may be used in NAN events even before the command
> > + * returns, so userspace shouldn't process NAN events until it
> processes
> > + * the response to this command.
> > + * Look at %NL80211_ATTR_SOCKET_OWNER as well.
> > + * @NL80211_CMD_RM_NAN_FUNCTION: Remove a NAN function by
> cookie.
> > + * This command is also used as a notification sent when a NAN function
> is
> > + * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
> > + * and %NL80211_ATTR_COOKIE attributes.
> > *
> > * @NL80211_CMD_MAX: highest used command number
> > * @__NL80211_CMD_AFTER_LAST: internal use @@ -1038,6 +1056,8 @@
> enum
> > nl80211_commands {
> >
> > NL80211_CMD_START_NAN,
> > NL80211_CMD_STOP_NAN,
> > + NL80211_CMD_ADD_NAN_FUNCTION,
> > + NL80211_CMD_RM_NAN_FUNCTION,
>
> NL80211_CMD_DEL_NAN_FUNCTION?
>
> Regards,
> Arend

2016-09-16 08:33:37

by Luca Coelho

[permalink] [raw]
Subject: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

From: Ayala Beker <[email protected]>

A NAN function can be either publish, subscribe or follow
up. Make all the necessary verifications and just pass the
request to the driver.
Allow the user space application that starts NAN to
forbid any other socket to add or remove functions.

Signed-off-by: Andrei Otcheretianski <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Ayala Beker <[email protected]>
Signed-off-by: Luca Coelho <[email protected]>
---
include/net/cfg80211.h | 91 +++++++++++
include/uapi/linux/nl80211.h | 153 ++++++++++++++++++
net/wireless/core.c | 3 +-
net/wireless/nl80211.c | 368 +++++++++++++++++++++++++++++++++++++++++++
net/wireless/rdev-ops.h | 21 +++
net/wireless/trace.h | 39 +++++
net/wireless/util.c | 22 +++
7 files changed, 696 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ca64d69..ced5b8a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2306,6 +2306,73 @@ struct cfg80211_nan_conf {
};

/**
+ * struct cfg80211_nan_func_filter - a NAN function Rx / Tx filter
+ *
+ * @filter: the content of the filter
+ * @len: the length of the filter
+ */
+struct cfg80211_nan_func_filter {
+ const u8 *filter;
+ u8 len;
+};
+
+/**
+ * struct cfg80211_nan_func - a NAN function
+ *
+ * @type: &enum nl80211_nan_function_type
+ * @service_id: the service ID of the function
+ * @publish_type: &nl80211_nan_publish_type
+ * @close_range: if true, the range should be limited. Threshold is
+ * implementation specific.
+ * @publish_bcast: if true, the solicited publish should be broadcasted
+ * @subscribe_active: if true, the subscribe is active
+ * @followup_id: the instance ID for follow up
+ * @followup_reqid: the requestor instance ID for follow up
+ * @followup_dest: MAC address of the recipient of the follow up
+ * @ttl: time to live counter in DW.
+ * @serv_spec_info: Service Specific Info
+ * @serv_spec_info_len: Service Specific Info length
+ * @srf_include: if true, SRF is inclusive
+ * @srf_bf: Bloom Filter
+ * @srf_bf_len: Bloom Filter length
+ * @srf_bf_idx: Bloom Filter index
+ * @srf_macs: SRF MAC addresses
+ * @srf_num_macs: number of MAC addresses in SRF
+ * @rx_filters: rx filters that are matched with corresponding peer's tx_filter
+ * @tx_filters: filters that should be transmitted in the SDF.
+ * @num_rx_filters: length of &rx_filters.
+ * @num_tx_filters: length of &tx_filters.
+ * @instance_id: driver allocated id of the function.
+ * @cookie: unique NAN function identifier.
+ */
+struct cfg80211_nan_func {
+ enum nl80211_nan_function_type type;
+ u8 service_id[NL80211_NAN_FUNC_SERVICE_ID_LEN];
+ u8 publish_type;
+ bool close_range;
+ bool publish_bcast;
+ bool subscribe_active;
+ u8 followup_id;
+ u8 followup_reqid;
+ struct mac_address followup_dest;
+ u32 ttl;
+ const u8 *serv_spec_info;
+ u8 serv_spec_info_len;
+ bool srf_include;
+ const u8 *srf_bf;
+ u8 srf_bf_len;
+ u8 srf_bf_idx;
+ struct mac_address *srf_macs;
+ int srf_num_macs;
+ struct cfg80211_nan_func_filter *rx_filters;
+ struct cfg80211_nan_func_filter *tx_filters;
+ u8 num_tx_filters;
+ u8 num_rx_filters;
+ u8 instance_id;
+ u64 cookie;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2595,6 +2662,14 @@ struct cfg80211_nan_conf {
* peers must be on the base channel when the call completes.
* @start_nan: Start the NAN interface.
* @stop_nan: Stop the NAN interface.
+ * @add_nan_func: Add a NAN function. Returns negative value on failure.
+ * On success @nan_func ownership is transferred to the driver and
+ * it may access it outside of the scope of this function. The driver
+ * should free the @nan_func when no longer needed by calling
+ * cfg80211_free_nan_func().
+ * On success the driver should assign an instance_id in the
+ * provided @nan_func.
+ * @rm_nan_func: Remove a NAN function.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2863,6 +2938,10 @@ struct cfg80211_ops {
int (*start_nan)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct cfg80211_nan_conf *conf);
void (*stop_nan)(struct wiphy *wiphy, struct wireless_dev *wdev);
+ int (*add_nan_func)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ struct cfg80211_nan_func *nan_func);
+ void (*rm_nan_func)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ u64 cookie);
};

/*
@@ -3311,6 +3390,8 @@ struct wiphy_iftype_ext_capab {
* @bss_select_support: bitmask indicating the BSS selection criteria supported
* by the driver in the .connect() callback. The bit position maps to the
* attribute indices defined in &enum nl80211_bss_select_attr.
+ *
+ * @cookie_counter: unique generic cookie counter, used to identify objects.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -3440,6 +3521,8 @@ struct wiphy {

u32 bss_select_support;

+ u64 cookie_counter;
+
char priv[0] __aligned(NETDEV_ALIGN);
};

@@ -5529,6 +5612,14 @@ wiphy_ext_feature_isset(struct wiphy *wiphy,
return (ft_byte & BIT(ftidx % 8)) != 0;
}

+/**
+ * cfg80211_free_nan_func - free NAN function
+ * @f: NAN function that should be freed
+ *
+ * Frees all the NAN function and all it's allocated members.
+ */
+void cfg80211_free_nan_func(struct cfg80211_nan_func *f);
+
/* ethtool helper */
void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 7ab18c8..ab16c8e 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -847,6 +847,24 @@
* After this command NAN functions can be added.
* @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
* its %NL80211_ATTR_WDEV interface.
+ * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The function is defined
+ * with %NL80211_ATTR_NAN_FUNC nested attribute. When called, this
+ * operation returns the strictly positive and unique instance id
+ * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie (%NL80211_ATTR_COOKIE)
+ * of the function upon success.
+ * Since instance ID's can be re-used, this cookie is the right
+ * way to identify the function. This will avoid races when a termination
+ * event is handled by the user space after it has already added a new
+ * function that got the same instance id from the kernel as the one
+ * which just terminated.
+ * This cookie may be used in NAN events even before the command
+ * returns, so userspace shouldn't process NAN events until it processes
+ * the response to this command.
+ * Look at %NL80211_ATTR_SOCKET_OWNER as well.
+ * @NL80211_CMD_RM_NAN_FUNCTION: Remove a NAN function by cookie.
+ * This command is also used as a notification sent when a NAN function is
+ * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
+ * and %NL80211_ATTR_COOKIE attributes.
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -1038,6 +1056,8 @@ enum nl80211_commands {

NL80211_CMD_START_NAN,
NL80211_CMD_STOP_NAN,
+ NL80211_CMD_ADD_NAN_FUNCTION,
+ NL80211_CMD_RM_NAN_FUNCTION,

/* add new commands above here */

@@ -1893,6 +1913,9 @@ enum nl80211_commands {
* @NL80211_ATTR_NAN_DUAL: NAN dual band operation config (see
* &enum nl80211_nan_dual_band_conf). This attribute is used with
* %NL80211_CMD_START_NAN.
+ * @NL80211_ATTR_NAN_FUNC: a function that can be added to NAN. See
+ * &enum nl80211_nan_func_attributes for description of this nested
+ * attribute.
*
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
@@ -2290,6 +2313,7 @@ enum nl80211_attrs {

NL80211_ATTR_NAN_MASTER_PREF,
NL80211_ATTR_NAN_DUAL,
+ NL80211_ATTR_NAN_FUNC,

/* add attributes here, update the policy in nl80211.c */

@@ -4907,4 +4931,133 @@ enum nl80211_nan_dual_band_conf {
__NL80211_NAN_BAND_AFTER_LAST - 1,
};

+/**
+ * enum nl80211_nan_function_type - NAN function type
+ *
+ * Defines the function type of a NAN function
+ *
+ * @NL80211_NAN_FUNC_PUBLISH: function is publish
+ * @NL80211_NAN_FUNC_SUBSCRIBE: function is subscribe
+ * @NL80211_NAN_FUNC_FOLLOW_UP: function is follow-up
+ */
+enum nl80211_nan_function_type {
+ NL80211_NAN_FUNC_PUBLISH,
+ NL80211_NAN_FUNC_SUBSCRIBE,
+ NL80211_NAN_FUNC_FOLLOW_UP,
+
+ /* keep last */
+ __NL80211_NAN_FUNC_TYPE_AFTER_LAST,
+ NL80211_NAN_FUNC_MAX_TYPE = __NL80211_NAN_FUNC_TYPE_AFTER_LAST - 1,
+};
+
+/**
+ * enum nl80211_nan_publish_type - NAN publish tx type
+ *
+ * Defines how to send publish Service Discovery Frames
+ *
+ * @NL80211_NAN_SOLICITED_PUBLISH: publish function is solicited
+ * @NL80211_NAN_UNSOLICITED_PUBLISH: publish function is unsolicited
+ */
+enum nl80211_nan_publish_type {
+ NL80211_NAN_SOLICITED_PUBLISH = 1 << 0,
+ NL80211_NAN_UNSOLICITED_PUBLISH = 1 << 1,
+};
+
+#define NL80211_NAN_FUNC_SERVICE_ID_LEN 6
+#define NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN 0xff
+#define NL80211_NAN_FUNC_SRF_MAX_LEN 0xff
+
+/**
+ * enum nl80211_nan_func_attributes - NAN function attributes
+ * @__NL80211_NAN_FUNC_INVALID: invalid
+ * @NL80211_NAN_FUNC_TYPE: &enum nl80211_nan_function_type (u8).
+ * @NL80211_NAN_FUNC_SERVICE_ID: 6 bytes of the service ID hash as
+ * specified in NAN spec. This is a binary attribute.
+ * @NL80211_NAN_FUNC_PUBLISH_TYPE: relevant if the function's type is
+ * publish. Defines the transmission type for the publish Service Discovery
+ * Frame, see &enum nl80211_nan_publish_type. Its type is u8.
+ * @NL80211_NAN_FUNC_PUBLISH_BCAST: relevant if the function is a solicited
+ * publish. Should the solicited publish Service Discovery Frame be sent to
+ * the NAN Broadcast address. This is a flag.
+ * @NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE: relevant if the function's type is
+ * subscribe. Is the subscribe active. This is a flag.
+ * @NL80211_NAN_FUNC_FOLLOW_UP_ID: relevant if the function's type is follow up.
+ * The instance ID for the follow up Service Discovery Frame. This is u8.
+ * @NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID: relevant if the function's type
+ * is follow up. This is a u8.
+ * The requestor instance ID for the follow up Service Discovery Frame.
+ * @NL80211_NAN_FUNC_FOLLOW_UP_DEST: the MAC address of the recipient of the
+ * follow up Service Discovery Frame. This is a binary attribute.
+ * @NL80211_NAN_FUNC_CLOSE_RANGE: is this function limited for devices in a
+ * close range. The range itself (RSSI) is defined by the device.
+ * This is a flag.
+ * @NL80211_NAN_FUNC_TTL: strictly positive number of DWs this function should
+ * stay active. If not present infinite TTL is assumed. This is a u32.
+ * @NL80211_NAN_FUNC_SERVICE_INFO: array of bytes describing the service
+ * specific info. This is a binary attribute.
+ * @NL80211_NAN_FUNC_SRF: Service Receive Filter. This is a nested attribute.
+ * See &enum nl80211_nan_srf_attributes.
+ * @NL80211_NAN_FUNC_RX_MATCH_FILTER: Receive Matching filter. This is a nested
+ * attribute. It is a list of binary values.
+ * @NL80211_NAN_FUNC_TX_MATCH_FILTER: Transmit Matching filter. This is a
+ * nested attribute. It is a list of binary values.
+ * @NL80211_NAN_FUNC_INSTANCE_ID: The instance ID of the function.
+ * Its type is u8 and it cannot be 0.
+ * @NL80211_NAN_FUNC_TERM_REASON: NAN function termination reason.
+ * See &enum nl80211_nan_func_term_reason.
+ *
+ * @NUM_NL80211_NAN_FUNC_ATTR: internal
+ * @NL80211_NAN_FUNC_ATTR_MAX: highest NAN function attribute
+ */
+enum nl80211_nan_func_attributes {
+ __NL80211_NAN_FUNC_INVALID,
+ NL80211_NAN_FUNC_TYPE,
+ NL80211_NAN_FUNC_SERVICE_ID,
+ NL80211_NAN_FUNC_PUBLISH_TYPE,
+ NL80211_NAN_FUNC_PUBLISH_BCAST,
+ NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE,
+ NL80211_NAN_FUNC_FOLLOW_UP_ID,
+ NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID,
+ NL80211_NAN_FUNC_FOLLOW_UP_DEST,
+ NL80211_NAN_FUNC_CLOSE_RANGE,
+ NL80211_NAN_FUNC_TTL,
+ NL80211_NAN_FUNC_SERVICE_INFO,
+ NL80211_NAN_FUNC_SRF,
+ NL80211_NAN_FUNC_RX_MATCH_FILTER,
+ NL80211_NAN_FUNC_TX_MATCH_FILTER,
+ NL80211_NAN_FUNC_INSTANCE_ID,
+ NL80211_NAN_FUNC_TERM_REASON,
+
+ /* keep last */
+ NUM_NL80211_NAN_FUNC_ATTR,
+ NL80211_NAN_FUNC_ATTR_MAX = NUM_NL80211_NAN_FUNC_ATTR - 1
+};
+
+/**
+ * enum nl80211_nan_srf_attributes - NAN Service Response filter attributes
+ * @__NL80211_NAN_SRF_INVALID: invalid
+ * @NL80211_NAN_SRF_INCLUDE: present if the include bit of the SRF set.
+ * This is a flag.
+ * @NL80211_NAN_SRF_BF: Bloom Filter. Present if and only if
+ * &NL80211_NAN_SRF_MAC_ADDRS isn't present. This attribute is binary.
+ * @NL80211_NAN_SRF_BF_IDX: index of the Bloom Filter. Mandatory if
+ * &NL80211_NAN_SRF_BF is present. This is a u8.
+ * @NL80211_NAN_SRF_MAC_ADDRS: list of MAC addresses for the SRF. Present if
+ * and only if &NL80211_NAN_SRF_BF isn't present. This is a nested
+ * attribute. Each nested attribute is a MAC address.
+ * @NUM_NL80211_NAN_SRF_ATTR: internal
+ * @NL80211_NAN_SRF_ATTR_MAX: highest NAN SRF attribute
+ */
+enum nl80211_nan_srf_attributes {
+ __NL80211_NAN_SRF_INVALID,
+ NL80211_NAN_SRF_INCLUDE,
+ NL80211_NAN_SRF_BF,
+ NL80211_NAN_SRF_BF_IDX,
+ NL80211_NAN_SRF_MAC_ADDRS,
+
+ /* keep last */
+ NUM_NL80211_NAN_SRF_ATTR,
+ NL80211_NAN_SRF_ATTR_MAX = NUM_NL80211_NAN_SRF_ATTR - 1,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 0139872..3799884 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -605,7 +605,8 @@ int wiphy_register(struct wiphy *wiphy)
return -EINVAL;

if (WARN_ON((wiphy->interface_modes & BIT(NL80211_IFTYPE_NAN)) &&
- (!rdev->ops->start_nan || !rdev->ops->stop_nan)))
+ (!rdev->ops->start_nan || !rdev->ops->stop_nan ||
+ !rdev->ops->add_nan_func || !rdev->ops->rm_nan_func)))
return -EINVAL;

/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90580f9..58b3127 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -411,6 +411,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = { .len = ETH_ALEN },
[NL80211_ATTR_NAN_MASTER_PREF] = { .type = NLA_U8 },
[NL80211_ATTR_NAN_DUAL] = { .type = NLA_U8 },
+ [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED },
};

/* policy for the key attributes */
@@ -504,6 +505,39 @@ nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
},
};

+/* policy for NAN function attributes */
+static const struct nla_policy
+nl80211_nan_func_policy[NL80211_NAN_FUNC_ATTR_MAX + 1] = {
+ [NL80211_NAN_FUNC_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_SERVICE_ID] = { .type = NLA_BINARY,
+ .len = NL80211_NAN_FUNC_SERVICE_ID_LEN },
+ [NL80211_NAN_FUNC_PUBLISH_TYPE] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_PUBLISH_BCAST] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_FOLLOW_UP_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_FOLLOW_UP_DEST] = { .len = ETH_ALEN },
+ [NL80211_NAN_FUNC_CLOSE_RANGE] = { .type = NLA_FLAG },
+ [NL80211_NAN_FUNC_TTL] = { .type = NLA_U32 },
+ [NL80211_NAN_FUNC_SERVICE_INFO] = { .type = NLA_BINARY,
+ .len = NL80211_NAN_FUNC_SERVICE_SPEC_INFO_MAX_LEN },
+ [NL80211_NAN_FUNC_SRF] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_RX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_TX_MATCH_FILTER] = { .type = NLA_NESTED },
+ [NL80211_NAN_FUNC_INSTANCE_ID] = { .type = NLA_U8 },
+ [NL80211_NAN_FUNC_TERM_REASON] = { .type = NLA_U8 },
+};
+
+/* policy for Service Response Filter attributes */
+static const struct nla_policy
+nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
+ [NL80211_NAN_SRF_INCLUDE] = { .type = NLA_FLAG },
+ [NL80211_NAN_SRF_BF] = { .type = NLA_BINARY,
+ .len = NL80211_NAN_FUNC_SRF_MAX_LEN },
+ [NL80211_NAN_SRF_BF_IDX] = { .type = NLA_U8 },
+ [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
+};
+
static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct cfg80211_registered_device **rdev,
@@ -10478,6 +10512,324 @@ static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
return 0;
}

+static int validate_nan_filter(struct nlattr *filter_attr)
+{
+ struct nlattr *attr;
+ int len = 0, n_entries = 0, rem;
+
+ nla_for_each_nested(attr, filter_attr, rem) {
+ len += nla_len(attr);
+ n_entries++;
+ }
+
+ if (len >= U8_MAX)
+ return -EINVAL;
+
+ return n_entries;
+}
+
+static int handle_nan_filter(struct nlattr *attr_filter,
+ struct cfg80211_nan_func *func,
+ bool tx)
+{
+ struct nlattr *attr;
+ int n_entries, rem, i;
+ struct cfg80211_nan_func_filter *filter;
+
+ n_entries = validate_nan_filter(attr_filter);
+ if (n_entries < 0)
+ return n_entries;
+
+ BUILD_BUG_ON(sizeof(*func->rx_filters) != sizeof(*func->tx_filters));
+
+ filter = kcalloc(n_entries, sizeof(*func->rx_filters), GFP_KERNEL);
+ if (!filter)
+ return -ENOMEM;
+
+ i = 0;
+ nla_for_each_nested(attr, attr_filter, rem) {
+ filter[i].filter = kmemdup(nla_data(attr), nla_len(attr),
+ GFP_KERNEL);
+ filter[i].len = nla_len(attr);
+ i++;
+ }
+ if (tx) {
+ func->num_tx_filters = n_entries;
+ func->tx_filters = filter;
+ } else {
+ func->num_rx_filters = n_entries;
+ func->rx_filters = filter;
+ }
+
+ return 0;
+}
+
+static int nl80211_nan_add_func(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ struct nlattr *tb[NUM_NL80211_NAN_FUNC_ATTR], *func_attr;
+ struct cfg80211_nan_func *func;
+ struct sk_buff *msg = NULL;
+ void *hdr = NULL;
+ int err = 0;
+
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (!wdev->nan_started)
+ return -ENOTCONN;
+
+ if (!info->attrs[NL80211_ATTR_NAN_FUNC])
+ return -EINVAL;
+
+ if (wdev->owner_nlportid &&
+ wdev->owner_nlportid != genl_info_snd_portid(info))
+ return -ENOTCONN;
+
+ err = nla_parse(tb, NL80211_NAN_FUNC_ATTR_MAX,
+ nla_data(info->attrs[NL80211_ATTR_NAN_FUNC]),
+ nla_len(info->attrs[NL80211_ATTR_NAN_FUNC]),
+ nl80211_nan_func_policy);
+ if (err)
+ return err;
+
+ func = kzalloc(sizeof(*func), GFP_KERNEL);
+ if (!func)
+ return -ENOMEM;
+
+ func->cookie = wdev->wiphy->cookie_counter++;
+
+ if (!tb[NL80211_NAN_FUNC_TYPE] ||
+ nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]) > NL80211_NAN_FUNC_MAX_TYPE) {
+ err = -EINVAL;
+ goto out;
+ }
+
+
+ func->type = nla_get_u8(tb[NL80211_NAN_FUNC_TYPE]);
+
+ if (!tb[NL80211_NAN_FUNC_SERVICE_ID]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memcpy(func->service_id, nla_data(tb[NL80211_NAN_FUNC_SERVICE_ID]),
+ sizeof(func->service_id));
+
+ func->close_range =
+ nla_get_flag(tb[NL80211_NAN_FUNC_CLOSE_RANGE]);
+
+ if (tb[NL80211_NAN_FUNC_SERVICE_INFO]) {
+ func->serv_spec_info_len =
+ nla_len(tb[NL80211_NAN_FUNC_SERVICE_INFO]);
+ func->serv_spec_info =
+ kmemdup(nla_data(tb[NL80211_NAN_FUNC_SERVICE_INFO]),
+ func->serv_spec_info_len,
+ GFP_KERNEL);
+ if (!func->serv_spec_info) {
+ err = -ENOMEM;
+ goto out;
+ }
+ }
+
+ if (tb[NL80211_NAN_FUNC_TTL])
+ func->ttl = nla_get_u32(tb[NL80211_NAN_FUNC_TTL]);
+
+ switch (func->type) {
+ case NL80211_NAN_FUNC_PUBLISH:
+ if (!tb[NL80211_NAN_FUNC_PUBLISH_TYPE]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ func->publish_type =
+ nla_get_u8(tb[NL80211_NAN_FUNC_PUBLISH_TYPE]);
+ func->publish_bcast =
+ nla_get_flag(tb[NL80211_NAN_FUNC_PUBLISH_BCAST]);
+
+ if ((!(func->publish_type & NL80211_NAN_SOLICITED_PUBLISH)) &&
+ func->publish_bcast) {
+ err = -EINVAL;
+ goto out;
+ }
+ break;
+ case NL80211_NAN_FUNC_SUBSCRIBE:
+ func->subscribe_active =
+ nla_get_flag(tb[NL80211_NAN_FUNC_SUBSCRIBE_ACTIVE]);
+ break;
+ case NL80211_NAN_FUNC_FOLLOW_UP:
+ if (!tb[NL80211_NAN_FUNC_FOLLOW_UP_ID] ||
+ !tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ func->followup_id =
+ nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_ID]);
+ func->followup_reqid =
+ nla_get_u8(tb[NL80211_NAN_FUNC_FOLLOW_UP_REQ_ID]);
+ memcpy(func->followup_dest.addr,
+ nla_data(tb[NL80211_NAN_FUNC_FOLLOW_UP_DEST]),
+ sizeof(func->followup_dest.addr));
+ if (func->ttl) {
+ err = -EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (tb[NL80211_NAN_FUNC_SRF]) {
+ struct nlattr *srf_tb[NUM_NL80211_NAN_SRF_ATTR];
+
+ err = nla_parse(srf_tb, NL80211_NAN_SRF_ATTR_MAX,
+ nla_data(tb[NL80211_NAN_FUNC_SRF]),
+ nla_len(tb[NL80211_NAN_FUNC_SRF]), NULL);
+ if (err)
+ goto out;
+
+ func->srf_include =
+ nla_get_flag(srf_tb[NL80211_NAN_SRF_INCLUDE]);
+
+ if (srf_tb[NL80211_NAN_SRF_BF]) {
+ if (srf_tb[NL80211_NAN_SRF_MAC_ADDRS] ||
+ !srf_tb[NL80211_NAN_SRF_BF_IDX]) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ func->srf_bf_len =
+ nla_len(srf_tb[NL80211_NAN_SRF_BF]);
+ func->srf_bf =
+ kmemdup(nla_data(srf_tb[NL80211_NAN_SRF_BF]),
+ func->srf_bf_len, GFP_KERNEL);
+ if (!func->srf_bf) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ func->srf_bf_idx =
+ nla_get_u8(srf_tb[NL80211_NAN_SRF_BF_IDX]);
+ } else {
+ struct nlattr *attr, *mac_attr =
+ srf_tb[NL80211_NAN_SRF_MAC_ADDRS];
+ int n_entries, rem, i = 0;
+
+ if (!mac_attr) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ n_entries = validate_acl_mac_addrs(mac_attr);
+ if (n_entries <= 0) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ func->srf_num_macs = n_entries;
+ func->srf_macs =
+ kzalloc(sizeof(*func->srf_macs) * n_entries,
+ GFP_KERNEL);
+ if (!func->srf_macs) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ nla_for_each_nested(attr, mac_attr, rem)
+ memcpy(func->srf_macs[i++].addr, nla_data(attr),
+ sizeof(*func->srf_macs));
+ }
+ }
+
+ if (tb[NL80211_NAN_FUNC_TX_MATCH_FILTER]) {
+ err = handle_nan_filter(tb[NL80211_NAN_FUNC_TX_MATCH_FILTER],
+ func, true);
+ if (err)
+ goto out;
+ }
+
+ if (tb[NL80211_NAN_FUNC_RX_MATCH_FILTER]) {
+ err = handle_nan_filter(tb[NL80211_NAN_FUNC_RX_MATCH_FILTER],
+ func, false);
+ if (err)
+ goto out;
+ }
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ hdr = nl80211hdr_put(msg, genl_info_snd_portid(info), info->snd_seq, 0,
+ NL80211_CMD_ADD_NAN_FUNCTION);
+ /* This can't really happen - we just allocated 4KB */
+ if (WARN_ON(!hdr)) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = rdev_add_nan_func(rdev, wdev, func);
+out:
+ if (err < 0) {
+ cfg80211_free_nan_func(func);
+ nlmsg_free(msg);
+ return err;
+ }
+
+ /* propagate the instance id and cookie to userspace */
+ if (nla_put_u64(msg, NL80211_ATTR_COOKIE, func->cookie))
+ goto nla_put_failure;
+
+ func_attr = nla_nest_start(msg, NL80211_ATTR_NAN_FUNC);
+ if (!func_attr)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL80211_NAN_FUNC_INSTANCE_ID,
+ func->instance_id))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, func_attr);
+
+ genlmsg_end(msg, hdr);
+ return genlmsg_reply(msg, info);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+
+static int nl80211_nan_rm_func(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct wireless_dev *wdev = info->user_ptr[1];
+ u64 cookie;
+
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
+ return -EOPNOTSUPP;
+
+ if (!wdev->nan_started)
+ return -ENOTCONN;
+
+ if (!info->attrs[NL80211_ATTR_COOKIE])
+ return -EINVAL;
+
+ if (wdev->owner_nlportid &&
+ wdev->owner_nlportid != genl_info_snd_portid(info))
+ return -ENOTCONN;
+
+ cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]);
+
+ rdev_rm_nan_func(rdev, wdev, cookie);
+
+ return 0;
+}
+
static int nl80211_get_protocol_features(struct sk_buff *skb,
struct genl_info *info)
{
@@ -11836,6 +12188,22 @@ static const struct genl_ops nl80211_ops[] = {
NL80211_FLAG_NEED_RTNL,
},
{
+ .cmd = NL80211_CMD_ADD_NAN_FUNCTION,
+ .doit = nl80211_nan_add_func,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_RM_NAN_FUNCTION,
+ .doit = nl80211_nan_rm_func,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
.cmd = NL80211_CMD_SET_MCAST_RATE,
.doit = nl80211_set_mcast_rate,
.policy = nl80211_policy,
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index afb68a8..f42acf4 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -907,6 +907,27 @@ static inline void rdev_stop_nan(struct cfg80211_registered_device *rdev,
trace_rdev_return_void(&rdev->wiphy);
}

+static inline int
+rdev_add_nan_func(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev,
+ struct cfg80211_nan_func *nan_func)
+{
+ int ret;
+
+ trace_rdev_add_nan_func(&rdev->wiphy, wdev, nan_func);
+ ret = rdev->ops->add_nan_func(&rdev->wiphy, wdev, nan_func);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
+static inline void rdev_rm_nan_func(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, u64 cookie)
+{
+ trace_rdev_rm_nan_func(&rdev->wiphy, wdev, cookie);
+ rdev->ops->rm_nan_func(&rdev->wiphy, wdev, cookie);
+ trace_rdev_return_void(&rdev->wiphy);
+}
+
static inline int rdev_set_mac_acl(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_acl_data *params)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5f3370f..4845fe4 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1916,6 +1916,45 @@ DEFINE_EVENT(wiphy_wdev_evt, rdev_stop_nan,
TP_ARGS(wiphy, wdev)
);

+TRACE_EVENT(rdev_add_nan_func,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ const struct cfg80211_nan_func *func),
+ TP_ARGS(wiphy, wdev, func),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u8, func_type)
+ __field(u64, cookie)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->func_type = func->type;
+ __entry->cookie = func->cookie
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", type=%u, cookie=%llu",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->func_type,
+ __entry->cookie)
+);
+
+TRACE_EVENT(rdev_rm_nan_func,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ u64 cookie),
+ TP_ARGS(wiphy, wdev, cookie),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(u64, cookie)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->cookie = cookie;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", cookie=%llu",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->cookie)
+);
+
TRACE_EVENT(rdev_set_mac_acl,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_acl_data *params),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 91868e0..91bae35 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1762,6 +1762,28 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
}
EXPORT_SYMBOL(cfg80211_get_station);

+void cfg80211_free_nan_func(struct cfg80211_nan_func *f)
+{
+ int i;
+
+ if (!f)
+ return;
+
+ kfree(f->serv_spec_info);
+ kfree(f->srf_bf);
+ kfree(f->srf_macs);
+ for (i = 0; i < f->num_rx_filters; i++)
+ kfree(f->rx_filters[i].filter);
+
+ for (i = 0; i < f->num_tx_filters; i++)
+ kfree(f->tx_filters[i].filter);
+
+ kfree(f->rx_filters);
+ kfree(f->tx_filters);
+ kfree(f);
+}
+EXPORT_SYMBOL(cfg80211_free_nan_func);
+
/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
const unsigned char rfc1042_header[] __aligned(2) =
--
2.9.3

2016-09-19 08:10:02

by Andrei Otcheretianski

[permalink] [raw]
Subject: RE: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func

> -----Original Message-----
> From: Arend Van Spriel [mailto:[email protected]]
> Sent: Sunday, September 18, 2016 22:54
> To: Luca Coelho <[email protected]>; [email protected]
> Cc: [email protected]; Beker, Ayala <[email protected]>;
> Otcheretianski, Andrei <[email protected]>; Grumbach,
> Emmanuel <[email protected]>; Coelho, Luciano
> <[email protected]>
> Subject: Re: [PATCH v2 3/9] cfg80211: add add_nan_func / rm_nan_func
>
> On 16-9-2016 10:33, Luca Coelho wrote:
> > From: Ayala Beker <[email protected]>
> >
> > A NAN function can be either publish, subscribe or follow up. Make all
> > the necessary verifications and just pass the request to the driver.
> > Allow the user space application that starts NAN to forbid any other
> > socket to add or remove functions.
> >
> > Signed-off-by: Andrei Otcheretianski <[email protected]>
> > Signed-off-by: Emmanuel Grumbach <[email protected]>
> > Signed-off-by: Ayala Beker <[email protected]>
> > Signed-off-by: Luca Coelho <[email protected]>
> > ---
>
> [...]
>
> > diff --git a/include/uapi/linux/nl80211.h
> > b/include/uapi/linux/nl80211.h index 7ab18c8..ab16c8e 100644
> > --- a/include/uapi/linux/nl80211.h
> > +++ b/include/uapi/linux/nl80211.h
> > @@ -847,6 +847,24 @@
> > * After this command NAN functions can be added.
> > * @NL80211_CMD_STOP_NAN: Stop the NAN operation, identified by
> > * its %NL80211_ATTR_WDEV interface.
> > + * @NL80211_CMD_ADD_NAN_FUNCTION: Add a NAN function. The
> function is defined
> > + * with %NL80211_ATTR_NAN_FUNC nested attribute. When called,
> this
> > + * operation returns the strictly positive and unique instance id
> > + * (%NL80211_ATTR_NAN_FUNC_INST_ID) and a cookie
> (%NL80211_ATTR_COOKIE)
> > + * of the function upon success.
> > + * Since instance ID's can be re-used, this cookie is the right
> > + * way to identify the function. This will avoid races when a termination
> > + * event is handled by the user space after it has already added a new
> > + * function that got the same instance id from the kernel as the one
> > + * which just terminated.
> > + * This cookie may be used in NAN events even before the command
> > + * returns, so userspace shouldn't process NAN events until it
> processes
> > + * the response to this command.
> > + * Look at %NL80211_ATTR_SOCKET_OWNER as well.
> > + * @NL80211_CMD_RM_NAN_FUNCTION: Remove a NAN function by
> cookie.
> > + * This command is also used as a notification sent when a NAN function
> is
> > + * terminated. This will contain a %NL80211_ATTR_NAN_FUNC_INST_ID
> > + * and %NL80211_ATTR_COOKIE attributes.
>
> This patch does not show the notification scenario as it is added in patch 6. So
> those three lines could be added by that patch instead to keep things
> logically together.
>

Good point. Thanks

> Regards,
> Arend