From: Ilan Peer <ilan.peer@intel.com>
To: johannes@sipsolutions.net
Cc: linux-wireless@vger.kernel.org, Ilan Peer <ilan.peer@intel.com>,
Benjamin Berg <benjamin.berg@intel.com>,
Miri Korenblit <miriam.rachel.korenblit@intel.com>
Subject: [PATCH v2 11/11] wifi: mac80211_hwsim: add NAN Instant Communication support
Date: Mon, 5 Oct 2026 10:40:36 +0300 [thread overview]
Message-ID: <20261005074037.3506633-12-ilan.peer@intel.com> (raw)
In-Reply-To: <20261005074037.3506633-1-ilan.peer@intel.com>
Advertise Instant Communication (IC) support, and when it is enabled:
- Transmit the discovery beacons disregarding the role and the state,
with the configured beacon interval and the NAN attributes set by
user space.
- Accept beacons that carry a Service ID List or a Subscribe Service
ID List attribute at any time, so that they are forwarded to
mac80211.
- Process discovery beacons received during non DW slots for anchor
master tracking and synchronization.
Assisted-by: GitHubCopilot:claude-opus-5
Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Reviewed-by: Benjamin Berg <benjamin.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../wireless/virtual/mac80211_hwsim_main.c | 7 +-
.../net/wireless/virtual/mac80211_hwsim_nan.c | 129 ++++++++++++++++--
.../net/wireless/virtual/mac80211_hwsim_nan.h | 2 +
3 files changed, 122 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
index 02b6d81cccd1..5d235946e19a 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
@@ -1772,6 +1772,7 @@ struct tx_iter_data {
struct ieee80211_channel *channel;
struct ieee80211_rx_status *rx_status;
struct ieee80211_hw *hw;
+ struct sk_buff *skb;
bool receive;
};
@@ -1784,6 +1785,7 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
if (vif->type == NL80211_IFTYPE_NAN ||
vif->type == NL80211_IFTYPE_NAN_DATA) {
data->receive = mac80211_hwsim_nan_receive(data->hw,
+ data->skb,
data->channel,
data->rx_status);
return;
@@ -1968,6 +1970,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
.hw = data2->hw,
.channel = chan,
.rx_status = &rx_status,
+ .skb = skb,
};
if (data == data2)
@@ -5800,7 +5803,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
BIT(NL80211_BAND_5GHZ);
hw->wiphy->nan_capa.flags = WIPHY_NAN_FLAGS_CONFIGURABLE_SYNC |
- WIPHY_NAN_FLAGS_USERSPACE_DE;
+ WIPHY_NAN_FLAGS_USERSPACE_DE |
+ WIPHY_NAN_FLAGS_INSTANT_COMM;
hw->wiphy->nan_capa.op_mode = NAN_OP_MODE_PHY_MODE_MASK |
NAN_OP_MODE_80P80MHZ |
NAN_OP_MODE_160MHZ;
@@ -6546,6 +6550,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
struct tx_iter_data iter_data = {
.hw = data2->hw,
.rx_status = &rx_status,
+ .skb = skb,
};
/* throw away off-channel packets, but allow both the temporary
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
index 538ece73b1d5..1f058ec9c159 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.c
@@ -219,6 +219,37 @@ mac80211_hwsim_nan_schedule_slot(struct mac80211_hwsim_data *data, u8 slot,
mac80211_hwsim_tsf_to_boottime(data, tsf));
}
+static bool hwsim_nan_beacon_has_service_ids(struct sk_buff *skb)
+{
+ const struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ const struct ieee80211_nan_attr *nan_attr;
+ const struct element *elem;
+ size_t len;
+
+ if (skb->len < offsetofend(struct ieee80211_mgmt, u.beacon) ||
+ !ieee80211_is_beacon(mgmt->frame_control))
+ return false;
+
+ len = skb->len - offsetofend(struct ieee80211_mgmt, u.beacon);
+
+ /* TODO: fragmented NAN elements are not supported */
+ for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC,
+ mgmt->u.beacon.variable, len) {
+ if (elem->datalen < 4 ||
+ get_unaligned_be32(elem->data) !=
+ (WLAN_OUI_WFA << 8 | WLAN_OUI_TYPE_WFA_NAN))
+ continue;
+
+ for_each_nan_attr(nan_attr, elem->data + 4, elem->datalen - 4)
+ if (nan_attr->attr == NAN_ATTR_SERVICE_ID_LIST ||
+ nan_attr->attr ==
+ NAN_ATTR_SUBSCRIBE_SERVICE_ID_LIST)
+ return true;
+ }
+
+ return false;
+}
+
void mac80211_hwsim_nan_rx(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
@@ -270,15 +301,32 @@ void mac80211_hwsim_nan_rx(struct ieee80211_hw *hw,
}
/*
- * (overly) simplify things, only track 2.4 GHz here. Also, ignore
- * frames outside of the 2.4 GHz DW slot, unless in the initial SCAN
- * phase.
+ * Only sync on 2.4 GHz, which all NAN devices attend. The slot number
+ * is derived from the local TSF, so before being synchronized a 5 GHz
+ * beacon from a different device may fall into the local 2.4 GHz DW
+ * slot. Filter by frequency to keep such beacons out of master
+ * selection and synchronization.
*/
- if ((slot != SLOT_24GHZ_DW &&
- data->nan.phase != MAC80211_HWSIM_NAN_PHASE_SCAN) ||
- rx_status.freq != 2437)
+ if (rx_status.freq != 2437)
return;
+ /*
+ * Ignore frames outside of the 2.4 GHz DW slot, unless in the initial
+ * SCAN phase or in Instant Communication, where discovery beacons are
+ * received outside the DW.
+ */
+ if (slot != SLOT_24GHZ_DW) {
+ bool rx_outside_dw;
+
+ scoped_guard(spinlock_bh, &data->nan.state_lock)
+ rx_outside_dw = data->nan.instant_comm ||
+ data->nan.phase ==
+ MAC80211_HWSIM_NAN_PHASE_SCAN;
+
+ if (!rx_outside_dw)
+ return;
+ }
+
/* Just ignore low RSSI beacons that we cannot sync to */
if (rx_status.signal < NAN_RSSI_MIDDLE)
return;
@@ -629,10 +677,12 @@ mac80211_hwsim_nan_exec_state_transitions(struct mac80211_hwsim_data *data)
/*
* The discovery beacon timer will stop automatically. Make sure it is
- * running if we are master. Do not bother with a proper alignment it
- * will sync itself to the TSF after the first TX.
+ * running if we are master or if Instant Communication is enabled. Do
+ * not bother with a proper alignment it will sync itself to the TSF
+ * after the first TX.
*/
- if (data->nan.role == MAC80211_HWSIM_NAN_ROLE_MASTER &&
+ if ((data->nan.role == MAC80211_HWSIM_NAN_ROLE_MASTER ||
+ data->nan.instant_comm) &&
!hrtimer_active(&data->nan.discovery_beacon_timer))
hrtimer_start(&data->nan.discovery_beacon_timer,
ns_to_ktime(10 * NSEC_PER_USEC),
@@ -887,7 +937,15 @@ mac80211_hwsim_nan_discovery_beacon_timer(struct hrtimer *timer)
return HRTIMER_NORESTART;
scoped_guard(spinlock, &data->nan.state_lock) {
- if (data->nan.phase == MAC80211_HWSIM_NAN_PHASE_SCAN ||
+ if (data->nan.phase == MAC80211_HWSIM_NAN_PHASE_SCAN)
+ return HRTIMER_NORESTART;
+
+ /*
+ * With Instant Communication the discovery beacons are
+ * transmitted disregarding the role and the state, see
+ * Wi-Fi Aware version 4.0 section 13.
+ */
+ if (!data->nan.instant_comm &&
data->nan.role != MAC80211_HWSIM_NAN_ROLE_MASTER)
return HRTIMER_NORESTART;
}
@@ -944,6 +1002,8 @@ static int mac80211_hwsim_nan_set_config(struct mac80211_hwsim_data *data,
data->nan.discovery_beacon_interval =
conf->discovery_beacon_interval ? : 100;
+ data->nan.instant_comm = conf->instant_comm;
+
old = data->nan.extra_nan_attrs;
data->nan.extra_nan_attrs = extra_nan_attrs;
data->nan.extra_nan_attrs_len = conf->extra_nan_attrs_len;
@@ -976,9 +1036,13 @@ int mac80211_hwsim_nan_start(struct ieee80211_hw *hw,
data->nan.bands = conf->bands;
scoped_guard(spinlock_bh, &data->nan.state_lock) {
- /* Start in the "scan" phase and stay there for a little bit */
+ /*
+ * Start in the "scan" phase and stay there for a little bit,
+ * unless Instant Communication is configured, in which case an
+ * own cluster is started immediately.
+ */
data->nan.phase = MAC80211_HWSIM_NAN_PHASE_SCAN;
- data->nan.random_factor_valid_dwst = 1;
+ data->nan.random_factor_valid_dwst = conf->instant_comm ? 0 : 1;
data->nan.random_factor = 0;
data->nan.master_pref = conf->master_pref;
data->nan.role = MAC80211_HWSIM_NAN_ROLE_MASTER;
@@ -1018,6 +1082,7 @@ int mac80211_hwsim_nan_stop(struct ieee80211_hw *hw,
old = data->nan.extra_nan_attrs;
data->nan.extra_nan_attrs = NULL;
data->nan.extra_nan_attrs_len = 0;
+ data->nan.instant_comm = false;
}
kfree(old);
@@ -1045,6 +1110,16 @@ int mac80211_hwsim_nan_change_config(struct ieee80211_hw *hw,
if (err)
return err;
+
+ /*
+ * When Instant Communication is enabled discovery beacons are
+ * transmitted regardless of the role and the state.
+ */
+ if (conf->instant_comm &&
+ !hrtimer_active(&data->nan.discovery_beacon_timer))
+ hrtimer_start(&data->nan.discovery_beacon_timer,
+ ns_to_ktime(10 * NSEC_PER_USEC),
+ HRTIMER_MODE_REL_SOFT);
}
/* Handle only the changes we care about for simulation purposes */
@@ -1233,9 +1308,16 @@ bool mac80211_hwsim_nan_txq_transmitting(struct ieee80211_hw *hw,
is_dw_slot = mac80211_hwsim_nan_is_dw_slot(data, slot);
if (!txq->sta) {
- /* Non-STA TXQ: allow management frames during DW */
- if (txq->vif->type == NL80211_IFTYPE_NAN)
- return is_dw_slot;
+ /* Non-STA TXQ: allow management frames during DW or IC */
+ if (txq->vif->type == NL80211_IFTYPE_NAN) {
+ if (is_dw_slot)
+ return true;
+
+ /* Outside the DW the local schedule must allow it */
+ guard(spinlock_bh)(&data->nan.state_lock);
+ return data->nan.instant_comm &&
+ data->nan.local_sched[slot].chan;
+ }
/* Allow multicast data when all the peers are available
* on this slot
@@ -1288,15 +1370,32 @@ void mac80211_hwsim_nan_get_tx_chandef(struct ieee80211_hw *hw,
}
bool mac80211_hwsim_nan_receive(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
struct ieee80211_channel *channel,
struct ieee80211_rx_status *rx_status)
{
struct mac80211_hwsim_data *data = hw->priv;
+ bool instant_comm;
u8 slot;
if (WARN_ON_ONCE(!data->nan.device_vif))
return false;
+ scoped_guard(spinlock_bh, &data->nan.state_lock)
+ instant_comm = data->nan.instant_comm;
+
+ /*
+ * During Instant Communication a peer advertises its services in the
+ * discovery beacons, which are transmitted disregarding the roles and
+ * the states, see Section 13 in Wi-Fi Aware v4.0.
+ * Note that while according to the specification Instant communication
+ * should be enabled only on the NAN discovery channels, do not force
+ * this here, and allow receiving NAN frames on any channel if Instant
+ * Communication is enabled.
+ */
+ if (instant_comm && hwsim_nan_beacon_has_service_ids(skb))
+ return true;
+
if (data->nan.phase == MAC80211_HWSIM_NAN_PHASE_SCAN)
return channel->center_freq == 2437;
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
index 81761ab71955..995d1f6feb29 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_nan.h
@@ -56,6 +56,7 @@ struct mac80211_hwsim_nan_data {
bool tsf_adjusted;
bool tsf_discontinuity;
+ bool instant_comm;
u8 discovery_beacon_interval;
/*
@@ -95,6 +96,7 @@ void mac80211_hwsim_nan_get_tx_chandef(struct ieee80211_hw *hw,
struct cfg80211_chan_def *chandef);
bool mac80211_hwsim_nan_receive(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
struct ieee80211_channel *channel,
struct ieee80211_rx_status *rx_status);
--
2.55.0
prev parent reply other threads:[~2026-10-04 13:26 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-05 7:40 [PATCH v2 00/11] wifi: cfg80211/mac80211: add NAN Instant Communication support Ilan Peer
2026-10-04 13:41 ` Johannes Berg
2026-10-04 13:54 ` Peer, Ilan
2026-10-05 7:40 ` [PATCH v2 01/11] wifi: cfg80211: nan: add " Ilan Peer
2026-10-05 7:40 ` [PATCH v2 02/11] wifi: mac80211: nan: Update NAN configuration copy Ilan Peer
2026-10-05 7:40 ` [PATCH v2 03/11] wifi: cfg80211: nan: check Rx registration for NAN beacons Ilan Peer
2026-10-05 7:40 ` [PATCH v2 04/11] wifi: cfg80211: do not use NAN beacons to update the BSS table Ilan Peer
2026-10-05 7:40 ` [PATCH v2 05/11] wifi: mac80211: nan: allow Rx registration for NAN beacons Ilan Peer
2026-10-05 7:40 ` [PATCH v2 06/11] wifi: mac80211: accept NAN beacons only when IC is enabled Ilan Peer
2026-10-05 7:40 ` [PATCH v2 07/11] wifi: ieee80211: add NAN service ID list attribute definitions Ilan Peer
2026-10-05 7:40 ` [PATCH v2 08/11] wifi: mac80211_hwsim: nan: use ieee80211_is_nan_beacon() helper Ilan Peer
2026-10-05 7:40 ` [PATCH v2 09/11] wifi: mac80211_hwsim: nan: prepare for more configurable NAN settings Ilan Peer
2026-10-05 7:40 ` [PATCH v2 10/11] wifi: mac80211_hwsim: nan: Handle more of the NAN configuration Ilan Peer
2026-10-05 7:40 ` Ilan Peer [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261005074037.3506633-12-ilan.peer@intel.com \
--to=ilan.peer@intel.com \
--cc=benjamin.berg@intel.com \
--cc=johannes@sipsolutions.net \
--cc=linux-wireless@vger.kernel.org \
--cc=miriam.rachel.korenblit@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox