From patchwork Sun Jun 22 22:24:40 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 899189 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 66DDE6136 for ; Sun, 22 Jun 2025 22:25:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631143; cv=none; b=uUl8TSwnII9ARdjw03xweWxri319Vukd8jNl5yyCpEbFHjN9F5jnltD4Rnctj9oTLPQavuEqjsZh1K2vCyV7k3eaBYY53IgKerQ/w0U/BWLsrVAomJNR+rwgweW4Z++WrlUvQzaO2icVQ+EM83xfj6R5bS9653TnkrfZx8HGi1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631143; c=relaxed/simple; bh=O9xcSX1fGuJ/1JQTH8RqEJf21arbJJSeVL96gwjkBVY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cMp86belfCAQfL+xCwlaYQoOlhh19/va/n3cF/pWbQStrkp1voNyg/g1tgJ4EWbuTxnpzRluOv/N4POasEECiZU3clWkfXu+I0KTqZmW/PbzsOLnI8j+D7h6QLL8MQOCwEHZ9fB2Tgdmeyc+ndx2dpENE4JOcKbS3RpB7VFkGqg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=O1F4p4fv; arc=none smtp.client-ip=198.175.65.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="O1F4p4fv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750631142; x=1782167142; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=O9xcSX1fGuJ/1JQTH8RqEJf21arbJJSeVL96gwjkBVY=; b=O1F4p4fvcMPMTxPgXCR6xakpeB0F3zfR90PkIT0W5mxz2eMruAnO0rDu w3WNxGPkPvCe3CS5gdD83bbWSUWQquwDwO7g8gJqNPJLEuwcqsIN/14HQ 0BeA6XdRqXOTDcjU5f+GiRw3bnOPjLiD02BRLrHn5f9kF5ovWUyBrrnnu O7G5pJrto7BtNgZAsDNtm6XIQ4z+OLoDcpRVUI0OwLvh6IO9d/CyMQxRf g+VJcaWZYb2vNveKDKWTJO/G4K+0AfffbUmG+zJOFENsreEzvZTJkuvH8 UGQQ4e3W9jw5Kmm9feb6ts0lWjXZ7hjzlDIm3dHzthKibYNZvJ1u8SKWG Q==; X-CSE-ConnectionGUID: 016KO40ES7uI72X1fjLe4A== X-CSE-MsgGUID: q1YL8C7dS+SuCR6NAvv3Mw== X-IronPort-AV: E=McAfee;i="6800,10657,11472"; a="52916075" X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="52916075" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:25:41 -0700 X-CSE-ConnectionGUID: 2o8dlnmXSNqV0XdmQUdOYA== X-CSE-MsgGUID: deU7yTJtQIaRUKzuGT1Msw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="182295626" Received: from aotchere-mobl1.ger.corp.intel.com (HELO localhost.localdomain) ([10.245.248.120]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:25:38 -0700 From: Andrei Otcheretianski To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Andrei Otcheretianski Subject: [RFC 1/5] wifi: nl80211: Add more configuration options for NAN commands Date: Mon, 23 Jun 2025 01:24:40 +0300 Message-ID: <20250622222444.356435-2-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622222444.356435-1-andrei.otcheretianski@intel.com> References: <20250622222444.356435-1-andrei.otcheretianski@intel.com> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Current NAN API's have only basic configuration for master preference and operating bands. Add and parse additional parameters which provide more control for NAN synchronization. The newly added attributes allow to publish additional NAN attributes and vendor elements in NAN beacons, control scan and discovery beacons periodicity, enable/disable DW notifications etc. Signed-off-by: Andrei Otcheretianski --- include/net/cfg80211.h | 71 +++++++++ include/uapi/linux/nl80211.h | 94 +++++++++++- net/wireless/nl80211.c | 289 ++++++++++++++++++++++++++++++----- 3 files changed, 415 insertions(+), 39 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 47b4235eea59..b3d3b039c913 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -3758,6 +3758,30 @@ struct cfg80211_qos_map { struct cfg80211_dscp_range up[8]; }; +/** + * struct cfg80211_nan_band_config - NAN band specific configuration + * + * @chan: Pointer to the IEEE 802.11 channel structure. The channel to be used + * for NAN operations on this band. For 2.4 GHz band, this is always + * channel 6. For 5 GHz band, the channel is either 44 or 149, according + * to the regulatory constraints. + * @rssi_close: RSSI close threshold used for NAN master selection. If not + * specified (set to 0), default device value is used. The value should + * be greater than -60 dBm (unsigned). + * @rssi_middle: RSSI middle threshold used for NAN master selection. If not + * specified (set to 0), default device value is used. The value should be + * greater than -75 dBm and less than rssi_close. + * @awake_dw_interval: Committed DW interval. Valid values range: 0-5. 0 + * indicates no wakeup for DW and can't be used on 2.4GHz band, otherwise + * 2^(n-1). + */ +struct cfg80211_nan_band_config { + struct ieee80211_channel *chan; + u8 rssi_close; + u8 rssi_middle; + u8 awake_dw_interval; +}; + /** * struct cfg80211_nan_conf - NAN configuration * @@ -3767,10 +3791,35 @@ struct cfg80211_qos_map { * @bands: operating bands, a bitmap of &enum nl80211_band values. * For instance, for NL80211_BAND_2GHZ, bit 0 would be set * (i.e. BIT(NL80211_BAND_2GHZ)). + * @cluster_id: cluster ID used for NAN synchronization + * @scan_period: period (in seconds) between NAN scans. + * @scan_dwell_time: dwell time (in milliseconds) for NAN scans. + * @discovery_beacon_interval: interval (in TUs) for discovery beacons. + * @enable_dw_notification: flag to enable/disable discovery window + * notifications. + * @low_band_cfg: configuration for the low band. + * @high_band_cfg: configuration for the high band. + * @enable_scan: Flag to enable or disable scanning on 5 GHz band. + * @extra_nan_attrs: pointer to additional NAN attributes. + * @extra_nan_attrs_len: length of the additional NAN attributes. + * @vendor_elems: pointer to vendor-specific elements. + * @vendor_elems_len: length of the vendor-specific elements. */ struct cfg80211_nan_conf { u8 master_pref; u8 bands; + u16 cluster_id; + u16 scan_period; + u16 scan_dwell_time; + u16 discovery_beacon_interval; + bool enable_dw_notification; + struct cfg80211_nan_band_config low_band_cfg; + struct cfg80211_nan_band_config high_band_cfg; + bool enable_hb_scan; + u8 *extra_nan_attrs; + size_t extra_nan_attrs_len; + u8 *vendor_elems; + size_t vendor_elems_len; }; /** @@ -3779,10 +3828,32 @@ struct cfg80211_nan_conf { * * @CFG80211_NAN_CONF_CHANGED_PREF: master preference * @CFG80211_NAN_CONF_CHANGED_BANDS: operating bands + * @CFG80211_NAN_CONF_CHANGED_CLUSTER_ID: cluster ID + * @CFG80211_NAN_CONF_CHANGED_SCAN_PERIOD: scan period + * @CFG80211_NAN_CONF_CHANGED_SCAN_DWELL_TIME: scan dwell time + * @CFG80211_NAN_CONF_CHANGED_DISCOVERY_BEACON_INTERVAL: discovery beacon + * interval + * @CFG80211_NAN_CONF_CHANGED_ENABLE_DW_NOTIFICATION: enable DW notification + * @CFG80211_NAN_CONF_CHANGED_AWAKE_DW_INTERVALs: awake DW intervals (both + * bands) + * @CFG80211_NAN_CONF_CHANGED_RSSI_THOLDS: RSSI thresholds (both bands) + * @CFG80211_NAN_CONF_CHANGED_ENABLE_HB_SCAN: enable high band scan + * @CFG80211_NAN_CONF_CHANGED_EXTRA_ATTRS: extra attributes + * @CFG80211_NAN_CONF_CHANGED_VENDOR_ELEMS: vendor elements */ enum cfg80211_nan_conf_changes { CFG80211_NAN_CONF_CHANGED_PREF = BIT(0), CFG80211_NAN_CONF_CHANGED_BANDS = BIT(1), + CFG80211_NAN_CONF_CHANGED_CLUSTER_ID = BIT(2), + CFG80211_NAN_CONF_CHANGED_SCAN_PERIOD = BIT(3), + CFG80211_NAN_CONF_CHANGED_SCAN_DWELL_TIME = BIT(4), + CFG80211_NAN_CONF_CHANGED_DISCOVERY_BEACON_INTERVAL = BIT(5), + CFG80211_NAN_CONF_CHANGED_ENABLE_DW_NOTIFICATION = BIT(6), + CFG80211_NAN_CONF_CHANGED_AWAKE_DW_INTERVALS = BIT(7), + CFG80211_NAN_CONF_CHANGED_RSSI_THOLDS = BIT(8), + CFG80211_NAN_CONF_CHANGED_ENABLE_HB_SCAN = BIT(9), + CFG80211_NAN_CONF_CHANGED_EXTRA_ATTRS = BIT(10), + CFG80211_NAN_CONF_CHANGED_VENDOR_ELEMS = BIT(11), }; /** diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index a289014abe37..a68c486e2083 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1085,8 +1085,9 @@ * %NL80211_ATTR_NAN_MASTER_PREF attribute and optional * %NL80211_ATTR_BANDS attributes. If %NL80211_ATTR_BANDS is * omitted or set to 0, it means don't-care and the device will - * decide what to use. After this command NAN functions can be - * added. + * decide what to use. Additional cluster configuration may be + * optionally provided with %NL80211_ATTR_NAN_CONFIG. + * 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 @@ -1115,6 +1116,8 @@ * current configuration is not changed. If it is present but * set to zero, the configuration is changed to don't-care * (i.e. the device can decide what to do). + * Additional parameters may be provided with + * %NL80211_ATTR_NAN_CONFIG. * @NL80211_CMD_NAN_MATCH: Notification sent when a match is reported. * This will contain a %NL80211_ATTR_NAN_MATCH nested attribute and * %NL80211_ATTR_COOKIE. @@ -2907,6 +2910,12 @@ enum nl80211_commands { * APs Support". Drivers may set additional flags that they support * in the kernel or device. * + * @NL80211_ATTR_NAN_CONFIG: Nested attribute for + * extended NAN cluster configuration. This is used with + * %NL80211_CMD_START_NAN and %NL80211_CMD_CHANGE_NAN_CONFIG. + * See &enum nl80211_nan_conf_attributes for details. + * This attribute is optional. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -3464,6 +3473,7 @@ enum nl80211_attrs { NL80211_ATTR_ASSOC_MLD_EXT_CAPA_OPS, + NL80211_ATTR_NAN_CONFIG, /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -7252,6 +7262,86 @@ enum nl80211_nan_match_attributes { NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1 }; +/** + * enum nl80211_nan_band_conf_attributes - NAN band configuration attributes + * @__NL80211_NAN_BAND_CONF_INVALID: Invalid. + * @NL80211_NAN_BAND_CONF_CHAN: Discovery channel. Ignored on 2.4GHz band. + * Either 44 or 149 for 5 GHz band. + * @NL80211_NAN_BAND_CONF_RSSI_CLOSE: RSSI close for NAN cluster state changes. + * This is unsigned 8-bit value in dBm (absolute value). + * @NL80211_NAN_BAND_CONF_RSSI_MIDDLE: RSSI middle for NAN cluster state + * changes. This is unsigned 8-bit value in dBm (absolute value). + * @NL80211_NAN_BAND_CONF_WAKE_DW: Committed DW information (values 0-5). + * Value 0 means that the device will not wake up during the + * discovery window. Values 1-5 mean that the device will wake up + * during each 2^(n - 1) discovery window, where n is the value of + * this attribute. Setting this attribute to 0 is not allowed on + * 2.4 GHz band. + * @NUM_NL80211_NAN_BAND_CONF_ATTR: Internal. + * @NL80211_NAN_BAND_CONF_ATTR_MAX: Highest NAN band configuration attribute. + * + * These attributes are used to configure NAN band-specific parameters. Note, + * that both RSSI attributes should be configured (or both left unset), while + * RSSI close should be higher than (>) -65 dBm and RSSI middle should be + * below the RSSI close value but not lower than (>=) -75 dBm. + */ +enum nl80211_nan_band_conf_attributes { + __NL80211_NAN_BAND_CONF_INVALID, + NL80211_NAN_BAND_CONF_CHAN, + NL80211_NAN_BAND_CONF_RSSI_CLOSE, + NL80211_NAN_BAND_CONF_RSSI_MIDDLE, + NL80211_NAN_BAND_CONF_WAKE_DW, + + /* keep last */ + NUM_NL80211_NAN_BAND_CONF_ATTR, + NL80211_NAN_BAND_CONF_ATTR_MAX = NUM_NL80211_NAN_BAND_CONF_ATTR - 1, +}; + +/** + * enum nl80211_nan_conf_attributes - NAN configuration attributes + * @__NL80211_NAN_CONF_INVALID: Invalid attribute, used for validation. + * @NL80211_NAN_CONF_CLUSTER_ID: ID for the NAN cluster. + * @NL80211_NAN_CONF_EXTRA_ATTRS: Additional NAN attributes to be + * published in the beacons. (optional) + * @NL80211_NAN_CONF_VENDOR_ELEMS: Vendor-specific elements that will + * be published in the beacons. (optional) + * @NL80211_NAN_CONF_2GHZ_CONFIG: Configuration for the 2.4 GHz band. + * @NL80211_NAN_CONF_5GHZ_CONFIG: Configuration for the 5 GHz band. + * @NL80211_NAN_CONF_SCAN_PERIOD: Scan period in seconds. + * Zero value will disable scanning. + * @NL80211_NAN_CONF_SCAN_DWELL_TIME: Scan dwell time in TUs per channel. + * Only non-zero values are valid. The optimal value depends on the + * the discovery beacon interval of other devices in the cluster. + * @NL80211_NAN_CONF_ENABLE_HB_SCAN: If set, the device will enable scan on + * 5 GHz. + * @NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL: Discovery beacon interval + * in TUs. Valid range is 50-200 TUs. + * @NL80211_NAN_CONF_NOTIFY_DW: If set, the driver will notify userspace about + * the upcoming discovery window with + * %NL80211_CMD_NAN_NEXT_DW_NOTIFICATION. + * @NUM_NL80211_NAN_CONF_ATTR: Internal. + * @NL80211_NAN_CONF_ATTR_MAX: Highest NAN configuration attribute. + * + * These attributes are used to configure NAN-specific parameters. + */ +enum nl80211_nan_conf_attributes { + __NL80211_NAN_CONF_INVALID, + NL80211_NAN_CONF_CLUSTER_ID, + NL80211_NAN_CONF_EXTRA_ATTRS, + NL80211_NAN_CONF_VENDOR_ELEMS, + NL80211_NAN_CONF_2GHZ_CONFIG, + NL80211_NAN_CONF_5GHZ_CONFIG, + NL80211_NAN_CONF_SCAN_PERIOD, + NL80211_NAN_CONF_SCAN_DWELL_TIME, + NL80211_NAN_CONF_ENABLE_HB_SCAN, + NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL, + NL80211_NAN_CONF_NOTIFY_DW, + + /* keep last */ + NUM_NL80211_NAN_CONF_ATTR, + NL80211_NAN_CONF_ATTR_MAX = NUM_NL80211_NAN_CONF_ATTR - 1, +}; + /** * enum nl80211_external_auth_action - Action to perform with external * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION. diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 85f139016da2..6727580c0a50 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -479,6 +479,28 @@ nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, }; +static const struct nla_policy +nl80211_nan_band_conf_policy[NL80211_NAN_BAND_CONF_ATTR_MAX + 1] = { + [NL80211_NAN_BAND_CONF_CHAN] = { .type = NLA_U8 }, + [NL80211_NAN_BAND_CONF_RSSI_CLOSE] = { .type = NLA_U8 }, + [NL80211_NAN_BAND_CONF_RSSI_MIDDLE] = { .type = NLA_U8 }, + [NL80211_NAN_BAND_CONF_WAKE_DW] = { .type = NLA_U8}, +}; + +static const struct nla_policy +nl80211_nan_conf_policy[NL80211_NAN_CONF_ATTR_MAX + 1] = { + [NL80211_NAN_CONF_CLUSTER_ID] = NLA_POLICY_MIN(NLA_U16, 1), + [NL80211_NAN_CONF_EXTRA_ATTRS] = { .type = NLA_BINARY }, + [NL80211_NAN_CONF_VENDOR_ELEMS] = { .type = NLA_BINARY }, + [NL80211_NAN_CONF_2GHZ_CONFIG] = NLA_POLICY_NESTED(nl80211_nan_band_conf_policy), + [NL80211_NAN_CONF_5GHZ_CONFIG] = NLA_POLICY_NESTED(nl80211_nan_band_conf_policy), + [NL80211_NAN_CONF_SCAN_PERIOD] = { .type = NLA_U16 }, + [NL80211_NAN_CONF_SCAN_DWELL_TIME] = NLA_POLICY_RANGE(NLA_U16, 50, 512), + [NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL] = NLA_POLICY_RANGE(NLA_U16, 50, 200), + [NL80211_NAN_CONF_NOTIFY_DW] = { .type = NLA_FLAG }, + [NL80211_NAN_CONF_ENABLE_HB_SCAN] = { .type = NLA_FLAG }, +}; + static const struct netlink_range_validation nl80211_punct_bitmap_range = { .min = 0, .max = 0xffff, @@ -748,6 +770,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { [NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR] = NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN), [NL80211_ATTR_NAN_MASTER_PREF] = NLA_POLICY_MIN(NLA_U8, 1), [NL80211_ATTR_BANDS] = { .type = NLA_U32 }, + [NL80211_ATTR_NAN_CONFIG] = NLA_POLICY_NESTED(nl80211_nan_conf_policy), [NL80211_ATTR_NAN_FUNC] = { .type = NLA_NESTED }, [NL80211_ATTR_FILS_KEK] = { .type = NLA_BINARY, .len = FILS_MAX_KEK_LEN }, @@ -14483,40 +14506,249 @@ 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) +static bool nl80211_valid_nan_freq(struct wiphy *wiphy, int freq) { - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct wireless_dev *wdev = info->user_ptr[1]; - struct cfg80211_nan_conf conf = {}; + struct ieee80211_channel *chan; + struct cfg80211_chan_def def; + + /* Check if the frequency is valid for NAN */ + if (freq != 2437 && freq != 5220 && freq != 5745) + return false; + + chan = ieee80211_get_channel(wiphy, freq); + if (!chan) + return false; + + cfg80211_chandef_create(&def, chan, NL80211_CHAN_NO_HT); + + /* Check if the channel is allowed */ + if (!cfg80211_reg_can_beacon(wiphy, &def, NL80211_IFTYPE_NAN)) + return false; + + return true; +} + +static int nl80211_parse_nan_band_config(struct wiphy *wiphy, + struct nlattr *attr, + struct cfg80211_nan_band_config *cfg, + u32 *changed, struct genl_info *info, + enum nl80211_band band) +{ + struct nlattr *tb[NL80211_NAN_BAND_CONF_ATTR_MAX + 1]; int err; - if (wdev->iftype != NL80211_IFTYPE_NAN) - return -EOPNOTSUPP; + err = nla_parse_nested(tb, NL80211_NAN_BAND_CONF_ATTR_MAX, attr, NULL, + info->extack); + if (err) + return err; - if (wdev_running(wdev)) - return -EEXIST; + if (tb[NL80211_NAN_BAND_CONF_CHAN]) { + u8 ch = nla_get_u8(tb[NL80211_NAN_BAND_CONF_CHAN]); + int freq = ieee80211_channel_to_frequency(ch, band); - if (rfkill_blocked(rdev->wiphy.rfkill)) - return -ERFKILL; + if (!nl80211_valid_nan_freq(wiphy, freq)) + return -EINVAL; - if (!info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) - return -EINVAL; + cfg->chan = ieee80211_get_channel(wiphy, freq); + } - conf.master_pref = - nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); + if (tb[NL80211_NAN_BAND_CONF_RSSI_CLOSE]) { + cfg->rssi_close = + nla_get_u8(tb[NL80211_NAN_BAND_CONF_RSSI_CLOSE]); + if (cfg->rssi_close > 60 || + !tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]) + return -EINVAL; + + *changed |= CFG80211_NAN_CONF_CHANGED_RSSI_THOLDS; + } + + if (tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]) { + cfg->rssi_middle = + nla_get_u8(tb[NL80211_NAN_BAND_CONF_RSSI_MIDDLE]); + if (!cfg->rssi_close || cfg->rssi_middle > 75 || + cfg->rssi_middle <= cfg->rssi_close) + return -EINVAL; + + *changed |= CFG80211_NAN_CONF_CHANGED_RSSI_THOLDS; + } + + if (tb[NL80211_NAN_BAND_CONF_WAKE_DW]) { + cfg->awake_dw_interval = + nla_get_u8(tb[NL80211_NAN_BAND_CONF_WAKE_DW]); + if (cfg->awake_dw_interval > 5) + return -EINVAL; + + if (band == NL80211_BAND_2GHZ && cfg->awake_dw_interval == 0) + return -EINVAL; + + *changed |= CFG80211_NAN_CONF_CHANGED_AWAKE_DW_INTERVALS; + } + + return 0; +} + +static int nl80211_parse_nan_conf(struct wiphy *wiphy, + struct genl_info *info, + struct cfg80211_nan_conf *conf, + u32 *changed) +{ + struct nlattr *attrs[NL80211_NAN_CONF_ATTR_MAX + 1]; + int err; + + if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) { + conf->master_pref = + nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]); + + *changed |= CFG80211_NAN_CONF_CHANGED_PREF; + } if (info->attrs[NL80211_ATTR_BANDS]) { u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); - if (bands & ~(u32)wdev->wiphy->nan_supported_bands) + if (bands & ~(u32)wiphy->nan_supported_bands) return -EOPNOTSUPP; if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) return -EINVAL; - conf.bands = bands; + conf->bands = bands; + *changed |= CFG80211_NAN_CONF_CHANGED_BANDS; + } + + if (!info->attrs[NL80211_ATTR_NAN_CONFIG]) + return 0; + + err = nla_parse_nested(attrs, NL80211_NAN_CONF_ATTR_MAX, + info->attrs[NL80211_ATTR_NAN_CONFIG], NULL, + info->extack); + if (err) + return err; + + if (attrs[NL80211_NAN_CONF_CLUSTER_ID]) { + conf->cluster_id = + nla_get_u8(attrs[NL80211_NAN_CONF_CLUSTER_ID]); + *changed |= CFG80211_NAN_CONF_CHANGED_CLUSTER_ID; + } + + if (attrs[NL80211_NAN_CONF_EXTRA_ATTRS]) { + conf->extra_nan_attrs = + nla_data(attrs[NL80211_NAN_CONF_EXTRA_ATTRS]); + conf->extra_nan_attrs_len = + nla_len(attrs[NL80211_NAN_CONF_EXTRA_ATTRS]); + *changed |= CFG80211_NAN_CONF_CHANGED_EXTRA_ATTRS; + } + + if (attrs[NL80211_NAN_CONF_VENDOR_ELEMS]) { + conf->vendor_elems = + nla_data(attrs[NL80211_NAN_CONF_VENDOR_ELEMS]); + conf->vendor_elems_len = + nla_len(attrs[NL80211_NAN_CONF_VENDOR_ELEMS]); + *changed |= CFG80211_NAN_CONF_CHANGED_VENDOR_ELEMS; + } + + conf->low_band_cfg.awake_dw_interval = 1; + + if (conf->bands & BIT(NL80211_BAND_5GHZ)) + conf->high_band_cfg.awake_dw_interval = 1; + + if (attrs[NL80211_NAN_CONF_2GHZ_CONFIG]) { + err = nl80211_parse_nan_band_config(wiphy, + attrs[NL80211_NAN_CONF_2GHZ_CONFIG], + &conf->low_band_cfg, + changed, info, + NL80211_BAND_2GHZ); + if (err) + return err; + } + + if (!conf->low_band_cfg.chan) { + /* If no 2GHz channel is specified, use the default */ + conf->low_band_cfg.chan = + ieee80211_get_channel(wiphy, 2437); + if (!conf->low_band_cfg.chan || + !nl80211_valid_nan_freq(wiphy, 2437)) + return -EINVAL; + } + + /* If the user configured 5 GHz channel use it or fail */ + if (attrs[NL80211_NAN_CONF_5GHZ_CONFIG]) { + err = nl80211_parse_nan_band_config(wiphy, + attrs[NL80211_NAN_CONF_5GHZ_CONFIG], + &conf->high_band_cfg, + changed, info, + NL80211_BAND_5GHZ); + if (err) + return err; + } + + if (!conf->high_band_cfg.chan) { + /* If no 5GHz channel is specified use default, if possible */ + if (nl80211_valid_nan_freq(wiphy, 5745)) { + conf->high_band_cfg.chan = + ieee80211_get_channel(wiphy, 5745); + } else if (nl80211_valid_nan_freq(wiphy, 5220)) { + conf->high_band_cfg.chan = + ieee80211_get_channel(wiphy, 5220); + } else { + /* Disable 5GHZ */ + conf->bands &= ~BIT(NL80211_BAND_5GHZ); + } } + if (attrs[NL80211_NAN_CONF_SCAN_PERIOD]) { + conf->scan_period = + nla_get_u16(attrs[NL80211_NAN_CONF_SCAN_PERIOD]); + *changed |= CFG80211_NAN_CONF_CHANGED_SCAN_PERIOD; + } + + if (attrs[NL80211_NAN_CONF_SCAN_DWELL_TIME]) { + conf->scan_dwell_time = + nla_get_u16(attrs[NL80211_NAN_CONF_SCAN_DWELL_TIME]); + *changed |= CFG80211_NAN_CONF_CHANGED_SCAN_DWELL_TIME; + } + + if (attrs[NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL]) { + conf->discovery_beacon_interval = + nla_get_u16(attrs[NL80211_NAN_CONF_DISCOVERY_BEACON_INTERVAL]); + *changed |= CFG80211_NAN_CONF_CHANGED_DISCOVERY_BEACON_INTERVAL; + } + + if (attrs[NL80211_NAN_CONF_NOTIFY_DW]) { + conf->enable_dw_notification = + nla_get_flag(attrs[NL80211_NAN_CONF_NOTIFY_DW]); + *changed |= CFG80211_NAN_CONF_CHANGED_ENABLE_DW_NOTIFICATION; + } + + if (attrs[NL80211_NAN_CONF_ENABLE_HB_SCAN]) { + conf->enable_hb_scan = + nla_get_flag(attrs[NL80211_NAN_CONF_ENABLE_HB_SCAN]); + *changed |= CFG80211_NAN_CONF_CHANGED_ENABLE_HB_SCAN; + } + + 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; + u32 changed = 0; + + if (wdev->iftype != NL80211_IFTYPE_NAN) + return -EOPNOTSUPP; + + if (wdev_running(wdev)) + return -EEXIST; + + if (rfkill_blocked(rdev->wiphy.rfkill)) + return -ERFKILL; + + err = nl80211_parse_nan_conf(&rdev->wiphy, info, &conf, &changed); + if (err) + return err; + err = rdev_start_nan(rdev, wdev, &conf); if (err) return err; @@ -14871,6 +15103,7 @@ static int nl80211_nan_change_config(struct sk_buff *skb, struct wireless_dev *wdev = info->user_ptr[1]; struct cfg80211_nan_conf conf = {}; u32 changed = 0; + int err; if (wdev->iftype != NL80211_IFTYPE_NAN) return -EOPNOTSUPP; @@ -14878,27 +15111,9 @@ static int nl80211_nan_change_config(struct sk_buff *skb, if (!wdev_running(wdev)) 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_BANDS]) { - u32 bands = nla_get_u32(info->attrs[NL80211_ATTR_BANDS]); - - if (bands & ~(u32)wdev->wiphy->nan_supported_bands) - return -EOPNOTSUPP; - - if (bands && !(bands & BIT(NL80211_BAND_2GHZ))) - return -EINVAL; - - conf.bands = bands; - changed |= CFG80211_NAN_CONF_CHANGED_BANDS; - } + err = nl80211_parse_nan_conf(&rdev->wiphy, info, &conf, &changed); + if (err) + return err; if (!changed) return -EINVAL; From patchwork Sun Jun 22 22:24:42 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 899188 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EE10F21C187 for ; Sun, 22 Jun 2025 22:25:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631154; cv=none; b=DKc7LnFjy3VuVHVhPHUIpkoQPpXeVWu7uZexxeUNmpHJRtvLWCUXRHPjvTc8FwmJNusxsqUWHZib46jvcKaMJXp2QmJFIC8Krk7I9BrdMIAuAO7dc60BdQUylXesjc3JMgymnOoBVNrPNvnlJmaUDog9l8q87o+PlafLXg0YiGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631154; c=relaxed/simple; bh=9YD86E+kVFrUWNkttCTRoXa6NGoCuyuoPE4wdZs+VBM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DjU1a12keC8EWamJV2t7UUS1TMinLECHBk+PyBV+qQIWHa+LXInptuk/mi0EwoI1GhtN9Gy+F5hlzS4XO7OkrkXVmlcV87S+UZKb4BL/A7JBgdmemww19QjT+UcHJdcLY1g3rQiQJeG48911cg77RtZdSDopoh9GV0k19hLYUJU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=X3ANjxNa; arc=none smtp.client-ip=198.175.65.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="X3ANjxNa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750631153; x=1782167153; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9YD86E+kVFrUWNkttCTRoXa6NGoCuyuoPE4wdZs+VBM=; b=X3ANjxNaAJ3ZWI9V/+D6zDFxMCKkTTEuJyBaCg/Dvdeqbmqi0zZjfPW9 fL8AAAZ8ytRszY59zAsFrmvOvdJm/URx47DTuZJKODxHIihq8ZB1nTq5S CNk9L2T8E5l/f6rbfRySQMHTvFKnMseOJNFqBEY6u8duWL9tpIkG3iffL ClubI0+0cs12oRRm1Yq/ebPj9bBFBNF7RFq67CowvUHJDj6ErPE+5TBa0 iMnlqBTVkbmdlUU3rHpHkHqO2iTKwpPMjaL99J0YWj17JD5VWsOszJkhB Lq9Q68uWwlyvuWiKV+GmD1xhMS4IBhqsutOsEE0TOeGpryq7p0l/WQCob A==; X-CSE-ConnectionGUID: CODrcW83QLKP+idKLaoY9Q== X-CSE-MsgGUID: Kg3NY0s5ReGCCTVYG+6hOg== X-IronPort-AV: E=McAfee;i="6800,10657,11472"; a="52916082" X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="52916082" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:25:53 -0700 X-CSE-ConnectionGUID: kgbtmvokTI6bZtBBDR5TgQ== X-CSE-MsgGUID: qhjnJ/q+RG2RXa1HKSr0xQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="182295740" Received: from aotchere-mobl1.ger.corp.intel.com (HELO localhost.localdomain) ([10.245.248.120]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:25:51 -0700 From: Andrei Otcheretianski To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Andrei Otcheretianski Subject: [RFC 3/5] wifi: nl80211: Add NAN Discovery Window (DW) notification Date: Mon, 23 Jun 2025 01:24:42 +0300 Message-ID: <20250622222444.356435-4-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622222444.356435-1-andrei.otcheretianski@intel.com> References: <20250622222444.356435-1-andrei.otcheretianski@intel.com> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 This notification will be used by the device to inform user space about upcoming DW. When received, user space will be able to prepare multicast Service Discovery Frames (SDFs) to be transmitted during the next DW using %NL80211_CMD_FRAME command on the NAN management interface. The device/driver will take care to transmit the frames in the correct timing and flush the queues upon the termination of the DW. This allows to implement a synchronized Discovery Engine (DE) in user space, if the device doesn't support DE offload. Note that this notification can be sent before the actual DW starts as long as the driver/device handles the actual timing of the SDF transmission. Signed-off-by: Andrei Otcheretianski --- include/uapi/linux/nl80211.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index f2d4a2007463..134cea046bd0 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1347,6 +1347,11 @@ * control EPCS configuration. Used to notify userland on the current state * of EPCS. * + * @NL80211_CMD_NAN_NEXT_DW_NOTIFICATION: This command is used to notify + * userspace about the next Discovery Window (DW). Userspace may use it + * to prepare frames to be sent in the next DW. %NL80211_ATTR_WIPHY_FREQ + * is used to indicate the frequency of the next DW. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1607,6 +1612,8 @@ enum nl80211_commands { NL80211_CMD_ASSOC_MLO_RECONF, NL80211_CMD_EPCS_CFG, + NL80211_CMD_NAN_NEXT_DW_NOTIFICATION, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ From patchwork Sun Jun 22 22:24:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrei Otcheretianski X-Patchwork-Id: 899187 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 151AD6136 for ; Sun, 22 Jun 2025 22:26:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631163; cv=none; b=IOAvqvlAuHxV+pQeLPxF1iokEqw8U4sPkDOPEdGZJjcEY8mpYZtDt5Hz1w6Nx3YP0WtUZ/BFW9NDh9BELOxvPKWmL4tYvPR11TEtf0TyoHXV2n5SKaT8jRnoRBDMIYEMAjIZxQ8HtTks1+kK77f3+5aiOXtG+g04xwQ0QCFrn9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750631163; c=relaxed/simple; bh=SEoEqatTeW6Q36yIPcmWPbXVgCoYFMgUxZ1N2JQVdzc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Fg0ROaO2xnbGTsQ10rvFjhKT6dQ+e69bUMAZx1cBWbQsnxvwJCzXx9Va/o29REzb1P0exQqRm968j0A2P7JMfBCjGDAxj51GxoCoVzXBAsK5u84fiVX8ZZvoO+bQYeJCwynNjnPONQkyK9ZjDFmAAupKBCLppzjcs+O/TFCJKWc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=H7cve9zj; arc=none smtp.client-ip=198.175.65.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="H7cve9zj" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1750631163; x=1782167163; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SEoEqatTeW6Q36yIPcmWPbXVgCoYFMgUxZ1N2JQVdzc=; b=H7cve9zj+0r652B3Jt13MW30iPCHGECBd1sWVwj+4p3y0aNB1j7Plebe pKO3ac2oxfZK+C1fWr/w0uhSv1Uy4iqRtVGh6Mvbtbe0+5hPx16DbXzoA jqQ15Lvkvha30LTWl5YrSqW4+kTv1/8WXX97lOcAgnAbbjET6Zl8I7rQ6 Udcu09oreRTVhQ/UC+RXl7OzAoTbFnYk9hsfLAzeGjO2Gaa6o4PkZzEyx LAeET5CDJc1+OL2sGrRw8CQpNo5kBVx3BC9EpL5RZYAImRgUjhP4SvHyG YnTbencsua6Nss7JiYLvb/YDUh+fcxMab+g0gHt9CFK7l4Ovsc/MFDzas A==; X-CSE-ConnectionGUID: 9hK6qrkmQ926EOB1tNa0uQ== X-CSE-MsgGUID: DfxGWxrCTlGt5xUapWCQ3g== X-IronPort-AV: E=McAfee;i="6800,10657,11472"; a="52916087" X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="52916087" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:26:02 -0700 X-CSE-ConnectionGUID: YrGxTH/aT7ihHxtsUlLaww== X-CSE-MsgGUID: e0YNJct2SDatoZ4eBwpcEg== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.16,257,1744095600"; d="scan'208";a="182295775" Received: from aotchere-mobl1.ger.corp.intel.com (HELO localhost.localdomain) ([10.245.248.120]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Jun 2025 15:26:00 -0700 From: Andrei Otcheretianski To: johannes@sipsolutions.net Cc: linux-wireless@vger.kernel.org, Andrei Otcheretianski Subject: [RFC 5/5] wifi: cfg80211: Add cluster joined notification API's Date: Mon, 23 Jun 2025 01:24:44 +0300 Message-ID: <20250622222444.356435-6-andrei.otcheretianski@intel.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250622222444.356435-1-andrei.otcheretianski@intel.com> References: <20250622222444.356435-1-andrei.otcheretianski@intel.com> Precedence: bulk X-Mailing-List: linux-wireless@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 The drivers should notify upper layers and user space when a NAN device joins a cluster. This is needed, for example, to set the correct addr3 in SDF frames. Add API to report cluster join event. Signed-off-by: Andrei Otcheretianski --- include/net/cfg80211.h | 14 ++++++++++++ include/uapi/linux/nl80211.h | 9 +++++++- net/wireless/nl80211.c | 43 ++++++++++++++++++++++++++++++++++++ net/wireless/trace.h | 18 +++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 27a3b8795d9b..93516ea07f7c 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -9881,6 +9881,20 @@ void cfg80211_next_nan_dw_notif(struct wireless_dev *wdev, struct ieee80211_channel *chan, gfp_t gfp); +/** + * cfg80211_nan_cluster_joined - Notify about NAN cluster join + * @wdev: Pointer to the wireless device structure + * @cluster_id: Cluster ID of the NAN cluster that was joined or started + * @new_cluster: Indicates if this is a new cluster or an existing one + * @gfp: Memory allocation flags + * + * This function is used to notify user space when a NAN cluster has been + * joined, providing the cluster ID and a flag whether it is a new cluster. + */ +void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, + u16 cluster_id, bool new_cluster, + gfp_t gfp); + #ifdef CONFIG_CFG80211_DEBUGFS /** * wiphy_locked_debugfs_read - do a locked read in debugfs diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h index 134cea046bd0..d883f4a639e8 100644 --- a/include/uapi/linux/nl80211.h +++ b/include/uapi/linux/nl80211.h @@ -1351,6 +1351,9 @@ * userspace about the next Discovery Window (DW). Userspace may use it * to prepare frames to be sent in the next DW. %NL80211_ATTR_WIPHY_FREQ * is used to indicate the frequency of the next DW. + * @NL80211_CMD_NAN_CLUSTER_JOINED: This command is used to notify + * userspace that the NAN new cluster has been joined. The cluster ID is + * indicated by %NL80211_ATTR_MAC. * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use @@ -1613,7 +1616,7 @@ enum nl80211_commands { NL80211_CMD_EPCS_CFG, NL80211_CMD_NAN_NEXT_DW_NOTIFICATION, - + NL80211_CMD_NAN_CLUSTER_JOINED, /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -2926,6 +2929,9 @@ enum nl80211_commands { * This is used with %NL80211_CMD_GET_WIPHY to indicate the NAN * capabilities supported by the driver. See &enum nl80211_nan_capabilities * for details. + * @NL80211_ATTR_NAN_NEW_CLUSTER: Flag attribute indicating that a new + * NAN cluster has been created. This is used with + * %NL80211_CMD_NAN_CLUSTER_JOINED * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined @@ -3486,6 +3492,7 @@ enum nl80211_attrs { NL80211_ATTR_NAN_CONFIG, NL80211_ATTR_NAN_CAPABILITIES, + NL80211_ATTR_NAN_NEW_CLUSTER, /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 5936ec1557fe..f979fc1b504a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -20864,6 +20864,49 @@ void cfg80211_next_nan_dw_notif(struct wireless_dev *wdev, } EXPORT_SYMBOL(cfg80211_next_nan_dw_notif); +void cfg80211_nan_cluster_joined(struct wireless_dev *wdev, + u16 cluster_id, bool new_cluster, + gfp_t gfp) +{ + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); + struct sk_buff *msg; + void *hdr; + u8 nan_cluster_addr[ETH_ALEN] = { 0x51, 0x6f, 0x9a, 0x01, 0x00, 0x00 }; + + nan_cluster_addr[5] = cluster_id & 0xff; + nan_cluster_addr[4] = (cluster_id >> 8) & 0xff; + trace_cfg80211_nan_cluster_joined(wdev, cluster_id, new_cluster); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NAN_CLUSTER_JOINED); + if (!hdr) + goto nla_put_failure; + + if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || + nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), + NL80211_ATTR_PAD) || + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, nan_cluster_addr) || + (new_cluster && nla_put_flag(msg, NL80211_ATTR_NAN_NEW_CLUSTER))) + goto nla_put_failure; + + 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_cluster_joined); + /* initialisation/exit functions */ int __init nl80211_init(void) diff --git a/net/wireless/trace.h b/net/wireless/trace.h index bf84e6abaf69..deafd0b4f94c 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -4203,6 +4203,24 @@ TRACE_EVENT(cfg80211_next_nan_dw_notif, WDEV_PR_ARG, CHAN_PR_ARG) ); +TRACE_EVENT(cfg80211_nan_cluster_joined, + TP_PROTO(struct wireless_dev *wdev, + u16 cluster_id, bool new_cluster), + TP_ARGS(wdev, cluster_id, new_cluster), + TP_STRUCT__entry( + WDEV_ENTRY + __field(u16, cluster_id) + __field(bool, new_cluster) + ), + TP_fast_assign( + WDEV_ASSIGN; + __entry->cluster_id = cluster_id; + __entry->new_cluster = new_cluster; + ), + TP_printk(WDEV_PR_FMT " cluster_id 0x%04x %s", + WDEV_PR_ARG, __entry->cluster_id, + __entry->new_cluster ? "[new]" : "") +); #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH