From patchwork Fri Aug 26 14:40:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956127 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23E82ECAAA3 for ; Fri, 26 Aug 2022 14:41:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344515AbiHZOlF (ORCPT ); Fri, 26 Aug 2022 10:41:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48682 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229472AbiHZOk7 (ORCPT ); Fri, 26 Aug 2022 10:40:59 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C2EA2ABD7C; Fri, 26 Aug 2022 07:40:57 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 80CD31BF215; Fri, 26 Aug 2022 14:40:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524856; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MhPle3Loc9DzyWn1KWs/wY2k+T6fObmYwcJpPw+b7n0=; b=APwf/jHh9Eqc5GxoFMTZ7zEWgKx3MZL6iq4XqIACYYGjLdJ3EMY88kXhkikVnB92FYb18y vOTgTbDdZsPB94gf1Ak5qWhOEY9zZRiHDq4SIv/NTh1lxF7iCSsuqsir9V2E2IPR3fTUh8 i24n81WUcXxQB4w168WMJz1rO3f2lRGDPaXSA+J5QDrtWdWCqkPpDeSWUlDcRL69Rqf7hg 1wXxhfjTXCl0DOtEWdOpGST+kY3cn2SzONLAaWz1Kn3l/HhsSoEjbmkrST8TmoCUncmbFk IBEwXPx9vj0UtUvCNNLpt1wRSlFYy63mAax1habSfqL6FU0fniSQ2hccgrxhnA== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 01/11] net: mac802154: Introduce filtering levels Date: Fri, 26 Aug 2022 16:40:39 +0200 Message-Id: <20220826144049.256134-2-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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(); From patchwork Fri Aug 26 14:40:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956128 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11E5FECAAD7 for ; Fri, 26 Aug 2022 14:41:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344521AbiHZOlG (ORCPT ); Fri, 26 Aug 2022 10:41:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48768 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344480AbiHZOlC (ORCPT ); Fri, 26 Aug 2022 10:41:02 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9ED0ACC33F; Fri, 26 Aug 2022 07:40:59 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 6B0261BF20D; Fri, 26 Aug 2022 14:40:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524858; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fY3AHa++QoYX1T0AIKr3WtVFrfOKMtJ/BSj+z0SXYXs=; b=Y1Pnxs8fvUcI7jFf4rLyWWsYZzDFcWmWoM5jEiHBqVq2TpYFfQyDrgvdfLyrWAfS5t/u9r yGRqJWBqvwp7lVEipSvvt3i42pPMCP9psTM9OTwp2bGTbra65Q/bjeDng7xBfkcPI8nra6 LmZppEDxengmW1LBF51bsrPe+qZRdWlBR9MGc+oQi1CNnfQMt0trV7l/XyoLo5dksBl8rZ vvhlt4Z6QKwHNifMBH6jS8p4i+HmeKLZTyDZeFuTQ3/rTgRJYsd+AI+p8PEkOLYTbQzDD0 TkgZxRIPB3Sqe2I7jqZp7pEK5BPplPR0mEZkokSqC9d++kowSxVlep819+Itkw== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 02/11] net: mac802154: Drop IEEE802154_HW_RX_DROP_BAD_CKSUM Date: Fri, 26 Aug 2022 16:40:40 +0200 Message-Id: <20220826144049.256134-3-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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(); From patchwork Fri Aug 26 14:40:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956129 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD180ECAAD9 for ; Fri, 26 Aug 2022 14:41:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344526AbiHZOlG (ORCPT ); Fri, 26 Aug 2022 10:41:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48860 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344510AbiHZOlE (ORCPT ); Fri, 26 Aug 2022 10:41:04 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B7C2B2D85; Fri, 26 Aug 2022 07:41:01 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 98DF81BF208; Fri, 26 Aug 2022 14:40:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524860; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a9IYMuDIyxj+HLkgz7Y6Y6sR1gMiuEZfqG+jyTP97zw=; b=Y8WCw1KNvwhVvLgVRZjtpgUCVwfCwTMQkofzkAIgT2za+K0E5EirGA7Tuic/KShBF+V73j Q6+p60TdklKxuOmQm0ZMMHFpENsvOO44F+Bb3q1TOPvIn9AIFoQcU5aeUCE3+J5+N977EP leSB6NBoAE4ngs/ElCxvkPi8NuvkkoVUuvWOxqZgy6xYJ201hKk3Y1zP/IbRlk88QBqEo7 RNbiAg20In7FJYqjdQhWwYRsxN56muz6LKU9kuabCVXFuwFOoJ3d1AkElLLBoPve6qSQI/ JBoox4DZiJKtGiFs9SnderUA4B1+wcS4Wjy1ebKyEH6tk6VWaPWPKdV6HHzVvg== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 03/11] net: mac802154: Allow the creation of coordinator interfaces Date: Fri, 26 Aug 2022 16:40:41 +0200 Message-Id: <20220826144049.256134-4-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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); From patchwork Fri Aug 26 14:40:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956130 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 177C5ECAAA3 for ; Fri, 26 Aug 2022 14:41:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344529AbiHZOlQ (ORCPT ); Fri, 26 Aug 2022 10:41:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48980 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344507AbiHZOlG (ORCPT ); Fri, 26 Aug 2022 10:41:06 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0784DD34EF; Fri, 26 Aug 2022 07:41:04 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 133ED1BF20F; Fri, 26 Aug 2022 14:41:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524863; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=YcBfJGWfJBPwMcIKjGk6npj52Nug+5Ik8yfWqck5EIc=; b=iSFvW1PL+TKJxDbpF71Crv/lqWrRpd3twVsgTGCGdJg02MWPhK1oUZcnER2hYEPlfIFewj xVp3nAz7FFWRjDezIhVjCNpe9u90XRSUR1xHc5L6X+ayhDgfh0v1/R52rEqlrUOzPk+UyI H76wOlf1x3idTl1itRkNlXEiLacg6ldXzPBVrvjAoN9ntV40nIjWXSj70tXvprDAHyvCyK F3yfauBHIPMB+7R0qDdZmhMd03o+6kew3EA+CkmFdgcsQj9Uif9txjj6a1yIbgfWI180R+ BphEGQbYppcS3XOg9g5FGCKHZpbfmqEZArFN9JrGqltgEgFwCf1+1ICYRp3c4w== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 04/11] net: ieee802154: Advertize coordinators discovery Date: Fri, 26 Aug 2022 16:40:42 +0200 Message-Id: <20220826144049.256134-5-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 Signed-off-by: David Girault Signed-off-by: Miquel Raynal --- 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 */ From patchwork Fri Aug 26 14:40:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956132 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 161D8ECAAD6 for ; Fri, 26 Aug 2022 14:41:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344544AbiHZOlR (ORCPT ); Fri, 26 Aug 2022 10:41:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49070 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344510AbiHZOlI (ORCPT ); Fri, 26 Aug 2022 10:41:08 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 94D9CD3996; Fri, 26 Aug 2022 07:41:06 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 6D9951BF20C; Fri, 26 Aug 2022 14:41:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524865; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rQPNtDm8zYc/dgbrnGnAMfeRFxGCXSici07duwx2Zbk=; b=ewMDK3ZfiASHJPmhvdinclHZkoxUrxtRABgvMYAvOGgaGq0jXMw+cu81Tdb/hFMPxV00p6 WUDNUHTY7Mv9iH3bOQiw5gMvJt4tCyhak5fzmQG2kN4pcIQOxWkBa1wnV0AJnu96Sg9VHx EMatuzdD2I5bwN1Y5aQzbwc6djtzGhRtIP2K2xKroGI2/vMUVF2QktdmfFPtb21WdgkQfU VwttDjLMNwdnjUhqxlEeb+5eXANdOJF8DPFUeUBmUELJVaLDDRFRwQmIxEsW6Biar5J02U 5t+8Y1WVNX+VbB2waR22mP5XtIknWWdsadSLvuDLcJ/o3fC+XJJRJ8xT5e4Q8A== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 05/11] net: ieee802154: Handle coordinators discovery Date: Fri, 26 Aug 2022 16:40:43 +0200 Message-Id: <20220826144049.256134-6-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 Signed-off-by: David Girault Signed-off-by: Miquel Raynal --- 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 + * - Miquel Raynal + */ + +#include +#include +#include +#include + +#include +#include + +#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); From patchwork Fri Aug 26 14:40:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956131 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8297EECAAD9 for ; Fri, 26 Aug 2022 14:41:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229991AbiHZOlS (ORCPT ); Fri, 26 Aug 2022 10:41:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344524AbiHZOlP (ORCPT ); Fri, 26 Aug 2022 10:41:15 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7D75ED4775; Fri, 26 Aug 2022 07:41:09 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 94ED01BF207; Fri, 26 Aug 2022 14:41:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524867; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ajt4B69LYjejgNbGEH2ZBoXmoFMV0MROjIzP4TuvpyA=; b=nLwYtks8TJFjNL/MZlSuqKIGaDJf90Y+soH1lEZj70pPwOzqqUMjkFbO7HplUJWf522cwp ofV8J2Ct7RoHBZnAHTzTm4SGKXE1w8SSZcm6vq8VHrUj8wohFhxNLelvEOPfPJeMjfUML/ Jx0kD/TII87FvtMsIeQsc1REhJDe/F5/4txZcEW9j8i8uDUk2U6K8eP0EHvjZPcBUlOcRs TIMBDuzQno+9kfnAktPcFlkyiNXPvKRj8qD+82p3ZJZJNfK6NL9t3cZvqqcovvq8DPyf5O sfDnrUfbDpLpwhmKLpTPRGUkwJBj9GJqdjwNpyUioJ/4kd3IXCe30VTO4pLYeg== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 06/11] net: ieee802154: Trace the registration of new PANs Date: Fri, 26 Aug 2022 16:40:44 +0200 Message-Id: <20220826144049.256134-7-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org From: David Girault Add an internal trace when new PANs get discovered. Signed-off-by: David Girault Signed-off-by: Miquel Raynal --- 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), From patchwork Fri Aug 26 14:40:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956133 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D59E3ECAAD4 for ; Fri, 26 Aug 2022 14:41:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344524AbiHZOlU (ORCPT ); Fri, 26 Aug 2022 10:41:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344539AbiHZOlR (ORCPT ); Fri, 26 Aug 2022 10:41:17 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38E44D51D7; Fri, 26 Aug 2022 07:41:12 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 20ECD1BF20D; Fri, 26 Aug 2022 14:41:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524870; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=F99vujeIUMt75rvBW+iqot9s0sjDiMthz0JjVk4hsqw=; b=pyTnzKO9G2qHKwIxGGqbqr/8ry2dCZv2/oMhoNrPnlTehstDE0dsU2jc8UE7KjnPqQ7TXY oGZDjlbsAoAjrq02danJZS8dDsKVJcQUBt5eZ0s9UsOfh+pGiijkdZiPmHAmyeMLTESkS6 ccp/pwDA8FXoTjfkmLYWDhfNDSeS3x+D/Q2JTeh/EwlPBpnGG++lfJl3DpQZ/WE76XkX8p VnQTw8B84L54W2inMJHNq+VULphbPxPd4iDnrgItRIqWN+0maUmEdnH8vCN8/8eVYfH7Xo dzFxDsBAM2qreNPwZN2Vt8LO2ZrvMyie15akXFLYnB7WT9vfb8v3tJ4HJfAwgg== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 07/11] net: ieee802154: Add support for user scanning requests Date: Fri, 26 Aug 2022 16:40:45 +0200 Message-Id: <20220826144049.256134-8-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 Signed-off-by: David Girault Signed-off-by: Miquel Raynal --- 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), From patchwork Fri Aug 26 14:40:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956134 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 89AEFECAAD4 for ; Fri, 26 Aug 2022 14:41:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344561AbiHZOlf (ORCPT ); Fri, 26 Aug 2022 10:41:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49762 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344543AbiHZOlR (ORCPT ); Fri, 26 Aug 2022 10:41:17 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 943F1D5EAB; Fri, 26 Aug 2022 07:41:14 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id BA3941BF205; Fri, 26 Aug 2022 14:41:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524873; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9wcgIyPGRS/zviXahs9+8cWYo2rex5zR9iCJofdW/9A=; b=iF31hzAUFE5ZIwmHVpsNoL6o7zvpuOYwv/bcfMhuVPfhGuIk7N18OFXJvozZ7U6C8WlV+1 fNgIenm4NqWv5QLTZ5DNvK/9jmSW7w7bhxF18KMdr0GGITopMNDjPU133bEUBV7XK5VyWf W5Uqch+znhjSgLrXRGZ0uA8WUG/YG0Ds3gzPeqFcMzBeE/dCRpyRxaKUGF0XlFQy4lT/T2 VPPNhvAPLZm5PEHUfisxY8JdCJYFmH0fwA3NkB22hGVi0lf0jnWg353xQEPF05wF11iOSm omALcMGSu1jyDZmXgKk/i5l6bdU2LZYGyUnC8FZW23g6zsfZtlMy7lDKaXhkig== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 08/11] net: ieee802154: Define a beacon frame header Date: Fri, 26 Aug 2022 16:40:46 +0200 Message-Id: <20220826144049.256134-9-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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 +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 " +#endif +} __packed; + struct ieee802154_sechdr { #if defined(__LITTLE_ENDIAN_BITFIELD) u8 level:3, From patchwork Fri Aug 26 14:40:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956135 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2B0D2ECAAD6 for ; Fri, 26 Aug 2022 14:41:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344527AbiHZOlg (ORCPT ); Fri, 26 Aug 2022 10:41:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49500 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344534AbiHZOlU (ORCPT ); Fri, 26 Aug 2022 10:41:20 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C70CD4778; Fri, 26 Aug 2022 07:41:18 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id D9FF11BF203; Fri, 26 Aug 2022 14:41:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524877; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=T/TjOBws9BlYMi86wO8enSKNjnRfsDv6RtLZHMwuCVQ=; b=MvGmAVyVjDnn4bO9PnScsWpjIS8+KUwpQUXOG6nPT5dbQLoR/rQBl1TxvkgFfZVUtK4hGi HGJIX9qCc/PsGZJsJD8WG5diDq0zUXxLEmIb4IG/BLXx83BgDPMfYKgSrxWhOOWaS3dSl9 2WFW2WC9lm5dT93AgyeJHj3TnrXho3/f1xZxn/OElk2ZYKxXKYCLIDL9bXTSlesxRjFSuB 6HIKPDUjK2mYn0eOWBl6F+DGX92NzygcY9ip5oaDu9pZDBBdx8ABTpfcGKVChBRATfZFmR lZaqyC/78QKQT4q4kdWDH1TekHoLgP7uKSmdSdauRSSZ0aOmh4S/q9WDpyieBQ== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 09/11] net: mac802154: Prepare forcing specific symbol duration Date: Fri, 26 Aug 2022 16:40:47 +0200 Message-Id: <20220826144049.256134-10-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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; From patchwork Fri Aug 26 14:40:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956136 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A69A2ECAAA3 for ; Fri, 26 Aug 2022 14:41:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344545AbiHZOlj (ORCPT ); Fri, 26 Aug 2022 10:41:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50934 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344550AbiHZOlf (ORCPT ); Fri, 26 Aug 2022 10:41:35 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::228]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AB0AD6B80; Fri, 26 Aug 2022 07:41:21 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 926AA1BF20E; Fri, 26 Aug 2022 14:41:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524879; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=R/8hmzcZzU+Wlnj6uuVvpnUs67HRcrTDHdMDKmnQy9o=; b=Ptx3z5lRmgmViLyPnGGAsQa2wRDWE0nM8HC4iHCr8NLxHQgJXFQdsKWv8rovmQV5IrKpdu GeMsGuGK8QGfhIfYOiOYv5acxopIogLUkVhvwLtNmtAvouzBCsYfOk68xeh9Df8GzDtNsJ lNYDznmmCQBK90ppzW35YCe2H/m7uUbWZcgovaynMWuneRnGpJCk2Fo33yVxzDZSf/wD4S FdF7MFHuTUIW//raBOxvusgcouQPU+mDwyTTN0E/arf5atlfRyR9kD5FuPN9J5br1lo0lo Rsi9tAPwntPhXOl31sowwJ0JiYDjZbsg9eBu2bG6X810Uh3zQwh3VeFeHIqWXA== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 10/11] net: mac802154: Introduce a global device lock Date: Fri, 26 Aug 2022 16:40:48 +0200 Message-Id: <20220826144049.256134-11-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 --- 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; } From patchwork Fri Aug 26 14:40:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Miquel Raynal X-Patchwork-Id: 12956137 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 141A3ECAAD4 for ; Fri, 26 Aug 2022 14:41:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1344554AbiHZOlt (ORCPT ); Fri, 26 Aug 2022 10:41:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50974 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1344559AbiHZOlf (ORCPT ); Fri, 26 Aug 2022 10:41:35 -0400 Received: from relay8-d.mail.gandi.net (relay8-d.mail.gandi.net [217.70.183.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A20CDD7586; Fri, 26 Aug 2022 07:41:24 -0700 (PDT) Received: (Authenticated sender: miquel.raynal@bootlin.com) by mail.gandi.net (Postfix) with ESMTPSA id 415821BF20B; Fri, 26 Aug 2022 14:41:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1661524883; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MRxmk5U2NtM9dmjW2ZyDsahegM/fp9SMC4hkwCN2+Vs=; b=WnuKlg+4jz6I3wqfhq0pzx2PRF2IXVC9Z0+AT/uLuX84lpZqTKx6oft2Ht6RPPQcb5hqNu MM3huOC/JWE/NzInFelkZipJYXnp4I6JmaY3ETKBpPFeGYYmHIUT7NTNDdd+HhsWyVd1Qb vkeIRirorLCfjCMRAu8BJoUjJUcMSyf5PmgLJKDDRIC0sSUXbQ0/kUzACMruW0KF0DwzoW NiWrNd+S0QsjVUrMpoXMm9h4MTDUGGnTWFBHEp2YfNeRLswVrnFFdKg42HcJvdqTDGFEG6 Z9L3kxTTFtDlrL11nrtS2/DIXzQuh1IriBfhyznoH9wQS2VpQA38MCaEVZYG6Q== From: Miquel Raynal To: Alexander Aring , Stefan Schmidt , linux-wpan@vger.kernel.org Cc: "David S. Miller" , Jakub Kicinski , Paolo Abeni , Eric Dumazet , netdev@vger.kernel.org, David Girault , Romuald Despres , Frederic Blain , Nicolas Schodet , Thomas Petazzoni , Miquel Raynal Subject: [PATCH wpan-next v2 11/11] net: mac802154: Handle passive scanning Date: Fri, 26 Aug 2022 16:40:49 +0200 Message-Id: <20220826144049.256134-12-miquel.raynal@bootlin.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220826144049.256134-1-miquel.raynal@bootlin.com> References: <20220826144049.256134-1-miquel.raynal@bootlin.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org 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 Signed-off-by: David Girault Signed-off-by: Miquel Raynal --- 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 + * - Miquel Raynal + */ + +#include +#include +#include + +#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; +}