linux-wpan.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing
@ 2022-08-26 14:40 Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Miquel Raynal
                   ` (10 more replies)
  0 siblings, 11 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

Hello,

Here are the first patches of the big scan support series. Only passive
scan is present in these patches, we must agree on this first step
before moving forward with active scans, beaconing, associations and so
on. There are many other patches to come.

All of this is based on the initial work from David Girault and Romuald
Despres, they are often credited as Co-developpers.

Thanks,
Miquèl

Changes in v2 (some of them apply to other parts of the series not sent today):
* Initially tried to create a new (empty) path for COORD packets. As the
  processing, for now, is exactly the same as for NODE packets, I
  decided to go for a switch case as well as a comment indicating that
  the filtering should be enhanced with time.
* Reworked the rx path to clarify the ongoing filtering.
* Added an enum with the different filtering levels.
* Updated hwsim to reflect the right filtering level.
* Reworked again the rx path to include more filtering, in particular I
  added a real promiscuous mode as well as a level 4 filter (frame
  fields validation) which is enabled if the xceiver does not do it
  already.
* Set all the drivers (but the ca8210) able to create coordinators
  interfaces in theory.
* Prevented drivers with no promiscuous support to create COORD
  interfaces in the first place.
* Dropped the frame type enumeration because it was actually unused.
* The code already checked if the promiscuous mode was enabled, but
  it was not clear enough apparently, so I reorganized the logic a
  little bit in order to not hide this check.
* What was missing about the promiscuous mode however, was to remember
  in which state we found the PHY to avoid disabling the promiscuous
  mode if it was not enabled when we started scanning.
* Created a second workqueue, which would not be flushed in the close
  path because it does not need to be just for the mac commands. This
  allows acquiring the rtnl within scan_lock without issues.
* Thanks to the above change, I was able to drop the two patches
  reducing the use of the rtnl (in the tx path and in
  hwsim:change_channel()) but definitely not the change in the MLME Tx
  code which is really painful.

David Girault (1):
  net: ieee802154: Trace the registration of new PANs

Miquel Raynal (10):
  net: mac802154: Introduce filtering levels
  net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM
  net: mac802154: Allow the creation of coordinator interfaces
  net: ieee802154: Advertize coordinators discovery
  net: ieee802154: Handle coordinators discovery
  net: ieee802154: Add support for user scanning requests
  net: ieee802154: Define a beacon frame header
  net: mac802154: Prepare forcing specific symbol duration
  net: mac802154: Introduce a global device lock
  net: mac802154: Handle passive scanning

 drivers/net/ieee802154/mac802154_hwsim.c |  10 +-
 include/linux/ieee802154.h               |   7 +
 include/net/cfg802154.h                  |  74 ++++-
 include/net/ieee802154_netdev.h          |  36 +++
 include/net/mac802154.h                  |  28 +-
 include/net/nl802154.h                   |  91 +++++++
 net/ieee802154/Makefile                  |   2 +-
 net/ieee802154/core.c                    |   2 +
 net/ieee802154/nl802154.c                | 331 +++++++++++++++++++++++
 net/ieee802154/nl802154.h                |   9 +
 net/ieee802154/pan.c                     | 115 ++++++++
 net/ieee802154/rdev-ops.h                |  28 ++
 net/ieee802154/trace.h                   |  65 +++++
 net/mac802154/Makefile                   |   2 +-
 net/mac802154/cfg.c                      |  41 ++-
 net/mac802154/ieee802154_i.h             |  38 ++-
 net/mac802154/iface.c                    |  26 +-
 net/mac802154/main.c                     |  40 ++-
 net/mac802154/rx.c                       |  63 ++++-
 net/mac802154/scan.c                     | 291 ++++++++++++++++++++
 net/mac802154/tx.c                       |  12 +-
 21 files changed, 1269 insertions(+), 42 deletions(-)
 create mode 100644 net/ieee802154/pan.c
 create mode 100644 net/mac802154/scan.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-09-04 17:13   ` Alexander Aring
  2022-08-26 14:40 ` [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM Miquel Raynal
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

The 802154 specification details several filtering levels in which the
PHY and the MAC could be. The amount of filtering will vary if they are
in promiscuous mode or in scanning mode. Otherwise they are expected to
do some very basic checks, such as enforcing the frame validity. Either
the PHY is able to do so, and the MAC has nothing to do, or the PHY has
a lower filtering level than expected and the MAC should take over.

For now we define these levels in an enumeration, we add a per-PHY
parameter showing the PHY filtering level and we set it to a default
value. The drivers, if they cannot reach this level of filtering, should
overwrite this value so that it reflects what they do. Then, in the
core, this filtering level will be used to decide whether some
additional software processing is needed or not.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h |  3 +++
 include/net/mac802154.h | 24 ++++++++++++++++++++++++
 net/mac802154/iface.c   |  2 ++
 3 files changed, 29 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 04b996895fc1..2f29e95da47a 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -223,6 +223,9 @@ struct wpan_phy {
 	atomic_t hold_txs;
 	wait_queue_head_t sync_txq;
 
+	/* Current filtering level on reception */
+	unsigned long filtering;
+
 	char priv[] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 357d25ef627a..41c28118790c 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -130,6 +130,30 @@ enum ieee802154_hw_flags {
 #define IEEE802154_HW_OMIT_CKSUM	(IEEE802154_HW_TX_OMIT_CKSUM | \
 					 IEEE802154_HW_RX_OMIT_CKSUM)
 
+/**
+ * enum ieee802154_filtering_level - Filtering levels applicable to a PHY
+ *
+ * @IEEE802154_FILTERING_NONE: No filtering at all, what is received is
+ *	forwarded to the softMAC
+ * @IEEE802154_FILTERING_1_FCS: First filtering level, frames with an invalid
+ *	FCS should be dropped
+ * @IEEE802154_FILTERING_2_PROMISCUOUS: Second filtering level, promiscuous
+ *	mode, identical in terms of filtering to the first level at the PHY
+ *	level, but no ACK should be transmitted automatically and at the MAC
+ *	level the frame should be forwarded to the upper layer directly
+ * @IEEE802154_FILTERING_3_SCAN: Third filtering level, enforced during scans,
+ *	which only forwards beacons
+ * @IEEE802154_FILTERING_4_FRAME_FIELDS: Fourth filtering level actually
+ *	enforcing the validity of the content of the frame with various checks
+ */
+enum ieee802154_filtering_level {
+	IEEE802154_FILTERING_NONE,
+	IEEE802154_FILTERING_1_FCS,
+	IEEE802154_FILTERING_2_PROMISCUOUS,
+	IEEE802154_FILTERING_3_SCAN,
+	IEEE802154_FILTERING_4_FRAME_FIELDS,
+};
+
 /* struct ieee802154_ops - callbacks from mac802154 to the driver
  *
  * This structure contains various callbacks that the driver may
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 500ed1b81250..4bab2807acbe 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -587,6 +587,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
 		sdata->dev->netdev_ops = &mac802154_wpan_ops;
 		sdata->dev->ml_priv = &mac802154_mlme_wpan;
 		wpan_dev->promiscuous_mode = false;
+		wpan_dev->wpan_phy->filtering = IEEE802154_FILTERING_4_FRAME_FIELDS;
 		wpan_dev->header_ops = &ieee802154_header_ops;
 
 		mutex_init(&sdata->sec_mtx);
@@ -601,6 +602,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
 		sdata->dev->needs_free_netdev = true;
 		sdata->dev->netdev_ops = &mac802154_monitor_ops;
 		wpan_dev->promiscuous_mode = true;
+		wpan_dev->wpan_phy->filtering = IEEE802154_FILTERING_2_PROMISCUOUS;
 		break;
 	default:
 		BUG();
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-09-05  1:34   ` Alexander Aring
  2022-08-26 14:40 ` [PATCH wpan-next v2 03/11] net: mac802154: Allow the creation of coordinator interfaces Miquel Raynal
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

This IEEE802154_HW_RX_DROP_BAD_CKSUM flag was only used by hwsim to
reflect the fact that it would not validate the checksum (FCS). In other
words, the filtering level of hwsim is always "NONE" while the core
expects it to be higher.

Now that we have access to real filtering levels, we can actually use
them and always enforce the "NONE" level in hwsim. Handling this case
correctly in the receive path permits to drop the above mentioned flag.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/net/ieee802154/mac802154_hwsim.c | 10 +++++++++-
 include/net/mac802154.h                  |  4 ----
 net/mac802154/rx.c                       |  6 ++----
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
index 38c217bd7c82..d7e4048e8743 100644
--- a/drivers/net/ieee802154/mac802154_hwsim.c
+++ b/drivers/net/ieee802154/mac802154_hwsim.c
@@ -148,6 +148,8 @@ static int hwsim_hw_start(struct ieee802154_hw *hw)
 	struct hwsim_phy *phy = hw->priv;
 
 	phy->suspended = false;
+	hw->phy->filtering = IEEE802154_FILTERING_NONE;
+
 	return 0;
 }
 
@@ -161,6 +163,9 @@ static void hwsim_hw_stop(struct ieee802154_hw *hw)
 static int
 hwsim_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
 {
+	/* hwsim does not filter anything, so enforce the NONE level */
+	hw->phy->filtering = IEEE802154_FILTERING_NONE;
+
 	return 0;
 }
 
@@ -791,7 +796,10 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
 	phy->idx = idx;
 	INIT_LIST_HEAD(&phy->edges);
 
-	hw->flags = IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_RX_DROP_BAD_CKSUM;
+	/* This is a lie, hwsim does not even filter bad FCS, but we need to
+	 * advertize a PROMISCUOUS to be able to create COORD interfaces.
+	 */
+	hw->flags = IEEE802154_HW_PROMISCUOUS;
 	hw->parent = dev;
 
 	err = ieee802154_register_hw(hw);
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index 41c28118790c..a45ec09723f3 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -111,9 +111,6 @@ struct ieee802154_hw {
  *	promiscuous mode setting.
  *
  * @IEEE802154_HW_RX_OMIT_CKSUM: Indicates that receiver omits FCS.
- *
- * @IEEE802154_HW_RX_DROP_BAD_CKSUM: Indicates that receiver will not filter
- *	frames with bad checksum.
  */
 enum ieee802154_hw_flags {
 	IEEE802154_HW_TX_OMIT_CKSUM	= BIT(0),
@@ -123,7 +120,6 @@ enum ieee802154_hw_flags {
 	IEEE802154_HW_AFILT		= BIT(4),
 	IEEE802154_HW_PROMISCUOUS	= BIT(5),
 	IEEE802154_HW_RX_OMIT_CKSUM	= BIT(6),
-	IEEE802154_HW_RX_DROP_BAD_CKSUM	= BIT(7),
 };
 
 /* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index c439125ef2b9..42ebbe45a4c5 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -268,10 +268,8 @@ void ieee802154_rx(struct ieee802154_local *local, struct sk_buff *skb)
 
 	ieee802154_monitors_rx(local, skb);
 
-	/* Check if transceiver doesn't validate the checksum.
-	 * If not we validate the checksum here.
-	 */
-	if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM) {
+	/* Level 1 filtering: Check the FCS by software when relevant */
+	if (local->hw.phy->filtering == IEEE802154_FILTERING_NONE) {
 		crc = crc_ccitt(0, skb->data, skb->len);
 		if (crc) {
 			rcu_read_unlock();
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 03/11] net: mac802154: Allow the creation of coordinator interfaces
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 04/11] net: ieee802154: Advertize coordinators discovery Miquel Raynal
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

As a first strep in introducing proper PAN management and association,
we need to be able to create coordinator interfaces which might act as
coordinator or PAN coordinator.

Hence, let's add the minimum support to allow the creation of these
interfaces. This support will be improved later, in particular regarding
the filtering.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/iface.c | 14 ++++++++------
 net/mac802154/main.c  |  2 ++
 net/mac802154/rx.c    | 11 +++++++----
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 4bab2807acbe..8467a629e21f 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -273,13 +273,13 @@ ieee802154_check_concurrent_iface(struct ieee802154_sub_if_data *sdata,
 		if (nsdata != sdata && ieee802154_sdata_running(nsdata)) {
 			int ret;
 
-			/* TODO currently we don't support multiple node types
-			 * we need to run skb_clone at rx path. Check if there
-			 * exist really an use case if we need to support
-			 * multiple node types at the same time.
+			/* TODO currently we don't support multiple node/coord
+			 * types we need to run skb_clone at rx path. Check if
+			 * there exist really an use case if we need to support
+			 * multiple node/coord types at the same time.
 			 */
-			if (wpan_dev->iftype == NL802154_IFTYPE_NODE &&
-			    nsdata->wpan_dev.iftype == NL802154_IFTYPE_NODE)
+			if (wpan_dev->iftype != NL802154_IFTYPE_MONITOR &&
+			    nsdata->wpan_dev.iftype != NL802154_IFTYPE_MONITOR)
 				return -EBUSY;
 
 			/* check all phy mac sublayer settings are the same.
@@ -577,6 +577,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
 	wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
 
 	switch (type) {
+	case NL802154_IFTYPE_COORD:
 	case NL802154_IFTYPE_NODE:
 		ieee802154_be64_to_le64(&wpan_dev->extended_addr,
 					sdata->dev->dev_addr);
@@ -638,6 +639,7 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name,
 	ieee802154_le64_to_be64(ndev->perm_addr,
 				&local->hw.phy->perm_extended_addr);
 	switch (type) {
+	case NL802154_IFTYPE_COORD:
 	case NL802154_IFTYPE_NODE:
 		ndev->type = ARPHRD_IEEE802154;
 		if (ieee802154_is_valid_extended_unicast_addr(extended_addr)) {
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 40fab08df24b..d03ecb747afc 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -219,6 +219,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
 	if (hw->flags & IEEE802154_HW_PROMISCUOUS)
 		local->phy->supported.iftypes |= BIT(NL802154_IFTYPE_MONITOR);
+	else
+		local->phy->supported.iftypes &= ~BIT(NL802154_IFTYPE_COORD);
 
 	rc = wpan_phy_register(local->phy);
 	if (rc < 0)
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index 42ebbe45a4c5..ea5320411848 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -194,6 +194,7 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
 	int ret;
 	struct ieee802154_sub_if_data *sdata;
 	struct ieee802154_hdr hdr;
+	struct sk_buff *skb2;
 
 	ret = ieee802154_parse_frame_start(skb, &hdr);
 	if (ret) {
@@ -203,15 +204,17 @@ __ieee802154_rx_handle_packet(struct ieee802154_local *local,
 	}
 
 	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-		if (sdata->wpan_dev.iftype != NL802154_IFTYPE_NODE)
+		if (sdata->wpan_dev.iftype == NL802154_IFTYPE_MONITOR)
 			continue;
 
 		if (!ieee802154_sdata_running(sdata))
 			continue;
 
-		ieee802154_subif_frame(sdata, skb, &hdr);
-		skb = NULL;
-		break;
+		skb2 = skb_clone(skb, GFP_ATOMIC);
+		if (skb2) {
+			skb2->dev = sdata->dev;
+			ieee802154_subif_frame(sdata, skb2, &hdr);
+		}
 	}
 
 	kfree_skb(skb);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 04/11] net: ieee802154: Advertize coordinators discovery
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (2 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 03/11] net: mac802154: Allow the creation of coordinator interfaces Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 05/11] net: ieee802154: Handle " Miquel Raynal
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

Let's introduce the basics for advertizing discovered PANs and
coordinators, which is:
- A new "scan" netlink message group.
- A couple of netlink command/attribute.
- The main netlink helper to send a netlink message with all the
  necessary information to forward the main information to the user.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h   |  20 +++++++
 include/net/nl802154.h    |  44 ++++++++++++++
 net/ieee802154/nl802154.c | 121 ++++++++++++++++++++++++++++++++++++++
 net/ieee802154/nl802154.h |   6 ++
 4 files changed, 191 insertions(+)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 2f29e95da47a..9d3daf4680b1 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -258,6 +258,26 @@ struct ieee802154_addr {
 	};
 };
 
+/**
+ * struct ieee802154_coord_desc - Coordinator descriptor
+ * @coord: PAN ID and coordinator address
+ * @page: page this coordinator is using
+ * @channel: channel this coordinator is using
+ * @superframe_spec: SuperFrame specification as received
+ * @link_quality: link quality indicator at which the beacon was received
+ * @gts_permit: the coordinator accepts GTS requests
+ * @node: list item
+ */
+struct ieee802154_coord_desc {
+	struct ieee802154_addr *addr;
+	u8 page;
+	u8 channel;
+	u16 superframe_spec;
+	u8 link_quality;
+	bool gts_permit;
+	struct list_head node;
+};
+
 struct ieee802154_llsec_key_id {
 	u8 mode;
 	u8 id;
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 145acb8f2509..cfe462288695 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -58,6 +58,9 @@ enum nl802154_commands {
 
 	NL802154_CMD_SET_WPAN_PHY_NETNS,
 
+	NL802154_CMD_NEW_COORDINATOR,
+	NL802154_CMD_KNOWN_COORDINATOR,
+
 	/* add new commands above here */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -133,6 +136,8 @@ enum nl802154_attrs {
 	NL802154_ATTR_PID,
 	NL802154_ATTR_NETNS_FD,
 
+	NL802154_ATTR_COORDINATOR,
+
 	/* add attributes here, update the policy in nl802154.c */
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
@@ -218,6 +223,45 @@ enum nl802154_wpan_phy_capability_attr {
 	NL802154_CAP_ATTR_MAX = __NL802154_CAP_ATTR_AFTER_LAST - 1
 };
 
+/**
+ * enum nl802154_coord - Netlink attributes for a coord
+ *
+ * @__NL802154_COORD_INVALID: invalid
+ * @NL802154_COORD_PANID: PANID of the coordinator (2 bytes)
+ * @NL802154_COORD_ADDR: coordinator address, (8 bytes or 2 bytes)
+ * @NL802154_COORD_CHANNEL: channel number, related to @NL802154_COORD_PAGE (u8)
+ * @NL802154_COORD_PAGE: channel page, related to @NL802154_COORD_CHANNEL (u8)
+ * @NL802154_COORD_PREAMBLE_CODE: Preamble code used when the beacon was received,
+ *	this is PHY dependent and optional (u8)
+ * @NL802154_COORD_MEAN_PRF: Mean PRF used when the beacon was received,
+ *     this is PHY dependent and optional (u8)
+ * @NL802154_COORD_SUPERFRAME_SPEC: superframe specification of the PAN (u16)
+ * @NL802154_COORD_LINK_QUALITY: signal quality of beacon in unspecified units,
+ *	scaled to 0..255 (u8)
+ * @NL802154_COORD_GTS_PERMIT: set to true if GTS is permitted on this PAN
+ * @NL802154_COORD_PAYLOAD_DATA: binary data containing the raw data from the
+ *	frame payload, (only if beacon or probe response had data)
+ * @NL802154_COORD_PAD: attribute used for padding for 64-bit alignment
+ * @NL802154_COORD_MAX: highest coordinator attribute
+ */
+enum nl802154_coord {
+	__NL802154_COORD_INVALID,
+	NL802154_COORD_PANID,
+	NL802154_COORD_ADDR,
+	NL802154_COORD_CHANNEL,
+	NL802154_COORD_PAGE,
+	NL802154_COORD_PREAMBLE_CODE,
+	NL802154_COORD_MEAN_PRF,
+	NL802154_COORD_SUPERFRAME_SPEC,
+	NL802154_COORD_LINK_QUALITY,
+	NL802154_COORD_GTS_PERMIT,
+	NL802154_COORD_PAYLOAD_DATA,
+	NL802154_COORD_PAD,
+
+	/* keep last */
+	NL802154_COORD_MAX,
+};
+
 /**
  * enum nl802154_cca_modes - cca modes
  *
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index e0b072aecf0f..f6fb7a228747 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -26,10 +26,12 @@ static struct genl_family nl802154_fam;
 /* multicast groups */
 enum nl802154_multicast_groups {
 	NL802154_MCGRP_CONFIG,
+	NL802154_MCGRP_SCAN,
 };
 
 static const struct genl_multicast_group nl802154_mcgrps[] = {
 	[NL802154_MCGRP_CONFIG] = { .name = "config", },
+	[NL802154_MCGRP_SCAN] = { .name = "scan", },
 };
 
 /* returns ERR_PTR values */
@@ -216,6 +218,9 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 
 	[NL802154_ATTR_PID] = { .type = NLA_U32 },
 	[NL802154_ATTR_NETNS_FD] = { .type = NLA_U32 },
+
+	[NL802154_ATTR_COORDINATOR] = { .type = NLA_NESTED },
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
 	[NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
@@ -1281,6 +1286,122 @@ static int nl802154_wpan_phy_netns(struct sk_buff *skb, struct genl_info *info)
 	return err;
 }
 
+static int nl802154_prep_new_coord_msg(struct sk_buff *msg,
+				       struct cfg802154_registered_device *rdev,
+				       struct wpan_dev *wpan_dev,
+				       u32 portid, u32 seq, int flags, u8 cmd,
+				       struct ieee802154_coord_desc *desc)
+{
+	struct nlattr *nla;
+	void *hdr;
+
+	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx))
+		goto nla_put_failure;
+
+	if (wpan_dev->netdev &&
+	    nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
+			      wpan_dev_id(wpan_dev), NL802154_ATTR_PAD))
+		goto nla_put_failure;
+
+	nla = nla_nest_start_noflag(msg, NL802154_ATTR_COORDINATOR);
+	if (!nla)
+		goto nla_put_failure;
+
+	if (nla_put(msg, NL802154_COORD_PANID, IEEE802154_PAN_ID_LEN,
+		    &desc->addr->pan_id))
+		goto nla_put_failure;
+
+	if (desc->addr->mode == IEEE802154_ADDR_SHORT) {
+		if (nla_put(msg, NL802154_COORD_ADDR,
+			    IEEE802154_SHORT_ADDR_LEN,
+			    &desc->addr->short_addr))
+			goto nla_put_failure;
+	} else {
+		if (nla_put(msg, NL802154_COORD_ADDR,
+			    IEEE802154_EXTENDED_ADDR_LEN,
+			    &desc->addr->extended_addr))
+			goto nla_put_failure;
+	}
+
+	if (nla_put_u8(msg, NL802154_COORD_CHANNEL, desc->channel))
+		goto nla_put_failure;
+
+	if (nla_put_u8(msg, NL802154_COORD_PAGE, desc->page))
+		goto nla_put_failure;
+
+	if (nla_put_u16(msg, NL802154_COORD_SUPERFRAME_SPEC,
+			desc->superframe_spec))
+		goto nla_put_failure;
+
+	if (nla_put_u8(msg, NL802154_COORD_LINK_QUALITY, desc->link_quality))
+		goto nla_put_failure;
+
+	if (desc->gts_permit && nla_put_flag(msg, NL802154_COORD_GTS_PERMIT))
+		goto nla_put_failure;
+
+	/* TODO: NL802154_COORD_PAYLOAD_DATA if any */
+
+	nla_nest_end(msg, nla);
+
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+ nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+
+	return -EMSGSIZE;
+}
+
+static int nl802154_advertise_coordinator(struct wpan_phy *wpan_phy,
+					  struct wpan_dev *wpan_dev, u8 cmd,
+					  struct ieee802154_coord_desc *desc)
+{
+	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
+	struct sk_buff *msg;
+	int ret;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+	if (!msg)
+		return -ENOMEM;
+
+	ret = nl802154_prep_new_coord_msg(msg, rdev, wpan_dev, 0, 0, 0, cmd, desc);
+	if (ret < 0) {
+		nlmsg_free(msg);
+		return ret;
+	}
+
+	return genlmsg_multicast_netns(&nl802154_fam, wpan_phy_net(wpan_phy),
+				       msg, 0, NL802154_MCGRP_SCAN, GFP_ATOMIC);
+}
+
+int nl802154_advertise_new_coordinator(struct wpan_phy *wpan_phy,
+				       struct wpan_dev *wpan_dev,
+				       struct ieee802154_coord_desc *desc)
+{
+	return nl802154_advertise_coordinator(wpan_phy, wpan_dev,
+					      NL802154_CMD_NEW_COORDINATOR,
+					      desc);
+}
+EXPORT_SYMBOL_GPL(nl802154_advertise_new_coordinator);
+
+int nl802154_advertise_known_coordinator(struct wpan_phy *wpan_phy,
+					 struct wpan_dev *wpan_dev,
+					 struct ieee802154_coord_desc *desc)
+{
+	return nl802154_advertise_coordinator(wpan_phy, wpan_dev,
+					      NL802154_CMD_KNOWN_COORDINATOR,
+					      desc);
+}
+EXPORT_SYMBOL_GPL(nl802154_advertise_known_coordinator);
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
diff --git a/net/ieee802154/nl802154.h b/net/ieee802154/nl802154.h
index 8c4b6d08954c..607af197fa0a 100644
--- a/net/ieee802154/nl802154.h
+++ b/net/ieee802154/nl802154.h
@@ -4,5 +4,11 @@
 
 int nl802154_init(void);
 void nl802154_exit(void);
+int nl802154_advertise_new_coordinator(struct wpan_phy *wpan_phy,
+				       struct wpan_dev *wpan_dev,
+				       struct ieee802154_coord_desc *desc);
+int nl802154_advertise_known_coordinator(struct wpan_phy *wpan_phy,
+					 struct wpan_dev *wpan_dev,
+					 struct ieee802154_coord_desc *desc);
 
 #endif /* __IEEE802154_NL802154_H */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 05/11] net: ieee802154: Handle coordinators discovery
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (3 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 04/11] net: ieee802154: Advertize coordinators discovery Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 06/11] net: ieee802154: Trace the registration of new PANs Miquel Raynal
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

Let's introduce helpers for giving the MAC layer a generic interface for
advertising discovered coordinators/PANs upon beacon reception. This
support requires the MAC layers to:
- Allocate a coordinator/PAN descriptor and fill it.
- Register this structure, giving the generic ieee802154 layer the
  necessary information about the coordinator/PAN the beacon originates
  from.
- To flush all the allocated structures once the scan is done.

The generic layer keeps a temporary list of the discovered coordinators
to avoid spamming the user with identical information. So only new
discoveries are forwarded to the user through netlink messages (already
implemented).

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h   |  11 ++++
 net/ieee802154/Makefile   |   2 +-
 net/ieee802154/core.c     |   2 +
 net/ieee802154/nl802154.c |   2 +
 net/ieee802154/pan.c      | 113 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 129 insertions(+), 1 deletion(-)
 create mode 100644 net/ieee802154/pan.c

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 9d3daf4680b1..f2cee32f292c 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -401,6 +401,10 @@ struct wpan_dev {
 
 	/* fallback for acknowledgment bit setting */
 	bool ackreq;
+
+	/* Coordinators management during scans */
+	spinlock_t coord_list_lock;
+	struct list_head coord_list;
 };
 
 #define to_phy(_dev)	container_of(_dev, struct wpan_phy, dev)
@@ -449,4 +453,11 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
 
 void ieee802154_configure_durations(struct wpan_phy *phy);
 
+struct ieee802154_coord_desc *
+cfg802154_alloc_coordinator(struct ieee802154_addr *coord);
+void cfg802154_record_coordinator(struct wpan_phy *wpan_phy,
+				  struct wpan_dev *wpan_dev,
+				  struct ieee802154_coord_desc *desc);
+void cfg802154_flush_known_coordinators(struct wpan_dev *wpan_dev);
+
 #endif /* __NET_CFG802154_H */
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index f05b7bdae2aa..6b7c66de730d 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o
 obj-y += 6lowpan/
 
 ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \
-                header_ops.o sysfs.o nl802154.o trace.o
+                header_ops.o sysfs.o nl802154.o pan.o trace.o
 ieee802154_socket-y := socket.o
 
 CFLAGS_trace.o := -I$(src)
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 57546e07e06a..091eb467fde6 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -276,6 +276,8 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
 		wpan_dev->identifier = ++rdev->wpan_dev_id;
 		list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list);
 		rdev->devlist_generation++;
+		spin_lock_init(&wpan_dev->coord_list_lock);
+		INIT_LIST_HEAD(&wpan_dev->coord_list);
 
 		wpan_dev->netdev = dev;
 		break;
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index f6fb7a228747..b6bd04fe160b 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1368,6 +1368,8 @@ static int nl802154_advertise_coordinator(struct wpan_phy *wpan_phy,
 	struct sk_buff *msg;
 	int ret;
 
+	lockdep_assert(&wpan_dev->coord_list_lock);
+
 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
 	if (!msg)
 		return -ENOMEM;
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
new file mode 100644
index 000000000000..27fb5432f651
--- /dev/null
+++ b/net/ieee802154/pan.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IEEE 802.15.4 PAN management
+ *
+ * Copyright (C) Qorvo, 2021
+ * Authors:
+ *   - David Girault <david.girault@qorvo.com>
+ *   - Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <net/cfg802154.h>
+#include <net/af_ieee802154.h>
+
+#include "ieee802154.h"
+#include "../ieee802154/nl802154.h"
+
+struct ieee802154_coord_desc *
+cfg802154_alloc_coordinator(struct ieee802154_addr *coord)
+{
+	struct ieee802154_coord_desc *desc;
+
+	desc = kzalloc(sizeof(*desc), GFP_ATOMIC);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->addr = kzalloc(sizeof(*coord), GFP_ATOMIC);
+	if (!desc->addr) {
+		kfree(desc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	memcpy(desc->addr, coord, sizeof(*coord));
+
+	return desc;
+}
+EXPORT_SYMBOL_GPL(cfg802154_alloc_coordinator);
+
+static void cfg802154_free_coordinator_desc(struct ieee802154_coord_desc *desc)
+{
+	kfree(desc->addr);
+	kfree(desc);
+}
+
+static bool
+cfg802154_is_same_coordinator(struct ieee802154_coord_desc *a,
+			      struct ieee802154_coord_desc *b)
+{
+	if (a->addr->pan_id != b->addr->pan_id)
+		return false;
+
+	if (a->addr->mode != b->addr->mode)
+		return false;
+
+	if (a->addr->mode == IEEE802154_ADDR_SHORT &&
+	    a->addr->short_addr == b->addr->short_addr)
+		return true;
+	else if (a->addr->mode == IEEE802154_ADDR_LONG &&
+		 a->addr->extended_addr == b->addr->extended_addr)
+		return true;
+
+	return false;
+}
+
+static bool
+cfg802154_coordinator_is_known(struct wpan_dev *wpan_dev,
+			       struct ieee802154_coord_desc *desc)
+{
+	struct ieee802154_coord_desc *item;
+
+	list_for_each_entry(item, &wpan_dev->coord_list, node)
+		if (cfg802154_is_same_coordinator(item, desc))
+			return true;
+
+	return false;
+}
+
+void cfg802154_record_coordinator(struct wpan_phy *wpan_phy,
+				  struct wpan_dev *wpan_dev,
+				  struct ieee802154_coord_desc *desc)
+{
+	spin_lock_bh(&wpan_dev->coord_list_lock);
+
+	if (cfg802154_coordinator_is_known(wpan_dev, desc)) {
+		nl802154_advertise_known_coordinator(wpan_phy, wpan_dev, desc);
+		cfg802154_free_coordinator_desc(desc);
+	} else {
+		list_add_tail(&desc->node, &wpan_dev->coord_list);
+		nl802154_advertise_new_coordinator(wpan_phy, wpan_dev, desc);
+	}
+
+	spin_unlock_bh(&wpan_dev->coord_list_lock);
+}
+EXPORT_SYMBOL_GPL(cfg802154_record_coordinator);
+
+void cfg802154_flush_known_coordinators(struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_coord_desc *desc, *tmp;
+
+	spin_lock_bh(&wpan_dev->coord_list_lock);
+
+	list_for_each_entry_safe(desc, tmp, &wpan_dev->coord_list, node) {
+		list_del(&desc->node);
+		cfg802154_free_coordinator_desc(desc);
+	}
+
+	spin_unlock_bh(&wpan_dev->coord_list_lock);
+}
+EXPORT_SYMBOL_GPL(cfg802154_flush_known_coordinators);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 06/11] net: ieee802154: Trace the registration of new PANs
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (4 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 05/11] net: ieee802154: Handle " Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 07/11] net: ieee802154: Add support for user scanning requests Miquel Raynal
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

From: David Girault <david.girault@qorvo.com>

Add an internal trace when new PANs get discovered.

Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/ieee802154/pan.c   |  2 ++
 net/ieee802154/trace.h | 25 +++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
index 27fb5432f651..d3b7a9764319 100644
--- a/net/ieee802154/pan.c
+++ b/net/ieee802154/pan.c
@@ -18,6 +18,7 @@
 
 #include "ieee802154.h"
 #include "../ieee802154/nl802154.h"
+#include "trace.h"
 
 struct ieee802154_coord_desc *
 cfg802154_alloc_coordinator(struct ieee802154_addr *coord)
@@ -90,6 +91,7 @@ void cfg802154_record_coordinator(struct wpan_phy *wpan_phy,
 		cfg802154_free_coordinator_desc(desc);
 	} else {
 		list_add_tail(&desc->node, &wpan_dev->coord_list);
+		trace_802154_new_coordinator(desc);
 		nl802154_advertise_new_coordinator(wpan_phy, wpan_dev, desc);
 	}
 
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h
index 19c2e5d60e76..03b3817c34ad 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -295,6 +295,31 @@ TRACE_EVENT(802154_rdev_set_ackreq_default,
 		WPAN_DEV_PR_ARG, BOOL_TO_STR(__entry->ackreq))
 );
 
+DECLARE_EVENT_CLASS(802154_new_coordinator_evt,
+	TP_PROTO(struct ieee802154_coord_desc *desc),
+	TP_ARGS(desc),
+	TP_STRUCT__entry(
+		__field(__le16, pan_id)
+		__field(__le64, addr)
+		__field(u8, channel)
+		__field(u8, page)
+	),
+	TP_fast_assign(
+		__entry->page = desc->page;
+		__entry->channel = desc->channel;
+		__entry->pan_id = desc->addr->pan_id;
+		__entry->addr = desc->addr->extended_addr;
+	),
+	TP_printk("panid: %u, coord_addr: 0x%llx, page: %u, channel: %u",
+		  __le16_to_cpu(__entry->pan_id), __le64_to_cpu(__entry->addr),
+		  __entry->page, __entry->channel)
+);
+
+DEFINE_EVENT(802154_new_coordinator_evt, 802154_new_coordinator,
+	TP_PROTO(struct ieee802154_coord_desc *desc),
+	TP_ARGS(desc)
+);
+
 TRACE_EVENT(802154_rdev_return_int,
 	TP_PROTO(struct wpan_phy *wpan_phy, int ret),
 	TP_ARGS(wpan_phy, ret),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 07/11] net: ieee802154: Add support for user scanning requests
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (5 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 06/11] net: ieee802154: Trace the registration of new PANs Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 08/11] net: ieee802154: Define a beacon frame header Miquel Raynal
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

The ieee802154 layer should be able to scan a set of channels in order
to look for beacons advertizing PANs. Supporting this involves adding
two user commands: triggering scans and aborting scans. The user should
also be notified when a new beacon is received and also upon scan
termination.

A scan request structure is created to list the requirements and to be
accessed asynchronously when changing channels or receiving beacons.

Mac layers may now implement the ->trigger_scan() and ->abort_scan()
hooks.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/ieee802154.h |   3 +
 include/net/cfg802154.h    |  25 +++++
 include/net/nl802154.h     |  47 +++++++++
 net/ieee802154/nl802154.c  | 208 +++++++++++++++++++++++++++++++++++++
 net/ieee802154/nl802154.h  |   3 +
 net/ieee802154/rdev-ops.h  |  28 +++++
 net/ieee802154/trace.h     |  40 +++++++
 7 files changed, 354 insertions(+)

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index f1f9412b6ac6..929d4e672575 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -44,6 +44,9 @@
 #define IEEE802154_SHORT_ADDR_LEN	2
 #define IEEE802154_PAN_ID_LEN		2
 
+/* Duration in superframe order */
+#define IEEE802154_MAX_SCAN_DURATION	14
+#define IEEE802154_ACTIVE_SCAN_DURATION	15
 #define IEEE802154_LIFS_PERIOD		40
 #define IEEE802154_SIFS_PERIOD		12
 #define IEEE802154_MAX_SIFS_FRAME_SIZE	18
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index f2cee32f292c..ebc41a8551b3 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -18,6 +18,7 @@
 
 struct wpan_phy;
 struct wpan_phy_cca;
+struct cfg802154_scan_request;
 
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 struct ieee802154_llsec_device_key;
@@ -67,6 +68,10 @@ struct cfg802154_ops {
 				struct wpan_dev *wpan_dev, bool mode);
 	int	(*set_ackreq_default)(struct wpan_phy *wpan_phy,
 				      struct wpan_dev *wpan_dev, bool ackreq);
+	int	(*trigger_scan)(struct wpan_phy *wpan_phy,
+				struct cfg802154_scan_request *request);
+	int	(*abort_scan)(struct wpan_phy *wpan_phy,
+			      struct wpan_dev *wpan_dev);
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	void	(*get_llsec_table)(struct wpan_phy *wpan_phy,
 				   struct wpan_dev *wpan_dev,
@@ -278,6 +283,26 @@ struct ieee802154_coord_desc {
 	struct list_head node;
 };
 
+/**
+ * struct cfg802154_scan_request - Scan request
+ *
+ * @type: type of scan to be performed
+ * @page: page on which to perform the scan
+ * @channels: channels in te %page to be scanned
+ * @duration: time spent on each channel, calculated with:
+ *            aBaseSuperframeDuration * (2 ^ duration + 1)
+ * @wpan_dev: the wpan device on which to perform the scan
+ * @wpan_phy: the wpan phy on which to perform the scan
+ */
+struct cfg802154_scan_request {
+	enum nl802154_scan_types type;
+	u8 page;
+	u32 channels;
+	u8 duration;
+	struct wpan_dev *wpan_dev;
+	struct wpan_phy *wpan_phy;
+};
+
 struct ieee802154_llsec_key_id {
 	u8 mode;
 	u8 id;
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index cfe462288695..71b7456d108e 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -60,6 +60,9 @@ enum nl802154_commands {
 
 	NL802154_CMD_NEW_COORDINATOR,
 	NL802154_CMD_KNOWN_COORDINATOR,
+	NL802154_CMD_TRIGGER_SCAN,
+	NL802154_CMD_ABORT_SCAN,
+	NL802154_CMD_SCAN_DONE,
 
 	/* add new commands above here */
 
@@ -137,6 +140,10 @@ enum nl802154_attrs {
 	NL802154_ATTR_NETNS_FD,
 
 	NL802154_ATTR_COORDINATOR,
+	NL802154_ATTR_SCAN_TYPE,
+	NL802154_ATTR_SCAN_FLAGS,
+	NL802154_ATTR_SCAN_CHANNELS,
+	NL802154_ATTR_SCAN_DURATION,
 
 	/* add attributes here, update the policy in nl802154.c */
 
@@ -262,6 +269,46 @@ enum nl802154_coord {
 	NL802154_COORD_MAX,
 };
 
+/**
+ * enum nl802154_scan_types - Scan types
+ *
+ * @__NL802154_SCAN_INVALID: scan type number 0 is reserved
+ * @NL802154_SCAN_ED: An ED scan allows a device to obtain a measure of the peak
+ *	energy in each requested channel
+ * @NL802154_SCAN_ACTIVE: Locate any coordinator transmitting Beacon frames using
+ *	a Beacon Request command
+ * @NL802154_SCAN_PASSIVE: Locate any coordinator transmitting Beacon frames
+ * @NL802154_SCAN_ORPHAN: Relocate coordinator following a loss of synchronisation
+ * @NL802154_SCAN_ENHANCED_ACTIVE: Same as Active using Enhanced Beacon Request
+ *	command instead of Beacon Request command
+ * @NL802154_SCAN_RIT_PASSIVE: Passive scan for RIT Data Request command frames
+ *	instead of Beacon frames
+ * @NL802154_SCAN_ATTR_MAX: Maximum SCAN attribute number
+ */
+enum nl802154_scan_types {
+	__NL802154_SCAN_INVALID,
+	NL802154_SCAN_ED,
+	NL802154_SCAN_ACTIVE,
+	NL802154_SCAN_PASSIVE,
+	NL802154_SCAN_ORPHAN,
+	NL802154_SCAN_ENHANCED_ACTIVE,
+	NL802154_SCAN_RIT_PASSIVE,
+
+	/* keep last */
+	NL802154_SCAN_ATTR_MAX,
+};
+
+/**
+ * enum nl802154_scan_flags - Scan request control flags
+ *
+ * @NL802154_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (ie.
+ *	a different one for every scan iteration). When the flag is set, full
+ *	randomisation is assumed.
+ */
+enum nl802154_scan_flags {
+	NL802154_SCAN_FLAG_RANDOM_ADDR = BIT(0),
+};
+
 /**
  * enum nl802154_cca_modes - cca modes
  *
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index b6bd04fe160b..16df8c99a663 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -221,6 +221,10 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
 
 	[NL802154_ATTR_COORDINATOR] = { .type = NLA_NESTED },
 
+	[NL802154_ATTR_SCAN_TYPE] = { .type = NLA_U8 },
+	[NL802154_ATTR_SCAN_CHANNELS] = { .type = NLA_U32 },
+	[NL802154_ATTR_SCAN_DURATION] = { .type = NLA_U8 },
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
 	[NL802154_ATTR_SEC_OUT_LEVEL] = { .type = NLA_U32, },
@@ -1404,6 +1408,194 @@ int nl802154_advertise_known_coordinator(struct wpan_phy *wpan_phy,
 }
 EXPORT_SYMBOL_GPL(nl802154_advertise_known_coordinator);
 
+static int nl802154_trigger_scan(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+	struct wpan_phy *wpan_phy = &rdev->wpan_phy;
+	struct cfg802154_scan_request *request;
+	u8 type;
+	int err;
+
+	/* Monitors are not allowed to perform scans */
+	if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
+		return -EPERM;
+
+	request = kzalloc(sizeof(*request), GFP_KERNEL);
+	if (!request)
+		return -ENOMEM;
+
+	request->wpan_dev = wpan_dev;
+	request->wpan_phy = wpan_phy;
+
+	type = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_TYPE]);
+	switch (type) {
+	case NL802154_SCAN_PASSIVE:
+		request->type = type;
+		break;
+	default:
+		pr_err("Unsupported scan type: %d\n", type);
+		err = -EINVAL;
+		goto free_request;
+	}
+
+	if (info->attrs[NL802154_ATTR_PAGE]) {
+		request->page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
+		if (request->page > IEEE802154_MAX_PAGE) {
+			pr_err("Invalid page %d > %d\n",
+			       request->page, IEEE802154_MAX_PAGE);
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Use current page by default */
+		request->page = wpan_phy->current_page;
+	}
+
+	if (info->attrs[NL802154_ATTR_SCAN_CHANNELS]) {
+		request->channels = nla_get_u32(info->attrs[NL802154_ATTR_SCAN_CHANNELS]);
+		if (request->channels >= BIT(IEEE802154_MAX_CHANNEL + 1)) {
+			pr_err("Invalid channels bitfield %x ≥ %lx\n",
+			       request->channels,
+			       BIT(IEEE802154_MAX_CHANNEL + 1));
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Scan all supported channels by default */
+		request->channels = wpan_phy->supported.channels[request->page];
+	}
+
+	if (info->attrs[NL802154_ATTR_SCAN_DURATION]) {
+		request->duration = nla_get_u8(info->attrs[NL802154_ATTR_SCAN_DURATION]);
+		if (request->duration > IEEE802154_MAX_SCAN_DURATION) {
+			pr_err("Duration is out of range\n");
+			err = -EINVAL;
+			goto free_request;
+		}
+	} else {
+		/* Use maximum duration order by default */
+		request->duration = IEEE802154_MAX_SCAN_DURATION;
+	}
+
+	if (wpan_dev->netdev)
+		dev_hold(wpan_dev->netdev);
+
+	err = rdev_trigger_scan(rdev, request);
+	if (err) {
+		pr_err("Failure starting scanning (%d)\n", err);
+		goto free_device;
+	}
+
+	return 0;
+
+free_device:
+	if (wpan_dev->netdev)
+		dev_put(wpan_dev->netdev);
+free_request:
+	kfree(request);
+
+	return err;
+}
+
+static int nl802154_prep_scan_msg(struct sk_buff *msg,
+				  struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev,
+				  u32 portid, u32 seq, int flags, u8 cmd)
+{
+	void *hdr;
+
+	hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
+	if (!hdr)
+		return -ENOBUFS;
+
+	if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx))
+		goto nla_put_failure;
+
+	if (wpan_dev->netdev &&
+	    nla_put_u32(msg, NL802154_ATTR_IFINDEX, wpan_dev->netdev->ifindex))
+		goto nla_put_failure;
+
+	if (nla_put_u64_64bit(msg, NL802154_ATTR_WPAN_DEV,
+			      wpan_dev_id(wpan_dev), NL802154_ATTR_PAD))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+
+	return 0;
+
+nla_put_failure:
+	genlmsg_cancel(msg, hdr);
+
+	return -EMSGSIZE;
+}
+
+static int nl802154_send_scan_msg(struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev, u8 cmd)
+{
+	struct sk_buff *msg;
+	int ret;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	ret = nl802154_prep_scan_msg(msg, rdev, wpan_dev, 0, 0, 0, cmd);
+	if (ret < 0) {
+		nlmsg_free(msg);
+		return ret;
+	}
+
+	return genlmsg_multicast_netns(&nl802154_fam,
+				       wpan_phy_net(&rdev->wpan_phy), msg, 0,
+				       NL802154_MCGRP_SCAN, GFP_KERNEL);
+}
+
+int nl802154_send_start_scan(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
+{
+	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
+	int err;
+
+	/* Ignore errors when there are no listeners */
+	err = nl802154_send_scan_msg(rdev, wpan_dev, NL802154_CMD_TRIGGER_SCAN);
+	if (err == -ESRCH)
+		err = 0;
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(nl802154_send_start_scan);
+
+int nl802154_send_scan_done(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+			    struct cfg802154_scan_request *request, u8 cmd)
+{
+	struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(wpan_phy);
+	int err;
+
+	/* Ignore errors when there are no listeners */
+	err = nl802154_send_scan_msg(rdev, wpan_dev, cmd);
+	if (err == -ESRCH)
+		err = 0;
+
+	kfree(request);
+
+	if (wpan_dev->netdev)
+		dev_put(wpan_dev->netdev);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(nl802154_send_scan_done);
+
+static int nl802154_abort_scan(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg802154_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+
+	/* Resources are released in the notification helper above */
+	return rdev_abort_scan(rdev, wpan_dev);
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static const struct nla_policy nl802154_dev_addr_policy[NL802154_DEV_ADDR_ATTR_MAX + 1] = {
 	[NL802154_DEV_ADDR_ATTR_PAN_ID] = { .type = NLA_U16 },
@@ -2492,6 +2684,22 @@ static const struct genl_ops nl802154_ops[] = {
 		.internal_flags = NL802154_FLAG_NEED_NETDEV |
 				  NL802154_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL802154_CMD_TRIGGER_SCAN,
+		.doit = nl802154_trigger_scan,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL802154_CMD_ABORT_SCAN,
+		.doit = nl802154_abort_scan,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL802154_FLAG_NEED_NETDEV |
+				  NL802154_FLAG_CHECK_NETDEV_UP |
+				  NL802154_FLAG_NEED_RTNL,
+	},
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	{
 		.cmd = NL802154_CMD_SET_SEC_PARAMS,
diff --git a/net/ieee802154/nl802154.h b/net/ieee802154/nl802154.h
index 607af197fa0a..298fa7d09894 100644
--- a/net/ieee802154/nl802154.h
+++ b/net/ieee802154/nl802154.h
@@ -10,5 +10,8 @@ int nl802154_advertise_new_coordinator(struct wpan_phy *wpan_phy,
 int nl802154_advertise_known_coordinator(struct wpan_phy *wpan_phy,
 					 struct wpan_dev *wpan_dev,
 					 struct ieee802154_coord_desc *desc);
+int nl802154_send_start_scan(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev);
+int nl802154_send_scan_done(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+			    struct cfg802154_scan_request *request, u8 cmd);
 
 #endif /* __IEEE802154_NL802154_H */
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h
index 598f5af49775..e171d74c3251 100644
--- a/net/ieee802154/rdev-ops.h
+++ b/net/ieee802154/rdev-ops.h
@@ -209,6 +209,34 @@ rdev_set_ackreq_default(struct cfg802154_registered_device *rdev,
 	return ret;
 }
 
+static inline int rdev_trigger_scan(struct cfg802154_registered_device *rdev,
+				    struct cfg802154_scan_request *request)
+{
+	int ret;
+
+	if (!rdev->ops->trigger_scan)
+		return -EOPNOTSUPP;
+
+	trace_802154_rdev_trigger_scan(&rdev->wpan_phy, request);
+	ret = rdev->ops->trigger_scan(&rdev->wpan_phy, request);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
+static inline int rdev_abort_scan(struct cfg802154_registered_device *rdev,
+				  struct wpan_dev *wpan_dev)
+{
+	int ret;
+
+	if (!rdev->ops->abort_scan)
+		return -EOPNOTSUPP;
+
+	trace_802154_rdev_abort_scan(&rdev->wpan_phy, wpan_dev);
+	ret = rdev->ops->abort_scan(&rdev->wpan_phy, wpan_dev);
+	trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 /* TODO this is already a nl802154, so move into ieee802154 */
 static inline void
diff --git a/net/ieee802154/trace.h b/net/ieee802154/trace.h
index 03b3817c34ad..d193f66ae0c7 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -320,6 +320,46 @@ DEFINE_EVENT(802154_new_coordinator_evt, 802154_new_coordinator,
 	TP_ARGS(desc)
 );
 
+TRACE_EVENT(802154_rdev_trigger_scan,
+	TP_PROTO(struct wpan_phy *wpan_phy,
+		 struct cfg802154_scan_request *request),
+	TP_ARGS(wpan_phy, request),
+	TP_STRUCT__entry(
+		WPAN_PHY_ENTRY
+		__field(u8, page)
+		__field(u32, channels)
+		__field(u8, duration)
+	),
+	TP_fast_assign(
+		WPAN_PHY_ASSIGN;
+		__entry->page = request->page;
+		__entry->channels = request->channels;
+		__entry->duration = request->duration;
+	),
+	TP_printk(WPAN_PHY_PR_FMT ", scan, page: %d, channels: %x, duration %d",
+		  WPAN_PHY_PR_ARG, __entry->page, __entry->channels, __entry->duration)
+);
+
+DECLARE_EVENT_CLASS(802154_wdev_template,
+	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+	TP_ARGS(wpan_phy, wpan_dev),
+	TP_STRUCT__entry(
+		WPAN_PHY_ENTRY
+		WPAN_DEV_ENTRY
+	),
+	TP_fast_assign(
+		WPAN_PHY_ASSIGN;
+		WPAN_DEV_ASSIGN;
+	),
+	TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT,
+		  WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG)
+);
+
+DEFINE_EVENT(802154_wdev_template, 802154_rdev_abort_scan,
+	TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+	TP_ARGS(wpan_phy, wpan_dev)
+);
+
 TRACE_EVENT(802154_rdev_return_int,
 	TP_PROTO(struct wpan_phy *wpan_phy, int ret),
 	TP_ARGS(wpan_phy, ret),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 08/11] net: ieee802154: Define a beacon frame header
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (6 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 07/11] net: ieee802154: Add support for user scanning requests Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 09/11] net: mac802154: Prepare forcing specific symbol duration Miquel Raynal
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

This definition will be used when adding support for scanning and defines
the content of a beacon frame header as in the 802.15.4 specification.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h | 36 +++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index d0d188c3294b..fb6ac354a7b6 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -22,6 +22,42 @@
 
 #include <net/cfg802154.h>
 
+struct ieee802154_beacon_hdr {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+	u16 beacon_order:4,
+	    superframe_order:4,
+	    final_cap_slot:4,
+	    battery_life_ext:1,
+	    reserved0:1,
+	    pan_coordinator:1,
+	    assoc_permit:1;
+	u8  gts_count:3,
+	    gts_reserved:4,
+	    gts_permit:1;
+	u8  pend_short_addr_count:3,
+	    reserved1:1,
+	    pend_ext_addr_count:3,
+	    reserved2:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	u16 assoc_permit:1,
+	    pan_coordinator:1,
+	    reserved0:1,
+	    battery_life_ext:1,
+	    final_cap_slot:4,
+	    superframe_order:4,
+	    beacon_order:4;
+	u8  gts_permit:1,
+	    gts_reserved:4,
+	    gts_count:3;
+	u8  reserved2:1,
+	    pend_ext_addr_count:3,
+	    reserved1:1,
+	    pend_short_addr_count:3;
+#else
+#error	"Please fix <asm/byteorder.h>"
+#endif
+} __packed;
+
 struct ieee802154_sechdr {
 #if defined(__LITTLE_ENDIAN_BITFIELD)
 	u8 level:3,
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 09/11] net: mac802154: Prepare forcing specific symbol duration
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (7 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 08/11] net: ieee802154: Define a beacon frame header Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 10/11] net: mac802154: Introduce a global device lock Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 11/11] net: mac802154: Handle passive scanning Miquel Raynal
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

The scan logic will bypass the whole ->set_channel() logic from the top
by calling the driver hook to just switch between channels when
required.

We can no longer rely on the "current" page/channel settings to set the
right symbol duration. Let's add these as new parameters to allow
providing the page/channel couple that we want.

There is no functional change.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/cfg802154.h |  3 ++-
 net/mac802154/cfg.c     |  2 +-
 net/mac802154/main.c    | 20 +++++++++++---------
 3 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index ebc41a8551b3..bfd6d5725a40 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -476,7 +476,8 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
 	return dev_name(&phy->dev);
 }
 
-void ieee802154_configure_durations(struct wpan_phy *phy);
+void ieee802154_configure_durations(struct wpan_phy *phy,
+				    unsigned int page, unsigned int channel);
 
 struct ieee802154_coord_desc *
 cfg802154_alloc_coordinator(struct ieee802154_addr *coord);
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 93df24f75572..4116a894c86e 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -118,7 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	if (!ret) {
 		wpan_phy->current_page = page;
 		wpan_phy->current_channel = channel;
-		ieee802154_configure_durations(wpan_phy);
+		ieee802154_configure_durations(wpan_phy, page, channel);
 	}
 
 	return ret;
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index d03ecb747afc..95100df6489a 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -113,32 +113,33 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 }
 EXPORT_SYMBOL(ieee802154_alloc_hw);
 
-void ieee802154_configure_durations(struct wpan_phy *phy)
+void ieee802154_configure_durations(struct wpan_phy *phy,
+				    unsigned int page, unsigned int channel)
 {
 	u32 duration = 0;
 
-	switch (phy->current_page) {
+	switch (page) {
 	case 0:
-		if (BIT(phy->current_channel) & 0x1)
+		if (BIT(channel) & 0x1)
 			/* 868 MHz BPSK 802.15.4-2003: 20 ksym/s */
 			duration = 50 * NSEC_PER_USEC;
-		else if (BIT(phy->current_channel) & 0x7FE)
+		else if (BIT(channel) & 0x7FE)
 			/* 915 MHz BPSK	802.15.4-2003: 40 ksym/s */
 			duration = 25 * NSEC_PER_USEC;
-		else if (BIT(phy->current_channel) & 0x7FFF800)
+		else if (BIT(channel) & 0x7FFF800)
 			/* 2400 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
 			duration = 16 * NSEC_PER_USEC;
 		break;
 	case 2:
-		if (BIT(phy->current_channel) & 0x1)
+		if (BIT(channel) & 0x1)
 			/* 868 MHz O-QPSK 802.15.4-2006: 25 ksym/s */
 			duration = 40 * NSEC_PER_USEC;
-		else if (BIT(phy->current_channel) & 0x7FE)
+		else if (BIT(channel) & 0x7FE)
 			/* 915 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */
 			duration = 16 * NSEC_PER_USEC;
 		break;
 	case 3:
-		if (BIT(phy->current_channel) & 0x3FFF)
+		if (BIT(channel) & 0x3FFF)
 			/* 2.4 GHz CSS 802.15.4a-2007: 1/6 Msym/s */
 			duration = 6 * NSEC_PER_USEC;
 		break;
@@ -201,7 +202,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
 	ieee802154_setup_wpan_phy_pib(local->phy);
 
-	ieee802154_configure_durations(local->phy);
+	ieee802154_configure_durations(local->phy, local->phy->current_page,
+				       local->phy->current_channel);
 
 	if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) {
 		local->phy->supported.min_csma_backoffs = 4;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 10/11] net: mac802154: Introduce a global device lock
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (8 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 09/11] net: mac802154: Prepare forcing specific symbol duration Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  2022-08-26 14:40 ` [PATCH wpan-next v2 11/11] net: mac802154: Handle passive scanning Miquel Raynal
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

