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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.