The purpose of this device lock is to prevent the removal of the device
while an asynchronous MLME operation happens. The RTNL works well for
that but in a later series having the RTNL taken here will be
problematic and will cause lockdep to warn us about a circular
dependency. We don't really need the RTNL here, just a serialization
over this operation.

Replace the RTNL calls with this new lock.

Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 net/mac802154/ieee802154_i.h |  2 ++
 net/mac802154/iface.c        |  4 ++++
 net/mac802154/main.c         |  1 +
 net/mac802154/tx.c           | 12 ++++++------
 4 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 010365a6364e..b8775bcc9003 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -29,7 +29,9 @@ struct ieee802154_local {
 	/* ieee802154 phy */
 	struct wpan_phy *phy;
 
+	/* Open/close counter and lock */
 	int open_count;
+	struct mutex device_lock;
 
 	/* As in mac80211 slaves list is modified:
 	 * 1) under the RTNL
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 8467a629e21f..29af3f80b4d0 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -315,11 +315,15 @@ static int mac802154_slave_close(struct net_device *dev)
 
 	ASSERT_RTNL();
 
+	mutex_lock(&local->device_lock);
+
 	netif_stop_queue(dev);
 	local->open_count--;
 
 	clear_bit(SDATA_STATE_RUNNING, &sdata->state);
 
+	mutex_unlock(&local->device_lock);
+
 	if (!local->open_count)
 		ieee802154_stop_device(local);
 
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 95100df6489a..7657fb46c9e1 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -90,6 +90,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_LIST_HEAD(&local->interfaces);
 	mutex_init(&local->iflist_mtx);
+	mutex_init(&local->device_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 9d8d43cf1e64..fb555797f326 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -143,14 +143,14 @@ int ieee802154_mlme_tx(struct ieee802154_local *local,
 {
 	int ret;
 
-	/* Avoid possible calls to ->ndo_stop() when we asynchronously perform
-	 * MLME transmissions.
+	/* Serialize possible calls to ->ndo_stop() when we asynchronously
+	 * perform MLME transmissions.
 	 */
-	rtnl_lock();
+	mutex_lock(&local->device_lock);
 
 	/* Ensure the device was not stopped, otherwise error out */
 	if (!local->open_count) {
-		rtnl_unlock();
+		mutex_unlock(&local->device_lock);
 		return -ENETDOWN;
 	}
 
@@ -158,14 +158,14 @@ int ieee802154_mlme_tx(struct ieee802154_local *local,
 	 * net interface expects this cannot happen.
 	 */
 	if (WARN_ON_ONCE(!netif_running(sdata->dev))) {
-		rtnl_unlock();
+		mutex_unlock(&local->device_lock);
 		return -ENETDOWN;
 	}
 
 	ieee802154_tx(local, skb);
 	ret = ieee802154_sync_queue(local);
 
-	rtnl_unlock();
+	mutex_unlock(&local->device_lock);
 
 	return ret;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH wpan-next v2 11/11] net: mac802154: Handle passive scanning
  2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
                   ` (9 preceding siblings ...)
  2022-08-26 14:40 ` [PATCH wpan-next v2 10/11] net: mac802154: Introduce a global device lock Miquel Raynal
@ 2022-08-26 14:40 ` Miquel Raynal
  10 siblings, 0 replies; 14+ messages in thread
From: Miquel Raynal @ 2022-08-26 14:40 UTC (permalink / raw)
  To: Alexander Aring, Stefan Schmidt, linux-wpan
  Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	netdev, David Girault, Romuald Despres, Frederic Blain,
	Nicolas Schodet, Thomas Petazzoni, Miquel Raynal

Implement the core hooks in order to provide the softMAC layer support
for passive scans. Scans are requested by the user and can be aborted.

Changing the channels is prohibited during the scan.

As transceivers enter promiscuous mode during scans, they might stop
checking frame validity so we ensure this gets done at mac level.

The implementation uses a workqueue triggered at a certain interval
depending on the symbol duration for the current channel and the
duration order provided.

Received beacons during a passive scan are processed also in a work
queue and forwarded to the upper layer.

Active scanning is not supported yet.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/linux/ieee802154.h   |   4 +
 include/net/cfg802154.h      |  12 ++
 net/mac802154/Makefile       |   2 +-
 net/mac802154/cfg.c          |  39 +++++
 net/mac802154/ieee802154_i.h |  36 ++++-
 net/mac802154/iface.c        |   6 +
 net/mac802154/main.c         |  17 +-
 net/mac802154/rx.c           |  46 ++++++
 net/mac802154/scan.c         | 291 +++++++++++++++++++++++++++++++++++
 9 files changed, 448 insertions(+), 5 deletions(-)
 create mode 100644 net/mac802154/scan.c

diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
index 929d4e672575..94bfee22bd0a 100644
--- a/include/linux/ieee802154.h
+++ b/include/linux/ieee802154.h
@@ -47,6 +47,10 @@
 /* Duration in superframe order */
 #define IEEE802154_MAX_SCAN_DURATION	14
 #define IEEE802154_ACTIVE_SCAN_DURATION	15
+/* Superframe duration in slots */
+#define IEEE802154_SUPERFRAME_PERIOD	16
+/* Various periods expressed in symbols */
+#define IEEE802154_SLOT_PERIOD		60
 #define IEEE802154_LIFS_PERIOD		40
 #define IEEE802154_SIFS_PERIOD		12
 #define IEEE802154_MAX_SIFS_FRAME_SIZE	18
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index bfd6d5725a40..d6b0195df3cd 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -303,6 +303,18 @@ struct cfg802154_scan_request {
 	struct wpan_phy *wpan_phy;
 };
 
+/**
+ * struct cfg802154_mac_pkt - MAC packet descriptor (beacon/command)
+ * @node: MAC packets to process list member
+ * @skb: the received sk_buff
+ * @sdata: the interface on which @skb was received
+ */
+struct cfg802154_mac_pkt {
+	struct list_head node;
+	struct sk_buff *skb;
+	struct ieee802154_sub_if_data *sdata;
+};
+
 struct ieee802154_llsec_key_id {
 	u8 mode;
 	u8 id;
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 4059295fdbf8..43d1347b37ee 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_MAC802154)	+= mac802154.o
 mac802154-objs		:= main.o rx.o tx.o mac_cmd.o mib.o \
-			   iface.o llsec.o util.o cfg.o trace.o
+			   iface.o llsec.o util.o cfg.o scan.o trace.o
 
 CFLAGS_trace.o := -I$(src)
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 4116a894c86e..1f532d93d870 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -114,6 +114,10 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	    wpan_phy->current_channel == channel)
 		return 0;
 
+	/* Refuse to change channels during a scanning operation */
+	if (mac802154_is_scanning(local))
+		return -EBUSY;
+
 	ret = drv_set_channel(local, page, channel);
 	if (!ret) {
 		wpan_phy->current_page = page;
@@ -261,6 +265,39 @@ ieee802154_set_ackreq_default(struct wpan_phy *wpan_phy,
 	return 0;
 }
 
+static int mac802154_trigger_scan(struct wpan_phy *wpan_phy,
+				  struct cfg802154_scan_request *request)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	struct ieee802154_sub_if_data *sdata;
+	int ret;
+
+	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(request->wpan_dev);
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->scan_lock);
+	ret = mac802154_trigger_scan_locked(sdata, request);
+	mutex_unlock(&local->scan_lock);
+
+	return ret;
+}
+
+static int mac802154_abort_scan(struct wpan_phy *wpan_phy,
+				struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	int ret;
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->scan_lock);
+	ret = mac802154_abort_scan_locked(local);
+	mutex_unlock(&local->scan_lock);
+
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static void
 ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -468,6 +505,8 @@ const struct cfg802154_ops mac802154_config_ops = {
 	.set_max_frame_retries = ieee802154_set_max_frame_retries,
 	.set_lbt_mode = ieee802154_set_lbt_mode,
 	.set_ackreq_default = ieee802154_set_ackreq_default,
+	.trigger_scan = mac802154_trigger_scan,
+	.abort_scan = mac802154_abort_scan,
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	.get_llsec_table = ieee802154_get_llsec_table,
 	.lock_llsec_table = ieee802154_lock_llsec_table,
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index b8775bcc9003..774e07236fd0 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -21,6 +21,10 @@
 
 #include "llsec.h"
 
+enum ieee802154_ongoing {
+	IEEE802154_IS_SCANNING = BIT(0),
+};
+
 /* mac802154 device private data */
 struct ieee802154_local {
 	struct ieee802154_hw hw;
@@ -43,15 +47,27 @@ struct ieee802154_local {
 	struct list_head	interfaces;
 	struct mutex		iflist_mtx;
 
-	/* This one is used for scanning and other jobs not to be interfered
-	 * with serial driver.
-	 */
+	/* Data related workqueue */
 	struct workqueue_struct	*workqueue;
+	/* MAC commands related workqueue */
+	struct workqueue_struct	*mac_wq;
 
 	struct hrtimer ifs_timer;
 
+	/* Scanning */
+	struct mutex scan_lock;
+	int scan_channel_idx;
+	struct cfg802154_scan_request __rcu *scan_req;
+	struct delayed_work scan_work;
+	bool was_promiscuous;
+
+	/* Asynchronous tasks */
+	struct list_head rx_beacon_list;
+	struct work_struct rx_beacon_work;
+
 	bool started;
 	bool suspended;
+	unsigned long ongoing;
 
 	struct tasklet_struct tasklet;
 	struct sk_buff_head skb_queue;
@@ -210,6 +226,20 @@ void mac802154_unlock_table(struct net_device *dev);
 
 int mac802154_wpan_update_llsec(struct net_device *dev);
 
+/* PAN management handling */
+void mac802154_scan_worker(struct work_struct *work);
+int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_scan_request *request);
+int mac802154_abort_scan_locked(struct ieee802154_local *local);
+int mac802154_process_beacon(struct ieee802154_local *local,
+			     struct sk_buff *skb);
+void mac802154_rx_beacon_worker(struct work_struct *work);
+
+static inline bool mac802154_is_scanning(struct ieee802154_local *local)
+{
+	return test_bit(IEEE802154_IS_SCANNING, &local->ongoing);
+}
+
 /* interface handling */
 int ieee802154_iface_init(void);
 void ieee802154_iface_exit(void);
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index 29af3f80b4d0..97974466e894 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -315,6 +315,12 @@ static int mac802154_slave_close(struct net_device *dev)
 
 	ASSERT_RTNL();
 
+	if (mac802154_is_scanning(local)) {
+		mutex_lock(&local->scan_lock);
+		mac802154_abort_scan_locked(local);
+		mutex_unlock(&local->scan_lock);
+	}
+
 	mutex_lock(&local->device_lock);
 
 	netif_stop_queue(dev);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 7657fb46c9e1..a45055d475dd 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -89,14 +89,18 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 	local->ops = ops;
 
 	INIT_LIST_HEAD(&local->interfaces);
+	INIT_LIST_HEAD(&local->rx_beacon_list);
 	mutex_init(&local->iflist_mtx);
 	mutex_init(&local->device_lock);
+	mutex_init(&local->scan_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
 	skb_queue_head_init(&local->skb_queue);
 
 	INIT_WORK(&local->sync_tx_work, ieee802154_xmit_sync_worker);
+	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_worker);
+	INIT_WORK(&local->rx_beacon_work, mac802154_rx_beacon_worker);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
@@ -186,6 +190,7 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
 int ieee802154_register_hw(struct ieee802154_hw *hw)
 {
 	struct ieee802154_local *local = hw_to_local(hw);
+	char mac_wq_name[IFNAMSIZ + 10] = {};
 	struct net_device *dev;
 	int rc = -ENOSYS;
 
@@ -196,6 +201,13 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 		goto out;
 	}
 
+	snprintf(mac_wq_name, IFNAMSIZ + 10, "%s-mac-cmds", wpan_phy_name(local->phy));
+	local->mac_wq =	create_singlethread_workqueue(mac_wq_name);
+	if (!local->mac_wq) {
+		rc = -ENOMEM;
+		goto out_wq;
+	}
+
 	hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	local->ifs_timer.function = ieee802154_xmit_ifs_timer;
 
@@ -227,7 +239,7 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
 	rc = wpan_phy_register(local->phy);
 	if (rc < 0)
-		goto out_wq;
+		goto out_mac_wq;
 
 	rtnl_lock();
 
@@ -246,6 +258,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
 out_phy:
 	wpan_phy_unregister(local->phy);
+out_mac_wq:
+	destroy_workqueue(local->mac_wq);
 out_wq:
 	destroy_workqueue(local->workqueue);
 out:
@@ -266,6 +280,7 @@ void ieee802154_unregister_hw(struct ieee802154_hw *hw)
 
 	rtnl_unlock();
 
+	destroy_workqueue(local->mac_wq);
 	destroy_workqueue(local->workqueue);
 	wpan_phy_unregister(local->phy);
 }
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index ea5320411848..b28fbfff6e51 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -29,11 +29,37 @@ static int ieee802154_deliver_skb(struct sk_buff *skb)
 	return netif_receive_skb(skb);
 }
 
+void mac802154_rx_beacon_worker(struct work_struct *work)
+{
+	struct ieee802154_local *local =
+		container_of(work, struct ieee802154_local, rx_beacon_work);
+	struct cfg802154_mac_pkt *mac_pkt;
+
+	mutex_lock(&local->scan_lock);
+
+	if (list_empty(&local->rx_beacon_list))
+		goto unlock;
+
+	mac_pkt = list_first_entry(&local->rx_beacon_list,
+				   struct cfg802154_mac_pkt, node);
+
+	mac802154_process_beacon(local, mac_pkt->skb);
+
+	list_del(&mac_pkt->node);
+	kfree_skb(mac_pkt->skb);
+	kfree(mac_pkt);
+
+unlock:
+	mutex_unlock(&local->scan_lock);
+}
+
 static int
 ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 		       struct sk_buff *skb, const struct ieee802154_hdr *hdr)
 {
 	struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+	struct wpan_phy *wpan_phy = sdata->local->hw.phy;
+	struct cfg802154_mac_pkt *mac_pkt;
 	__le16 span, sshort;
 	int rc;
 
@@ -42,6 +68,13 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 	span = wpan_dev->pan_id;
 	sshort = wpan_dev->short_addr;
 
+	/* Level 3 filtering: Only beacons are accepted during scans */
+	if (mac802154_is_scanning(sdata->local)) {
+		if (wpan_phy->filtering != IEEE802154_FILTERING_3_SCAN &&
+		    mac_cb(skb)->type != IEEE802154_FC_TYPE_BEACON)
+			goto fail;
+	}
+
 	switch (mac_cb(skb)->dest.mode) {
 	case IEEE802154_ADDR_NONE:
 		if (hdr->source.mode != IEEE802154_ADDR_NONE)
@@ -94,6 +127,19 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 
 	switch (mac_cb(skb)->type) {
 	case IEEE802154_FC_TYPE_BEACON:
+		if (!mac802154_is_scanning(sdata->local))
+			goto fail;
+
+		mac_pkt = kzalloc(sizeof(*mac_pkt), GFP_ATOMIC);
+		if (!mac_pkt)
+			goto fail;
+
+		mac_pkt->skb = skb_get(skb);
+		mac_pkt->sdata = sdata;
+		list_add_tail(&mac_pkt->node, &sdata->local->rx_beacon_list);
+		queue_work(sdata->local->mac_wq, &sdata->local->rx_beacon_work);
+		kfree_skb(skb);
+		return NET_RX_SUCCESS;
 	case IEEE802154_FC_TYPE_ACK:
 	case IEEE802154_FC_TYPE_MAC_CMD:
 		goto fail;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
new file mode 100644
index 000000000000..a2c08cd90a27
--- /dev/null
+++ b/net/mac802154/scan.c
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * IEEE 802.15.4 scanning management
+ *
+ * Copyright (C) Qorvo, 2021
+ * Authors:
+ *   - David Girault <david.girault@qorvo.com>
+ *   - Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <net/mac802154.h>
+
+#include "ieee802154_i.h"
+#include "driver-ops.h"
+#include "../ieee802154/nl802154.h"
+
+static bool mac802154_is_promiscuous(struct ieee802154_local *local)
+{
+	struct ieee802154_sub_if_data *sdata;
+	bool promiscuous = false;
+
+	/* Check if one subif is already in promiscuous mode. Since the list is
+	 * protected by its own mutex, take it here to ensure no modification
+	 * occurs during the check.
+	 */
+	rcu_read_lock();
+	list_for_each_entry(sdata, &local->interfaces, list) {
+		if (ieee802154_sdata_running(sdata) &&
+		    sdata->wpan_dev.promiscuous_mode) {
+			/* At least one is in promiscuous mode */
+			promiscuous = true;
+			break;
+		}
+	}
+	rcu_read_unlock();
+
+	return promiscuous;
+}
+
+static int mac802154_set_promiscuous_mode(struct ieee802154_local *local,
+					  bool state)
+{
+	int ret, ret_start;
+
+	drv_stop(local);
+	synchronize_net();
+
+	if (state)
+		local->hw.phy->filtering = IEEE802154_FILTERING_2_PROMISCUOUS;
+	else
+		local->hw.phy->filtering = IEEE802154_FILTERING_4_FRAME_FIELDS;
+
+	ret = drv_set_promiscuous_mode(local, state);
+	if (ret)
+		pr_err("Scan configuration failure: cannot %s promiscuous mode",
+		       state ? "set" : "reset");
+	ret_start = drv_start(local);
+
+	return ret ? ret : ret_start;
+}
+
+static int mac802154_send_scan_done(struct ieee802154_local *local, u8 cmd)
+{
+	struct cfg802154_scan_request *scan_req;
+	struct wpan_phy *wpan_phy;
+	struct wpan_dev *wpan_dev;
+
+	scan_req = rcu_dereference_protected(local->scan_req,
+					     lockdep_is_held(&local->scan_lock));
+	wpan_phy = scan_req->wpan_phy;
+	wpan_dev = scan_req->wpan_dev;
+
+	cfg802154_flush_known_coordinators(wpan_dev);
+
+	return nl802154_send_scan_done(wpan_phy, wpan_dev, scan_req, cmd);
+}
+
+static int mac802154_end_of_scan(struct ieee802154_local *local, bool aborted)
+{
+	u8 cmd;
+
+	drv_set_channel(local, local->phy->current_page,
+			local->phy->current_channel);
+	ieee802154_configure_durations(local->phy, local->phy->current_page,
+				       local->phy->current_channel);
+
+	clear_bit(IEEE802154_IS_SCANNING, &local->ongoing);
+	if (!local->was_promiscuous)
+		mac802154_set_promiscuous_mode(local, false);
+	ieee802154_mlme_op_post(local);
+	module_put(local->hw.parent->driver->owner);
+
+	cmd = aborted ? NL802154_CMD_ABORT_SCAN : NL802154_CMD_SCAN_DONE;
+
+	return mac802154_send_scan_done(local, cmd);
+}
+
+int mac802154_abort_scan_locked(struct ieee802154_local *local)
+{
+	lockdep_assert_held(&local->scan_lock);
+
+	if (!mac802154_is_scanning(local))
+		return -ESRCH;
+
+	cancel_delayed_work(&local->scan_work);
+
+	return mac802154_end_of_scan(local, true);
+}
+
+static unsigned int mac802154_scan_get_channel_time(u8 duration_order,
+						    u8 symbol_duration)
+{
+	u64 base_super_frame_duration = (u64)symbol_duration *
+		IEEE802154_SUPERFRAME_PERIOD * IEEE802154_SLOT_PERIOD;
+
+	return usecs_to_jiffies(base_super_frame_duration *
+				(BIT(duration_order) + 1));
+}
+
+void mac802154_flush_queued_beacons(struct ieee802154_local *local)
+{
+	struct cfg802154_mac_pkt *beacon, *tmp;
+
+	lockdep_assert_held(&local->scan_lock);
+
+	list_for_each_entry_safe(beacon, tmp, &local->rx_beacon_list, node) {
+		list_del(&beacon->node);
+		kfree_skb(beacon->skb);
+		kfree(beacon);
+	}
+}
+
+void mac802154_scan_worker(struct work_struct *work)
+{
+	struct ieee802154_local *local =
+		container_of(work, struct ieee802154_local, scan_work.work);
+	struct cfg802154_scan_request *scan_req;
+	struct ieee802154_sub_if_data *sdata;
+	unsigned int scan_duration;
+	unsigned long chan;
+	int ret;
+
+	/* In practice we don't really need the rtnl here, besides for the
+	 * drv_set_channel() operation. Unfortunately, as the rtnl is always
+	 * taken before any other lock, we must acquire it before scan_lock() to
+	 * avoid circular dependencies.
+	 */
+	rtnl_lock();
+	mutex_lock(&local->scan_lock);
+
+	if (!mac802154_is_scanning(local))
+		goto unlock_mutex;
+
+	scan_req = rcu_dereference_protected(local->scan_req,
+					     lockdep_is_held(&local->scan_lock));
+	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(scan_req->wpan_dev);
+
+	if (local->suspended || !ieee802154_sdata_running(sdata))
+		goto queue_work;
+
+	do {
+		chan = find_next_bit((const unsigned long *)&scan_req->channels,
+				     IEEE802154_MAX_CHANNEL + 1,
+				     local->scan_channel_idx + 1);
+
+		/* If there are no more channels left, complete the scan */
+		if (chan > IEEE802154_MAX_CHANNEL) {
+			mac802154_end_of_scan(local, false);
+			goto unlock_mutex;
+		}
+
+		/* Bypass the stack on purpose. As the channel change cannot be
+		 * made atomic with regard to the incoming beacon flow, we flush
+		 * the beacons list after changing the channel and before
+		 * releasing the scan lock, to avoid processing beacons which
+		 * have been received during this time frame.
+		 */
+		ret = drv_set_channel(local, scan_req->page, chan);
+		local->scan_channel_idx = chan;
+		ieee802154_configure_durations(local->phy, scan_req->page, chan);
+		mac802154_flush_queued_beacons(local);
+	} while (ret);
+
+queue_work:
+	scan_duration = mac802154_scan_get_channel_time(scan_req->duration,
+							local->phy->symbol_duration);
+	pr_debug("Scan channel %lu of page %u for %ums\n",
+		 chan, scan_req->page, jiffies_to_msecs(scan_duration));
+	queue_delayed_work(local->mac_wq, &local->scan_work, scan_duration);
+
+unlock_mutex:
+	mutex_unlock(&local->scan_lock);
+	rtnl_unlock();
+}
+
+int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_scan_request *request)
+{
+	struct ieee802154_local *local = sdata->local;
+	int ret;
+
+	lockdep_assert_held(&local->scan_lock);
+
+	if (mac802154_is_scanning(local))
+		return -EBUSY;
+
+	/* TODO: support other scanning type */
+	if (request->type != NL802154_SCAN_PASSIVE)
+		return -EOPNOTSUPP;
+
+	/* Store scanning parameters */
+	rcu_assign_pointer(local->scan_req, request);
+
+	/* Software scanning requires to set promiscuous mode, so we need to
+	 * pause the Tx queue during the entire operation.
+	 */
+	ieee802154_mlme_op_pre(local);
+
+	if (mac802154_is_promiscuous(local)) {
+		local->was_promiscuous = true;
+	} else {
+		local->was_promiscuous = false;
+		ret = mac802154_set_promiscuous_mode(local, true);
+		if (ret)
+			goto cancel_mlme;
+	}
+
+	local->scan_channel_idx = -1;
+	set_bit(IEEE802154_IS_SCANNING, &local->ongoing);
+
+	/* Starting a background job, ensure the module cannot be removed */
+	if (!try_module_get(local->hw.parent->driver->owner)) {
+		ret = -ENODEV;
+		goto cancel_promiscuous_mode;
+	}
+
+	queue_delayed_work(local->mac_wq, &local->scan_work, 0);
+
+	nl802154_send_start_scan(local->scan_req->wpan_phy,
+				 local->scan_req->wpan_dev);
+
+	return 0;
+
+cancel_promiscuous_mode:
+	clear_bit(IEEE802154_IS_SCANNING, &local->ongoing);
+	if (!local->was_promiscuous)
+		mac802154_set_promiscuous_mode(local, false);
+cancel_mlme:
+	ieee802154_mlme_op_post(local);
+	return ret;
+}
+
+int mac802154_process_beacon(struct ieee802154_local *local,
+			     struct sk_buff *skb)
+{
+	struct ieee802154_beacon_hdr *bh = (void *)skb->data;
+	struct ieee802154_addr *src = &mac_cb(skb)->source;
+	struct cfg802154_scan_request *scan_req;
+	struct ieee802154_coord_desc *desc;
+
+	/* Check the validity of the frame length */
+	if (skb->len < sizeof(*bh))
+		return -EINVAL;
+
+	if (unlikely(src->mode == IEEE802154_ADDR_NONE))
+		return -EINVAL;
+
+	scan_req = rcu_dereference_protected(local->scan_req,
+					     &local->scan_lock);
+	if (unlikely(!scan_req))
+		return -EINVAL;
+
+	pr_debug("Beacon received on channel %d of page %d\n",
+		 local->scan_channel_idx, scan_req->page);
+
+	/* Parse beacon, create PAN information and forward to upper layers */
+	desc = cfg802154_alloc_coordinator(src);
+	if (!desc)
+		return -ENOMEM;
+
+	desc->page = scan_req->page;
+	desc->channel = local->scan_channel_idx;
+	desc->link_quality = mac_cb(skb)->lqi;
+	desc->superframe_spec = get_unaligned_le16(skb->data);
+	desc->gts_permit = bh->gts_permit;
+	cfg802154_record_coordinator(scan_req->wpan_phy, scan_req->wpan_dev, desc);
+
+	return 0;
+}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels
  2022-08-26 14:40 ` [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Miquel Raynal
@ 2022-09-04 17:13   ` Alexander Aring
  0 siblings, 0 replies; 14+ messages in thread
From: Alexander Aring @ 2022-09-04 17:13 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Alexander Aring, Stefan Schmidt, linux-wpan - ML,
	David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	Network Development, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Thomas Petazzoni

Hi,

On Fri, Aug 26, 2022 at 10:41 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> The 802154 specification details several filtering levels in which the
> PHY and the MAC could be. The amount of filtering will vary if they are
> in promiscuous mode or in scanning mode. Otherwise they are expected to
> do some very basic checks, such as enforcing the frame validity. Either
> the PHY is able to do so, and the MAC has nothing to do, or the PHY has
> a lower filtering level than expected and the MAC should take over.
>
> For now we define these levels in an enumeration, we add a per-PHY
> parameter showing the PHY filtering level and we set it to a default
> value. The drivers, if they cannot reach this level of filtering, should
> overwrite this value so that it reflects what they do. Then, in the
> core, this filtering level will be used to decide whether some
> additional software processing is needed or not.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  include/net/cfg802154.h |  3 +++
>  include/net/mac802154.h | 24 ++++++++++++++++++++++++
>  net/mac802154/iface.c   |  2 ++
>  3 files changed, 29 insertions(+)
>
> diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> index 04b996895fc1..2f29e95da47a 100644
> --- a/include/net/cfg802154.h
> +++ b/include/net/cfg802154.h
> @@ -223,6 +223,9 @@ struct wpan_phy {
>         atomic_t hold_txs;
>         wait_queue_head_t sync_txq;
>
> +       /* Current filtering level on reception */
> +       unsigned long filtering;
> +

enum ieee802154_filtering_level?

>         char priv[] __aligned(NETDEV_ALIGN);
>  };
>
> diff --git a/include/net/mac802154.h b/include/net/mac802154.h
> index 357d25ef627a..41c28118790c 100644
> --- a/include/net/mac802154.h
> +++ b/include/net/mac802154.h
> @@ -130,6 +130,30 @@ enum ieee802154_hw_flags {
>  #define IEEE802154_HW_OMIT_CKSUM       (IEEE802154_HW_TX_OMIT_CKSUM | \
>                                          IEEE802154_HW_RX_OMIT_CKSUM)
>
> +/**
> + * enum ieee802154_filtering_level - Filtering levels applicable to a PHY
> + *
> + * @IEEE802154_FILTERING_NONE: No filtering at all, what is received is
> + *     forwarded to the softMAC
> + * @IEEE802154_FILTERING_1_FCS: First filtering level, frames with an invalid
> + *     FCS should be dropped
> + * @IEEE802154_FILTERING_2_PROMISCUOUS: Second filtering level, promiscuous
> + *     mode, identical in terms of filtering to the first level at the PHY
> + *     level, but no ACK should be transmitted automatically and at the MAC
> + *     level the frame should be forwarded to the upper layer directly

You have no ACK back in all filtering levels except in
IEEE802154_FILTERING_4_FRAME_FIELDS. It is some kind of mixed thing
between "receive mode and filtering mode" but I am fine with it.

> + * @IEEE802154_FILTERING_3_SCAN: Third filtering level, enforced during scans,
> + *     which only forwards beacons
> + * @IEEE802154_FILTERING_4_FRAME_FIELDS: Fourth filtering level actually
> + *     enforcing the validity of the content of the frame with various checks
> + */
> +enum ieee802154_filtering_level {
> +       IEEE802154_FILTERING_NONE,
> +       IEEE802154_FILTERING_1_FCS,
> +       IEEE802154_FILTERING_2_PROMISCUOUS,
> +       IEEE802154_FILTERING_3_SCAN,
> +       IEEE802154_FILTERING_4_FRAME_FIELDS,
> +};
> +
>  /* struct ieee802154_ops - callbacks from mac802154 to the driver
>   *
>   * This structure contains various callbacks that the driver may
> diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
> index 500ed1b81250..4bab2807acbe 100644
> --- a/net/mac802154/iface.c
> +++ b/net/mac802154/iface.c
> @@ -587,6 +587,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
>                 sdata->dev->netdev_ops = &mac802154_wpan_ops;
>                 sdata->dev->ml_priv = &mac802154_mlme_wpan;
>                 wpan_dev->promiscuous_mode = false;
> +               wpan_dev->wpan_phy->filtering = IEEE802154_FILTERING_4_FRAME_FIELDS;
>                 wpan_dev->header_ops = &ieee802154_header_ops;
>
>                 mutex_init(&sdata->sec_mtx);
> @@ -601,6 +602,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
>                 sdata->dev->needs_free_netdev = true;
>                 sdata->dev->netdev_ops = &mac802154_monitor_ops;
>                 wpan_dev->promiscuous_mode = true;
> +               wpan_dev->wpan_phy->filtering = IEEE802154_FILTERING_2_PROMISCUOUS;

In my opinion this is currently IEEE802154_FILTERING_NONE ?

- Alex


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM
  2022-08-26 14:40 ` [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM Miquel Raynal
@ 2022-09-05  1:34   ` Alexander Aring
  0 siblings, 0 replies; 14+ messages in thread
From: Alexander Aring @ 2022-09-05  1:34 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Alexander Aring, Stefan Schmidt, linux-wpan - ML,
	David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
	Network Development, David Girault, Romuald Despres,
	Frederic Blain, Nicolas Schodet, Thomas Petazzoni

Hi,

On Fri, Aug 26, 2022 at 10:41 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> This IEEE802154_HW_RX_DROP_BAD_CKSUM flag was only used by hwsim to
> reflect the fact that it would not validate the checksum (FCS). In other
> words, the filtering level of hwsim is always "NONE" while the core
> expects it to be higher.
>
> Now that we have access to real filtering levels, we can actually use
> them and always enforce the "NONE" level in hwsim. Handling this case
> correctly in the receive path permits to drop the above mentioned flag.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
>  drivers/net/ieee802154/mac802154_hwsim.c | 10 +++++++++-
>  include/net/mac802154.h                  |  4 ----
>  net/mac802154/rx.c                       |  6 ++----
>  3 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c
> index 38c217bd7c82..d7e4048e8743 100644
> --- a/drivers/net/ieee802154/mac802154_hwsim.c
> +++ b/drivers/net/ieee802154/mac802154_hwsim.c
> @@ -148,6 +148,8 @@ static int hwsim_hw_start(struct ieee802154_hw *hw)
>         struct hwsim_phy *phy = hw->priv;
>
>         phy->suspended = false;
> +       hw->phy->filtering = IEEE802154_FILTERING_NONE;
> +
>         return 0;
>  }
>
> @@ -161,6 +163,9 @@ static void hwsim_hw_stop(struct ieee802154_hw *hw)
>  static int
>  hwsim_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
>  {
> +       /* hwsim does not filter anything, so enforce the NONE level */
> +       hw->phy->filtering = IEEE802154_FILTERING_NONE;
> +
>         return 0;
>  }
>
> @@ -791,7 +796,10 @@ static int hwsim_add_one(struct genl_info *info, struct device *dev,
>         phy->idx = idx;
>         INIT_LIST_HEAD(&phy->edges);
>
> -       hw->flags = IEEE802154_HW_PROMISCUOUS | IEEE802154_HW_RX_DROP_BAD_CKSUM;
> +       /* This is a lie, hwsim does not even filter bad FCS, but we need to
> +        * advertize a PROMISCUOUS to be able to create COORD interfaces.
> +        */

I think this is now different because PROMISCUOUS/any disable address
filtering will disable AACK and this is not what we want, or? This
comment was made with the assumption to deal with acks which we can't?

I did not look further into this patch series yet.

- Alex


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2022-09-05  1:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-26 14:40 [PATCH wpan-next v2 00/11] net: ieee802154: Support scanning/beaconing Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Miquel Raynal
2022-09-04 17:13   ` Alexander Aring
2022-08-26 14:40 ` [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM Miquel Raynal
2022-09-05  1:34   ` Alexander Aring
2022-08-26 14:40 ` [PATCH wpan-next v2 03/11] net: mac802154: Allow the creation of coordinator interfaces Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 04/11] net: ieee802154: Advertize coordinators discovery Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 05/11] net: ieee802154: Handle " Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 06/11] net: ieee802154: Trace the registration of new PANs Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 07/11] net: ieee802154: Add support for user scanning requests Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 08/11] net: ieee802154: Define a beacon frame header Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 09/11] net: mac802154: Prepare forcing specific symbol duration Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 10/11] net: mac802154: Introduce a global device lock Miquel Raynal
2022-08-26 14:40 ` [PATCH wpan-next v2 11/11] net: mac802154: Handle passive scanning Miquel Raynal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).