* [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-24 20:42 ` Alexander Aring
2023-09-22 15:50 ` [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management Miquel Raynal
` (9 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Soon association and disassociation will be implemented, which will
require to be able to either change the PAN ID from 0xFFFF to a real
value when association succeeded, or to reset the PAN ID to 0xFFFF upon
disassociation. Let's allow to do that manually for now.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
net/ieee802154/nl802154.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index d610c1886160..46ac6f599fe1 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1087,16 +1087,6 @@ static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
- /* TODO
- * I am not sure about to check here on broadcast pan_id.
- * Broadcast is a valid setting, comment from 802.15.4:
- * If this value is 0xffff, the device is not associated.
- *
- * This could useful to simple deassociate an device.
- */
- if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
- return -EINVAL;
-
return rdev_set_pan_id(rdev, wpan_dev, pan_id);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset
2023-09-22 15:50 ` [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset Miquel Raynal
@ 2023-09-24 20:42 ` Alexander Aring
2023-09-25 7:34 ` Miquel Raynal
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Aring @ 2023-09-24 20:42 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Fri, Sep 22, 2023 at 11:50 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Soon association and disassociation will be implemented, which will
> require to be able to either change the PAN ID from 0xFFFF to a real
> value when association succeeded, or to reset the PAN ID to 0xFFFF upon
> disassociation. Let's allow to do that manually for now.
>
ok. But keep in mind what happens when a device is associated and the
user sets a short address manually to 0xFFFF?
It should be a kind of forced mode of disassociation?
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset
2023-09-24 20:42 ` Alexander Aring
@ 2023-09-25 7:34 ` Miquel Raynal
0 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-25 7:34 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi Alexander,
aahringo@redhat.com wrote on Sun, 24 Sep 2023 16:42:31 -0400:
> Hi,
>
> On Fri, Sep 22, 2023 at 11:50 AM Miquel Raynal
> <miquel.raynal@bootlin.com> wrote:
> >
> > Soon association and disassociation will be implemented, which will
> > require to be able to either change the PAN ID from 0xFFFF to a real
> > value when association succeeded, or to reset the PAN ID to 0xFFFF upon
> > disassociation. Let's allow to do that manually for now.
> >
>
> ok. But keep in mind what happens when a device is associated and the
> user sets a short address manually to 0xFFFF?
>
> It should be a kind of forced mode of disassociation?
I believe once you start interacting with other devices with proper
associations, random user requests cannot all be addressed, in
particular once you are officially associated with another device, you
cannot change your own short address or PAN ID like that. So in the
right next series (after this one) I have a couple of small
additions through the tree to handle this kind of corner case. Here
is how it will look like in nl802154.c:
nl802154_set_short_addr():
/* The short address only has a meaning when part of a PAN, after a
* proper association procedure. However, we want to still offer the
* possibility to create static networks so changing the short address
* is only allowed when not already associated to other devices with
* the official handshake.
*/
if (cfg802154_device_is_associated(wpan_dev)) {
NL_SET_ERR_MSG(info->extack,
"Existing associations, changing short address forbidden");
return -EINVAL;
}
nl802154_set_pan_id():
/* Only allow changing the PAN ID when the device has no more
* associations ongoing to avoid confusing peers.
*/
if (cfg802154_device_is_associated(wpan_dev)) {
NL_SET_ERR_MSG(info->extack,
"Existing associations, changing PAN ID forbidden");
return -EINVAL;
}
I did not want to bloat this series with too much corner case handling,
so there are a couple of "misc additions" in the next series to handle
exactly that.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-24 20:47 ` Alexander Aring
2023-09-22 15:50 ` [PATCH wpan-next v4 03/11] ieee802154: Add support for user association requests Miquel Raynal
` (8 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Introduce structures to describe peer devices in a PAN as well as a few
related helpers. We basically care about:
- Our unique parent after associating with a coordinator.
- Peer devices, children, which successfully associated with us.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 47 ++++++++++++++++++++++++++
net/ieee802154/Makefile | 2 +-
net/ieee802154/core.c | 2 ++
net/ieee802154/pan.c | 73 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 123 insertions(+), 1 deletion(-)
create mode 100644 net/ieee802154/pan.c
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index f79ce133e51a..a89f1c9cea3f 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -303,6 +303,22 @@ struct ieee802154_coord_desc {
bool gts_permit;
};
+/**
+ * struct ieee802154_pan_device - PAN device information
+ * @pan_id: the PAN ID of this device
+ * @mode: the preferred mode to reach the device
+ * @short_addr: the short address of this device
+ * @extended_addr: the extended address of this device
+ * @node: the list node
+ */
+struct ieee802154_pan_device {
+ __le16 pan_id;
+ u8 mode;
+ __le16 short_addr;
+ __le64 extended_addr;
+ struct list_head node;
+};
+
/**
* struct cfg802154_scan_request - Scan request
*
@@ -478,6 +494,11 @@ struct wpan_dev {
/* fallback for acknowledgment bit setting */
bool ackreq;
+
+ /* Associations */
+ struct mutex association_lock;
+ struct ieee802154_pan_device *parent;
+ struct list_head children;
};
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
@@ -529,4 +550,30 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
void ieee802154_configure_durations(struct wpan_phy *phy,
unsigned int page, unsigned int channel);
+/**
+ * cfg802154_device_is_associated - Checks whether we are associated to any device
+ * @wpan_dev: the wpan device
+ * @return: true if we are associated
+ */
+bool cfg802154_device_is_associated(struct wpan_dev *wpan_dev);
+
+/**
+ * cfg802154_device_is_parent - Checks if a device is our coordinator
+ * @wpan_dev: the wpan device
+ * @target: the expected parent
+ * @return: true if @target is our coordinator
+ */
+bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target);
+
+/**
+ * cfg802154_device_is_child - Checks whether a device is associated to us
+ * @wpan_dev: the wpan device
+ * @target: the expected child
+ * @return: the PAN device
+ */
+struct ieee802154_pan_device *
+cfg802154_device_is_child(struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target);
+
#endif /* __NET_CFG802154_H */
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index f05b7bdae2aa..7bce67673e83 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 trace.o pan.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..cd69bdbfd59f 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++;
+ mutex_init(&wpan_dev->association_lock);
+ INIT_LIST_HEAD(&wpan_dev->children);
wpan_dev->netdev = dev;
break;
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
new file mode 100644
index 000000000000..1677bb89c5ff
--- /dev/null
+++ b/net/ieee802154/pan.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IEEE 802.15.4 PAN management
+ *
+ * Copyright (C) 2023 Qorvo US, Inc
+ * Authors:
+ * - David Girault <david.girault@qorvo.com>
+ * - Miquel Raynal <miquel.raynal@bootlin.com>
+ */
+
+#include <linux/kernel.h>
+#include <net/cfg802154.h>
+#include <net/af_ieee802154.h>
+
+/* Checks whether a device address matches one from the PAN list.
+ * This helper is meant to be used only during PAN management, when we expect
+ * extended addresses to be used.
+ */
+static bool cfg802154_device_in_pan(struct ieee802154_pan_device *pan_dev,
+ struct ieee802154_addr *ext_dev)
+{
+ if (!pan_dev || !ext_dev)
+ return false;
+
+ if (ext_dev->mode == IEEE802154_ADDR_SHORT)
+ return false;
+
+ switch (ext_dev->mode) {
+ case IEEE802154_ADDR_SHORT:
+ return pan_dev->short_addr == ext_dev->short_addr;
+ case IEEE802154_ADDR_LONG:
+ return pan_dev->extended_addr == ext_dev->extended_addr;
+ default:
+ return false;
+ }
+}
+
+bool cfg802154_device_is_associated(struct wpan_dev *wpan_dev)
+{
+ bool is_assoc;
+
+ mutex_lock(&wpan_dev->association_lock);
+ is_assoc = !list_empty(&wpan_dev->children) || wpan_dev->parent;
+ mutex_unlock(&wpan_dev->association_lock);
+
+ return is_assoc;
+}
+
+bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target)
+{
+ lockdep_assert_held(&wpan_dev->association_lock);
+
+ if (cfg802154_device_in_pan(wpan_dev->parent, target))
+ return true;
+
+ return false;
+}
+
+struct ieee802154_pan_device *
+cfg802154_device_is_child(struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target)
+{
+ struct ieee802154_pan_device *child;
+
+ lockdep_assert_held(&wpan_dev->association_lock);
+
+ list_for_each_entry(child, &wpan_dev->children, node)
+ if (cfg802154_device_in_pan(child, target))
+ return child;
+
+ return NULL;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management
2023-09-22 15:50 ` [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management Miquel Raynal
@ 2023-09-24 20:47 ` Alexander Aring
2023-09-27 16:10 ` Miquel Raynal
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Aring @ 2023-09-24 20:47 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Fri, Sep 22, 2023 at 11:50 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Introduce structures to describe peer devices in a PAN as well as a few
> related helpers. We basically care about:
> - Our unique parent after associating with a coordinator.
> - Peer devices, children, which successfully associated with us.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> include/net/cfg802154.h | 47 ++++++++++++++++++++++++++
> net/ieee802154/Makefile | 2 +-
> net/ieee802154/core.c | 2 ++
> net/ieee802154/pan.c | 73 +++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 123 insertions(+), 1 deletion(-)
> create mode 100644 net/ieee802154/pan.c
>
> diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> index f79ce133e51a..a89f1c9cea3f 100644
> --- a/include/net/cfg802154.h
> +++ b/include/net/cfg802154.h
> @@ -303,6 +303,22 @@ struct ieee802154_coord_desc {
> bool gts_permit;
> };
>
> +/**
> + * struct ieee802154_pan_device - PAN device information
> + * @pan_id: the PAN ID of this device
> + * @mode: the preferred mode to reach the device
> + * @short_addr: the short address of this device
> + * @extended_addr: the extended address of this device
> + * @node: the list node
> + */
> +struct ieee802154_pan_device {
> + __le16 pan_id;
> + u8 mode;
> + __le16 short_addr;
> + __le64 extended_addr;
> + struct list_head node;
> +};
> +
> /**
> * struct cfg802154_scan_request - Scan request
> *
> @@ -478,6 +494,11 @@ struct wpan_dev {
>
> /* fallback for acknowledgment bit setting */
> bool ackreq;
> +
> + /* Associations */
> + struct mutex association_lock;
> + struct ieee802154_pan_device *parent;
> + struct list_head children;
> };
>
> #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
> @@ -529,4 +550,30 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy)
> void ieee802154_configure_durations(struct wpan_phy *phy,
> unsigned int page, unsigned int channel);
>
> +/**
> + * cfg802154_device_is_associated - Checks whether we are associated to any device
> + * @wpan_dev: the wpan device
> + * @return: true if we are associated
> + */
> +bool cfg802154_device_is_associated(struct wpan_dev *wpan_dev);
> +
> +/**
> + * cfg802154_device_is_parent - Checks if a device is our coordinator
> + * @wpan_dev: the wpan device
> + * @target: the expected parent
> + * @return: true if @target is our coordinator
> + */
> +bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
> + struct ieee802154_addr *target);
> +
> +/**
> + * cfg802154_device_is_child - Checks whether a device is associated to us
> + * @wpan_dev: the wpan device
> + * @target: the expected child
> + * @return: the PAN device
> + */
> +struct ieee802154_pan_device *
> +cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> + struct ieee802154_addr *target);
> +
> #endif /* __NET_CFG802154_H */
> diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
> index f05b7bdae2aa..7bce67673e83 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 trace.o pan.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..cd69bdbfd59f 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++;
> + mutex_init(&wpan_dev->association_lock);
> + INIT_LIST_HEAD(&wpan_dev->children);
>
> wpan_dev->netdev = dev;
> break;
> diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
> new file mode 100644
> index 000000000000..1677bb89c5ff
> --- /dev/null
> +++ b/net/ieee802154/pan.c
> @@ -0,0 +1,73 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * IEEE 802.15.4 PAN management
> + *
> + * Copyright (C) 2023 Qorvo US, Inc
> + * Authors:
> + * - David Girault <david.girault@qorvo.com>
> + * - Miquel Raynal <miquel.raynal@bootlin.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <net/cfg802154.h>
> +#include <net/af_ieee802154.h>
> +
> +/* Checks whether a device address matches one from the PAN list.
> + * This helper is meant to be used only during PAN management, when we expect
> + * extended addresses to be used.
> + */
> +static bool cfg802154_device_in_pan(struct ieee802154_pan_device *pan_dev,
> + struct ieee802154_addr *ext_dev)
> +{
> + if (!pan_dev || !ext_dev)
> + return false;
> +
> + if (ext_dev->mode == IEEE802154_ADDR_SHORT)
> + return false;
> +
> + switch (ext_dev->mode) {
> + case IEEE802154_ADDR_SHORT:
> + return pan_dev->short_addr == ext_dev->short_addr;
This is dead code now, it will never be reached, it's checked above
(Or I don't see it)? I want to help you here. What exactly do you try
to reach here again?
> + case IEEE802154_ADDR_LONG:
> + return pan_dev->extended_addr == ext_dev->extended_addr;
> + default:
> + return false;
> + }
> +}
> +
> +bool cfg802154_device_is_associated(struct wpan_dev *wpan_dev)
> +{
> + bool is_assoc;
> +
> + mutex_lock(&wpan_dev->association_lock);
> + is_assoc = !list_empty(&wpan_dev->children) || wpan_dev->parent;
> + mutex_unlock(&wpan_dev->association_lock);
> +
> + return is_assoc;
> +}
> +
> +bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
> + struct ieee802154_addr *target)
> +{
> + lockdep_assert_held(&wpan_dev->association_lock);
> +
> + if (cfg802154_device_in_pan(wpan_dev->parent, target))
> + return true;
> +
> + return false;
return cfg802154_device_in_pan(...); Why isn't checkpatch warning about that?
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management
2023-09-24 20:47 ` Alexander Aring
@ 2023-09-27 16:10 ` Miquel Raynal
2023-09-29 0:22 ` Alexander Aring
0 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-27 16:10 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi Alexander,
> > +
> > +#include <linux/kernel.h>
> > +#include <net/cfg802154.h>
> > +#include <net/af_ieee802154.h>
> > +
> > +/* Checks whether a device address matches one from the PAN list.
> > + * This helper is meant to be used only during PAN management, when we expect
> > + * extended addresses to be used.
> > + */
> > +static bool cfg802154_device_in_pan(struct ieee802154_pan_device *pan_dev,
> > + struct ieee802154_addr *ext_dev)
> > +{
> > + if (!pan_dev || !ext_dev)
> > + return false;
> > +
> > + if (ext_dev->mode == IEEE802154_ADDR_SHORT)
> > + return false;
> > +
> > + switch (ext_dev->mode) {
> > + case IEEE802154_ADDR_SHORT:
> > + return pan_dev->short_addr == ext_dev->short_addr;
>
> This is dead code now, it will never be reached, it's checked above
> (Or I don't see it)? I want to help you here. What exactly do you try
> to reach here again?
It's a left over. All association/disassociation operation so far which
need these checks are operated using extended addressing (from the
spec). I will simplify further this helper.
> > +bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
> > + struct ieee802154_addr *target)
> > +{
> > + lockdep_assert_held(&wpan_dev->association_lock);
> > +
> > + if (cfg802154_device_in_pan(wpan_dev->parent, target))
> > + return true;
> > +
> > + return false;
>
> return cfg802154_device_in_pan(...); Why isn't checkpatch warning about that?
checkpatch does not care I guess, but I can definitely simplify this
return path as well, you're right.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management
2023-09-27 16:10 ` Miquel Raynal
@ 2023-09-29 0:22 ` Alexander Aring
0 siblings, 0 replies; 25+ messages in thread
From: Alexander Aring @ 2023-09-29 0:22 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Wed, Sep 27, 2023 at 12:10 PM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> > > +
> > > +#include <linux/kernel.h>
> > > +#include <net/cfg802154.h>
> > > +#include <net/af_ieee802154.h>
> > > +
> > > +/* Checks whether a device address matches one from the PAN list.
> > > + * This helper is meant to be used only during PAN management, when we expect
> > > + * extended addresses to be used.
> > > + */
> > > +static bool cfg802154_device_in_pan(struct ieee802154_pan_device *pan_dev,
> > > + struct ieee802154_addr *ext_dev)
> > > +{
> > > + if (!pan_dev || !ext_dev)
> > > + return false;
> > > +
> > > + if (ext_dev->mode == IEEE802154_ADDR_SHORT)
> > > + return false;
> > > +
> > > + switch (ext_dev->mode) {
> > > + case IEEE802154_ADDR_SHORT:
> > > + return pan_dev->short_addr == ext_dev->short_addr;
> >
> > This is dead code now, it will never be reached, it's checked above
> > (Or I don't see it)? I want to help you here. What exactly do you try
> > to reach here again?
>
> It's a left over. All association/disassociation operation so far which
> need these checks are operated using extended addressing (from the
> spec). I will simplify further this helper.
>
I see, it makes sense to me.
>
> > > +bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
> > > + struct ieee802154_addr *target)
> > > +{
> > > + lockdep_assert_held(&wpan_dev->association_lock);
> > > +
> > > + if (cfg802154_device_in_pan(wpan_dev->parent, target))
> > > + return true;
> > > +
> > > + return false;
> >
> > return cfg802154_device_in_pan(...); Why isn't checkpatch warning about that?
>
> checkpatch does not care I guess, but I can definitely simplify this
> return path as well, you're right.
>
ok. Was a nitpick.
Thanks.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH wpan-next v4 03/11] ieee802154: Add support for user association requests
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 01/11] ieee802154: Let PAN IDs be reset Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 02/11] ieee802154: Internal PAN management Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 04/11] mac802154: Handle associating Miquel Raynal
` (7 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Users may decide to associate with a peer, which becomes our parent
coordinator. Let's add the necessary netlink support for this.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 4 +++
include/net/ieee802154_netdev.h | 38 +++++++++++++++++++++++++++++
include/net/nl802154.h | 1 +
net/ieee802154/nl802154.c | 43 +++++++++++++++++++++++++++++++++
net/ieee802154/rdev-ops.h | 15 ++++++++++++
net/ieee802154/trace.h | 19 +++++++++++++++
6 files changed, 120 insertions(+)
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index a89f1c9cea3f..d0c033176220 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -20,6 +20,7 @@ struct wpan_phy;
struct wpan_phy_cca;
struct cfg802154_scan_request;
struct cfg802154_beacon_request;
+struct ieee802154_addr;
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
struct ieee802154_llsec_device_key;
@@ -77,6 +78,9 @@ struct cfg802154_ops {
struct cfg802154_beacon_request *request);
int (*stop_beacons)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev);
+ int (*associate)(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *coord);
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
void (*get_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 063313df447d..ca8c827d0d7f 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -125,6 +125,30 @@ struct ieee802154_hdr_fc {
#endif
};
+struct ieee802154_assoc_req_pl {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
+ u8 reserved1:1,
+ device_type:1,
+ power_source:1,
+ rx_on_when_idle:1,
+ assoc_type:1,
+ reserved2:1,
+ security_cap:1,
+ alloc_addr:1;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ u8 alloc_addr:1,
+ security_cap:1,
+ reserved2:1,
+ assoc_type:1,
+ rx_on_when_idle:1,
+ power_source:1,
+ device_type:1,
+ reserved1:1;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+} __packed;
+
enum ieee802154_frame_version {
IEEE802154_2003_STD,
IEEE802154_2006_STD,
@@ -140,6 +164,14 @@ enum ieee802154_addressing_mode {
IEEE802154_EXTENDED_ADDRESSING,
};
+enum ieee802154_association_status {
+ IEEE802154_ASSOCIATION_SUCCESSFUL = 0x00,
+ IEEE802154_PAN_AT_CAPACITY = 0x01,
+ IEEE802154_PAN_ACCESS_DENIED = 0x02,
+ IEEE802154_HOPPING_SEQUENCE_OFFSET_DUP = 0x03,
+ IEEE802154_FAST_ASSOCIATION_SUCCESSFUL = 0x80,
+};
+
struct ieee802154_hdr {
struct ieee802154_hdr_fc fc;
u8 seq;
@@ -163,6 +195,12 @@ struct ieee802154_beacon_req_frame {
struct ieee802154_mac_cmd_pl mac_pl;
};
+struct ieee802154_association_req_frame {
+ struct ieee802154_hdr mhr;
+ struct ieee802154_mac_cmd_pl mac_pl;
+ struct ieee802154_assoc_req_pl assoc_req_pl;
+};
+
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
* the contents of hdr will be, and the actual value of those bits in
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 8cd9d141f5af..830e1c51d3df 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -78,6 +78,7 @@ enum nl802154_commands {
NL802154_CMD_SCAN_DONE,
NL802154_CMD_SEND_BEACONS,
NL802154_CMD_STOP_BEACONS,
+ NL802154_CMD_ASSOCIATE,
/* add new commands above here */
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 46ac6f599fe1..2c28e0e9fdda 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1628,6 +1628,41 @@ nl802154_stop_beacons(struct sk_buff *skb, struct genl_info *info)
return rdev_stop_beacons(rdev, wpan_dev);
}
+static int nl802154_associate(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;
+ struct wpan_phy *wpan_phy;
+ struct ieee802154_addr coord;
+ int err;
+
+ wpan_dev = dev->ieee802154_ptr;
+ wpan_phy = &rdev->wpan_phy;
+
+ if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
+ NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
+ return -EOPNOTSUPP;
+ }
+
+ if (!info->attrs[NL802154_ATTR_PAN_ID] ||
+ !info->attrs[NL802154_ATTR_EXTENDED_ADDR])
+ return -EINVAL;
+
+ coord.pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
+ coord.mode = IEEE802154_ADDR_LONG;
+ coord.extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
+
+ mutex_lock(&wpan_dev->association_lock);
+ err = rdev_associate(rdev, wpan_dev, &coord);
+ mutex_unlock(&wpan_dev->association_lock);
+ if (err)
+ pr_err("Association with PAN ID 0x%x failed (%d)\n",
+ le16_to_cpu(coord.pan_id), err);
+
+ return err;
+}
+
#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 },
@@ -2749,6 +2784,14 @@ static const struct genl_ops nl802154_ops[] = {
NL802154_FLAG_CHECK_NETDEV_UP |
NL802154_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL802154_CMD_ASSOCIATE,
+ .doit = nl802154_associate,
+ .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/rdev-ops.h b/net/ieee802154/rdev-ops.h
index 5eaae15c610e..4843d52f1ee0 100644
--- a/net/ieee802154/rdev-ops.h
+++ b/net/ieee802154/rdev-ops.h
@@ -265,6 +265,21 @@ static inline int rdev_stop_beacons(struct cfg802154_registered_device *rdev,
return ret;
}
+static inline int rdev_associate(struct cfg802154_registered_device *rdev,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *coord)
+{
+ int ret;
+
+ if (!rdev->ops->associate)
+ return -EOPNOTSUPP;
+
+ trace_802154_rdev_associate(&rdev->wpan_phy, wpan_dev, coord);
+ ret = rdev->ops->associate(&rdev->wpan_phy, wpan_dev, coord);
+ 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 c16db0b326fa..2e1d4f456316 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -356,6 +356,25 @@ DEFINE_EVENT(802154_wdev_template, 802154_rdev_stop_beacons,
TP_ARGS(wpan_phy, wpan_dev)
);
+TRACE_EVENT(802154_rdev_associate,
+ TP_PROTO(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *coord),
+ TP_ARGS(wpan_phy, wpan_dev, coord),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(__le64, addr)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->addr = coord->extended_addr;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", associating with: 0x%llx",
+ WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, __entry->addr)
+);
+
TRACE_EVENT(802154_rdev_return_int,
TP_PROTO(struct wpan_phy *wpan_phy, int ret),
TP_ARGS(wpan_phy, ret),
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 04/11] mac802154: Handle associating
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (2 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 03/11] ieee802154: Add support for user association requests Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-25 11:35 ` kernel test robot
2023-09-22 15:50 ` [PATCH wpan-next v4 05/11] ieee802154: Add support for user disassociation requests Miquel Raynal
` (6 subsequent siblings)
10 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Joining a PAN officially goes by associating with a coordinator. This
coordinator may have been discovered thanks to the beacons it sent in
the past. Add support to the MAC layer for these associations, which
require:
- Sending an association request
- Receiving an association response
The association response contains the association status, eventually a
reason if the association was unsuccessful, and finally a short address
that we should use for intra-PAN communication from now on, if we
required one (which is the default, and not yet configurable).
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/ieee802154_netdev.h | 5 ++
net/ieee802154/core.c | 12 +++
net/mac802154/cfg.c | 69 +++++++++++++++++
net/mac802154/ieee802154_i.h | 19 +++++
net/mac802154/main.c | 2 +
net/mac802154/rx.c | 9 +++
net/mac802154/scan.c | 127 ++++++++++++++++++++++++++++++++
7 files changed, 243 insertions(+)
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index ca8c827d0d7f..e26ffd079556 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -149,6 +149,11 @@ struct ieee802154_assoc_req_pl {
#endif
} __packed;
+struct ieee802154_assoc_resp_pl {
+ __le16 short_addr;
+ u8 status;
+} __packed;
+
enum ieee802154_frame_version {
IEEE802154_2003_STD,
IEEE802154_2006_STD,
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index cd69bdbfd59f..a08d75dd56ad 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -198,6 +198,16 @@ void wpan_phy_free(struct wpan_phy *phy)
}
EXPORT_SYMBOL(wpan_phy_free);
+static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
+{
+ mutex_lock(&wpan_dev->association_lock);
+
+ kfree(wpan_dev->parent);
+ wpan_dev->parent = NULL;
+
+ mutex_unlock(&wpan_dev->association_lock);
+}
+
int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
struct net *net)
{
@@ -293,6 +303,8 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
rdev->opencount++;
break;
case NETDEV_UNREGISTER:
+ cfg802154_free_peer_structures(wpan_dev);
+
/* It is possible to get NETDEV_UNREGISTER
* multiple times. To detect that, check
* that the interface is still on the list
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 5c3cb019f751..0602bc5b8fbd 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -315,6 +315,74 @@ static int mac802154_stop_beacons(struct wpan_phy *wpan_phy,
return mac802154_stop_beacons_locked(local, sdata);
}
+static int mac802154_associate(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *coord)
+{
+ struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+ u64 ceaddr = swab64((__force u64)coord->extended_addr);
+ struct ieee802154_sub_if_data *sdata;
+ struct ieee802154_pan_device *parent;
+ __le16 short_addr;
+ int ret;
+
+ ASSERT_RTNL();
+
+ sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev);
+
+ if (wpan_dev->parent) {
+ dev_err(&sdata->dev->dev,
+ "Device %8phC is already associated\n", &ceaddr);
+ return -EPERM;
+ }
+
+ if (coord->mode == IEEE802154_SHORT_ADDRESSING)
+ return -EINVAL;
+
+ parent = kzalloc(sizeof(*parent), GFP_KERNEL);
+ if (!parent)
+ return -ENOMEM;
+
+ parent->pan_id = coord->pan_id;
+ parent->mode = coord->mode;
+ parent->extended_addr = coord->extended_addr;
+ parent->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST);
+
+ /* Set the PAN ID hardware address filter beforehand to avoid dropping
+ * the association response with a destination PAN ID field set to the
+ * "new" PAN ID.
+ */
+ if (local->hw.flags & IEEE802154_HW_AFILT) {
+ ret = drv_set_pan_id(local, coord->pan_id);
+ if (ret < 0)
+ goto free_parent;
+ }
+
+ ret = mac802154_perform_association(sdata, parent, &short_addr);
+ if (ret)
+ goto reset_panid;
+
+ if (local->hw.flags & IEEE802154_HW_AFILT) {
+ ret = drv_set_short_addr(local, short_addr);
+ if (ret < 0)
+ goto reset_panid;
+ }
+
+ wpan_dev->pan_id = coord->pan_id;
+ wpan_dev->short_addr = short_addr;
+ wpan_dev->parent = parent;
+
+ return 0;
+
+reset_panid:
+ if (local->hw.flags & IEEE802154_HW_AFILT)
+ drv_set_pan_id(local, IEEE802154_PAN_ID_BROADCAST);
+
+free_parent:
+ kfree(parent);
+ return ret;
+}
+
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
static void
ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -526,6 +594,7 @@ const struct cfg802154_ops mac802154_config_ops = {
.abort_scan = mac802154_abort_scan,
.send_beacons = mac802154_send_beacons,
.stop_beacons = mac802154_stop_beacons,
+ .associate = mac802154_associate,
#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 c347ec9ff8c9..fff67676b400 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -24,6 +24,7 @@
enum ieee802154_ongoing {
IEEE802154_IS_SCANNING = BIT(0),
IEEE802154_IS_BEACONING = BIT(1),
+ IEEE802154_IS_ASSOCIATING = BIT(2),
};
/* mac802154 device private data */
@@ -74,6 +75,13 @@ struct ieee802154_local {
struct list_head rx_mac_cmd_list;
struct work_struct rx_mac_cmd_work;
+ /* Association */
+ struct ieee802154_pan_device *assoc_dev;
+ struct completion assoc_done;
+ __le16 assoc_addr;
+ u8 assoc_status;
+ struct work_struct assoc_work;
+
bool started;
bool suspended;
unsigned long ongoing;
@@ -296,6 +304,17 @@ static inline bool mac802154_is_beaconing(struct ieee802154_local *local)
void mac802154_rx_mac_cmd_worker(struct work_struct *work);
+int mac802154_perform_association(struct ieee802154_sub_if_data *sdata,
+ struct ieee802154_pan_device *coord,
+ __le16 *short_addr);
+int mac802154_process_association_resp(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb);
+
+static inline bool mac802154_is_associating(struct ieee802154_local *local)
+{
+ return test_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
+}
+
/* interface handling */
int ieee802154_iface_init(void);
void ieee802154_iface_exit(void);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index 357ece67432b..9ab7396668d2 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -103,6 +103,8 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
INIT_DELAYED_WORK(&local->beacon_work, mac802154_beacon_worker);
INIT_WORK(&local->rx_mac_cmd_work, mac802154_rx_mac_cmd_worker);
+ init_completion(&local->assoc_done);
+
/* init supported flags with 802.15.4 default ranges */
phy->supported.max_minbe = 8;
phy->supported.min_maxbe = 3;
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index e2434b4fe514..d0e08613a36b 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -93,6 +93,15 @@ void mac802154_rx_mac_cmd_worker(struct work_struct *work)
queue_delayed_work(local->mac_wq, &local->beacon_work, 0);
break;
+
+ case IEEE802154_CMD_ASSOCIATION_RESP:
+ dev_dbg(&mac_pkt->sdata->dev->dev, "processing ASSOC RESP\n");
+ if (!mac802154_is_associating(local))
+ break;
+
+ mac802154_process_association_resp(mac_pkt->sdata, mac_pkt->skb);
+ break;
+
default:
break;
}
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index d9658f2c4ae6..5dd50e1ce329 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -510,3 +510,130 @@ int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
return 0;
}
+
+int mac802154_perform_association(struct ieee802154_sub_if_data *sdata,
+ struct ieee802154_pan_device *coord,
+ __le16 *short_addr)
+{
+ u64 ceaddr = swab64((__force u64)coord->extended_addr);
+ struct ieee802154_association_req_frame frame = {};
+ struct ieee802154_local *local = sdata->local;
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct sk_buff *skb;
+ int ret;
+
+ frame.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
+ frame.mhr.fc.security_enabled = 0;
+ frame.mhr.fc.frame_pending = 0;
+ frame.mhr.fc.ack_request = 1; /* We always expect an ack here */
+ frame.mhr.fc.intra_pan = 0;
+ frame.mhr.fc.dest_addr_mode = (coord->mode == IEEE802154_ADDR_LONG) ?
+ IEEE802154_EXTENDED_ADDRESSING : IEEE802154_SHORT_ADDRESSING;
+ frame.mhr.fc.version = IEEE802154_2003_STD;
+ frame.mhr.fc.source_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+ frame.mhr.source.mode = IEEE802154_ADDR_LONG;
+ frame.mhr.source.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
+ frame.mhr.source.extended_addr = wpan_dev->extended_addr;
+ frame.mhr.dest.mode = coord->mode;
+ frame.mhr.dest.pan_id = coord->pan_id;
+ if (coord->mode == IEEE802154_ADDR_LONG)
+ frame.mhr.dest.extended_addr = coord->extended_addr;
+ else
+ frame.mhr.dest.short_addr = coord->short_addr;
+ frame.mhr.seq = atomic_inc_return(&wpan_dev->dsn) & 0xFF;
+ frame.mac_pl.cmd_id = IEEE802154_CMD_ASSOCIATION_REQ;
+ frame.assoc_req_pl.device_type = 1;
+ frame.assoc_req_pl.power_source = 1;
+ frame.assoc_req_pl.rx_on_when_idle = 1;
+ frame.assoc_req_pl.alloc_addr = 1;
+
+ skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ + sizeof(frame.assoc_req_pl),
+ GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
+ skb->dev = sdata->dev;
+
+ ret = ieee802154_mac_cmd_push(skb, &frame, &frame.assoc_req_pl,
+ sizeof(frame.assoc_req_pl));
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ local->assoc_dev = coord;
+ reinit_completion(&local->assoc_done);
+ set_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
+
+ ret = ieee802154_mlme_tx_one_locked(local, sdata, skb);
+ if (ret) {
+ if (ret > 0)
+ ret = (ret == IEEE802154_NO_ACK) ? -EREMOTEIO : -EIO;
+ dev_warn(&sdata->dev->dev,
+ "No ASSOC REQ ACK received from %8phC\n", &ceaddr);
+ goto clear_assoc;
+ }
+
+ ret = wait_for_completion_killable_timeout(&local->assoc_done, 10 * HZ);
+ if (ret <= 0) {
+ dev_warn(&sdata->dev->dev,
+ "No ASSOC RESP received from %8phC\n", &ceaddr);
+ ret = -ETIMEDOUT;
+ goto clear_assoc;
+ }
+
+ if (local->assoc_status != IEEE802154_ASSOCIATION_SUCCESSFUL) {
+ if (local->assoc_status == IEEE802154_PAN_AT_CAPACITY)
+ ret = -ERANGE;
+ else
+ ret = -EPERM;
+
+ dev_warn(&sdata->dev->dev,
+ "Negative ASSOC RESP received from %8phC: %s\n", &ceaddr,
+ local->assoc_status == IEEE802154_PAN_AT_CAPACITY ?
+ "PAN at capacity" : "access denied");
+ }
+
+ ret = 0;
+ *short_addr = local->assoc_addr;
+
+clear_assoc:
+ clear_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
+ local->assoc_dev = NULL;
+
+ return ret;
+}
+
+int mac802154_process_association_resp(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb)
+{
+ struct ieee802154_addr *src = &mac_cb(skb)->source;
+ struct ieee802154_addr *dest = &mac_cb(skb)->dest;
+ u64 deaddr = swab64((__force u64)dest->extended_addr);
+ struct ieee802154_local *local = sdata->local;
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct ieee802154_assoc_resp_pl resp_pl = {};
+
+ if (skb->len != sizeof(resp_pl))
+ return -EINVAL;
+
+ if (unlikely(src->mode != IEEE802154_EXTENDED_ADDRESSING ||
+ dest->mode != IEEE802154_EXTENDED_ADDRESSING))
+ return -EINVAL;
+
+ if (unlikely(dest->extended_addr != wpan_dev->extended_addr ||
+ src->extended_addr != local->assoc_dev->extended_addr))
+ return -ENODEV;
+
+ memcpy(&resp_pl, skb->data, sizeof(resp_pl));
+ local->assoc_addr = resp_pl.short_addr;
+ local->assoc_status = resp_pl.status;
+
+ dev_dbg(&skb->dev->dev,
+ "ASSOC RESP 0x%x received from %8phC, getting short address %04x\n",
+ local->assoc_status, &deaddr, local->assoc_addr);
+
+ complete(&local->assoc_done);
+
+ return 0;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 04/11] mac802154: Handle associating
2023-09-22 15:50 ` [PATCH wpan-next v4 04/11] mac802154: Handle associating Miquel Raynal
@ 2023-09-25 11:35 ` kernel test robot
0 siblings, 0 replies; 25+ messages in thread
From: kernel test robot @ 2023-09-25 11:35 UTC (permalink / raw)
To: Miquel Raynal, Alexander Aring, Stefan Schmidt, linux-wpan
Cc: oe-kbuild-all, Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev,
David Girault, Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni, Miquel Raynal
Hi Miquel,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
[also build test WARNING on net/main linus/master v6.6-rc3 next-20230925]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Miquel-Raynal/ieee802154-Let-PAN-IDs-be-reset/20230923-000250
base: net-next/main
patch link: https://lore.kernel.org/r/20230922155029.592018-5-miquel.raynal%40bootlin.com
patch subject: [PATCH wpan-next v4 04/11] mac802154: Handle associating
config: i386-randconfig-061-20230925 (https://download.01.org/0day-ci/archive/20230925/202309251904.eSN2jHxq-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.2.0-14) 12.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20230925/202309251904.eSN2jHxq-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202309251904.eSN2jHxq-lkp@intel.com/
sparse warnings: (new ones prefixed by >>)
>> net/mac802154/cfg.c:379:39: sparse: sparse: incorrect type in argument 2 (different base types) @@ expected restricted __le16 [usertype] pan_id @@ got int @@
net/mac802154/cfg.c:379:39: sparse: expected restricted __le16 [usertype] pan_id
net/mac802154/cfg.c:379:39: sparse: got int
vim +379 net/mac802154/cfg.c
317
318 static int mac802154_associate(struct wpan_phy *wpan_phy,
319 struct wpan_dev *wpan_dev,
320 struct ieee802154_addr *coord)
321 {
322 struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
323 u64 ceaddr = swab64((__force u64)coord->extended_addr);
324 struct ieee802154_sub_if_data *sdata;
325 struct ieee802154_pan_device *parent;
326 __le16 short_addr;
327 int ret;
328
329 ASSERT_RTNL();
330
331 sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev);
332
333 if (wpan_dev->parent) {
334 dev_err(&sdata->dev->dev,
335 "Device %8phC is already associated\n", &ceaddr);
336 return -EPERM;
337 }
338
339 if (coord->mode == IEEE802154_SHORT_ADDRESSING)
340 return -EINVAL;
341
342 parent = kzalloc(sizeof(*parent), GFP_KERNEL);
343 if (!parent)
344 return -ENOMEM;
345
346 parent->pan_id = coord->pan_id;
347 parent->mode = coord->mode;
348 parent->extended_addr = coord->extended_addr;
349 parent->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST);
350
351 /* Set the PAN ID hardware address filter beforehand to avoid dropping
352 * the association response with a destination PAN ID field set to the
353 * "new" PAN ID.
354 */
355 if (local->hw.flags & IEEE802154_HW_AFILT) {
356 ret = drv_set_pan_id(local, coord->pan_id);
357 if (ret < 0)
358 goto free_parent;
359 }
360
361 ret = mac802154_perform_association(sdata, parent, &short_addr);
362 if (ret)
363 goto reset_panid;
364
365 if (local->hw.flags & IEEE802154_HW_AFILT) {
366 ret = drv_set_short_addr(local, short_addr);
367 if (ret < 0)
368 goto reset_panid;
369 }
370
371 wpan_dev->pan_id = coord->pan_id;
372 wpan_dev->short_addr = short_addr;
373 wpan_dev->parent = parent;
374
375 return 0;
376
377 reset_panid:
378 if (local->hw.flags & IEEE802154_HW_AFILT)
> 379 drv_set_pan_id(local, IEEE802154_PAN_ID_BROADCAST);
380
381 free_parent:
382 kfree(parent);
383 return ret;
384 }
385
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH wpan-next v4 05/11] ieee802154: Add support for user disassociation requests
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (3 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 04/11] mac802154: Handle associating Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 06/11] mac802154: Handle disassociations Miquel Raynal
` (5 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
A device may decide at some point to disassociate from a PAN, let's
introduce a netlink command for this purpose.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 3 +++
include/net/ieee802154_netdev.h | 11 +++++++++
include/net/nl802154.h | 1 +
net/ieee802154/nl802154.c | 41 +++++++++++++++++++++++++++++++++
net/ieee802154/rdev-ops.h | 15 ++++++++++++
net/ieee802154/trace.h | 19 +++++++++++++++
6 files changed, 90 insertions(+)
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index d0c033176220..9b036ab20079 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -81,6 +81,9 @@ struct cfg802154_ops {
int (*associate)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
struct ieee802154_addr *coord);
+ int (*disassociate)(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target);
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
void (*get_llsec_table)(struct wpan_phy *wpan_phy,
struct wpan_dev *wpan_dev,
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index e26ffd079556..16194356cfe7 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -177,6 +177,11 @@ enum ieee802154_association_status {
IEEE802154_FAST_ASSOCIATION_SUCCESSFUL = 0x80,
};
+enum ieee802154_disassociation_reason {
+ IEEE802154_COORD_WISHES_DEVICE_TO_LEAVE = 0x1,
+ IEEE802154_DEVICE_WISHES_TO_LEAVE = 0x2,
+};
+
struct ieee802154_hdr {
struct ieee802154_hdr_fc fc;
u8 seq;
@@ -206,6 +211,12 @@ struct ieee802154_association_req_frame {
struct ieee802154_assoc_req_pl assoc_req_pl;
};
+struct ieee802154_disassociation_notif_frame {
+ struct ieee802154_hdr mhr;
+ struct ieee802154_mac_cmd_pl mac_pl;
+ u8 disassoc_pl;
+};
+
/* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
* the contents of hdr will be, and the actual value of those bits in
* hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 830e1c51d3df..8a47c14c72f0 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -79,6 +79,7 @@ enum nl802154_commands {
NL802154_CMD_SEND_BEACONS,
NL802154_CMD_STOP_BEACONS,
NL802154_CMD_ASSOCIATE,
+ NL802154_CMD_DISASSOCIATE,
/* add new commands above here */
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 2c28e0e9fdda..5820fe425ddd 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -1663,6 +1663,39 @@ static int nl802154_associate(struct sk_buff *skb, struct genl_info *info)
return err;
}
+static int nl802154_disassociate(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 ieee802154_addr target;
+
+ if (wpan_phy->flags & WPAN_PHY_FLAG_DATAGRAMS_ONLY) {
+ NL_SET_ERR_MSG(info->extack, "PHY only supports datagrams");
+ return -EOPNOTSUPP;
+ }
+
+ target.pan_id = wpan_dev->pan_id;
+
+ if (info->attrs[NL802154_ATTR_EXTENDED_ADDR]) {
+ target.mode = IEEE802154_ADDR_LONG;
+ target.extended_addr = nla_get_le64(info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
+ } else if (info->attrs[NL802154_ATTR_SHORT_ADDR]) {
+ target.mode = IEEE802154_ADDR_SHORT;
+ target.short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
+ } else {
+ NL_SET_ERR_MSG(info->extack, "Device address is missing");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wpan_dev->association_lock);
+ rdev_disassociate(rdev, wpan_dev, &target);
+ mutex_unlock(&wpan_dev->association_lock);
+
+ return 0;
+}
+
#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 },
@@ -2792,6 +2825,14 @@ static const struct genl_ops nl802154_ops[] = {
NL802154_FLAG_CHECK_NETDEV_UP |
NL802154_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL802154_CMD_DISASSOCIATE,
+ .doit = nl802154_disassociate,
+ .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/rdev-ops.h b/net/ieee802154/rdev-ops.h
index 4843d52f1ee0..64071ef6f57b 100644
--- a/net/ieee802154/rdev-ops.h
+++ b/net/ieee802154/rdev-ops.h
@@ -280,6 +280,21 @@ static inline int rdev_associate(struct cfg802154_registered_device *rdev,
return ret;
}
+static inline int rdev_disassociate(struct cfg802154_registered_device *rdev,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target)
+{
+ int ret;
+
+ if (!rdev->ops->disassociate)
+ return -EOPNOTSUPP;
+
+ trace_802154_rdev_disassociate(&rdev->wpan_phy, wpan_dev, target);
+ ret = rdev->ops->disassociate(&rdev->wpan_phy, wpan_dev, target);
+ 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 2e1d4f456316..62aa6465253a 100644
--- a/net/ieee802154/trace.h
+++ b/net/ieee802154/trace.h
@@ -375,6 +375,25 @@ TRACE_EVENT(802154_rdev_associate,
WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, __entry->addr)
);
+TRACE_EVENT(802154_rdev_disassociate,
+ TP_PROTO(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target),
+ TP_ARGS(wpan_phy, wpan_dev, target),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(__le64, addr)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->addr = target->extended_addr;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", disassociating with: 0x%llx",
+ WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG, __entry->addr)
+);
+
TRACE_EVENT(802154_rdev_return_int,
TP_PROTO(struct wpan_phy *wpan_phy, int ret),
TP_ARGS(wpan_phy, ret),
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 06/11] mac802154: Handle disassociations
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (4 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 05/11] ieee802154: Add support for user disassociation requests Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers Miquel Raynal
` (4 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Devices may decide to disassociate from their coordinator for different
reasons (device turning off, coordinator signal strength too low, etc),
the MAC layer just has to send a disassociation notification.
If the ack of the disassociation notification is not received, the
device may consider itself disassociated anyway.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
net/ieee802154/pan.c | 2 +
net/mac802154/cfg.c | 100 +++++++++++++++++++++++++++++++++++
net/mac802154/ieee802154_i.h | 4 ++
net/mac802154/scan.c | 60 +++++++++++++++++++++
4 files changed, 166 insertions(+)
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
index 1677bb89c5ff..9e1f1973c294 100644
--- a/net/ieee802154/pan.c
+++ b/net/ieee802154/pan.c
@@ -56,6 +56,7 @@ bool cfg802154_device_is_parent(struct wpan_dev *wpan_dev,
return false;
}
+EXPORT_SYMBOL_GPL(cfg802154_device_is_parent);
struct ieee802154_pan_device *
cfg802154_device_is_child(struct wpan_dev *wpan_dev,
@@ -71,3 +72,4 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
return NULL;
}
+EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 0602bc5b8fbd..0d0aed788f57 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -383,6 +383,105 @@ static int mac802154_associate(struct wpan_phy *wpan_phy,
return ret;
}
+static int mac802154_disassociate_from_parent(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev)
+{
+ struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+ struct ieee802154_pan_device *child, *tmp;
+ struct ieee802154_sub_if_data *sdata;
+ u64 eaddr;
+ int ret;
+
+ sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev);
+
+ /* Start by disassociating all the children and preventing new ones to
+ * attempt associations.
+ */
+ list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
+ ret = mac802154_send_disassociation_notif(sdata, child,
+ IEEE802154_COORD_WISHES_DEVICE_TO_LEAVE);
+ if (ret) {
+ eaddr = swab64((__force u64)child->extended_addr);
+ dev_err(&sdata->dev->dev,
+ "Disassociation with %8phC may have failed (%d)\n",
+ &eaddr, ret);
+ }
+
+ list_del(&child->node);
+ }
+
+ ret = mac802154_send_disassociation_notif(sdata, wpan_dev->parent,
+ IEEE802154_DEVICE_WISHES_TO_LEAVE);
+ if (ret) {
+ eaddr = swab64((__force u64)wpan_dev->parent->extended_addr);
+ dev_err(&sdata->dev->dev,
+ "Disassociation from %8phC may have failed (%d)\n",
+ &eaddr, ret);
+ }
+
+ ret = 0;
+
+ kfree(wpan_dev->parent);
+ wpan_dev->parent = NULL;
+ wpan_dev->pan_id = cpu_to_le16(IEEE802154_PAN_ID_BROADCAST);
+ wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST);
+
+ if (local->hw.flags & IEEE802154_HW_AFILT) {
+ ret = drv_set_pan_id(local, wpan_dev->pan_id);
+ if (ret < 0)
+ return ret;
+
+ ret = drv_set_short_addr(local, wpan_dev->short_addr);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mac802154_disassociate_child(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_pan_device *child)
+{
+ struct ieee802154_sub_if_data *sdata;
+ int ret;
+
+ sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev);
+
+ ret = mac802154_send_disassociation_notif(sdata, child,
+ IEEE802154_COORD_WISHES_DEVICE_TO_LEAVE);
+ if (ret)
+ return ret;
+
+ list_del(&child->node);
+ kfree(child);
+
+ return 0;
+}
+
+static int mac802154_disassociate(struct wpan_phy *wpan_phy,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_addr *target)
+{
+ u64 teaddr = swab64((__force u64)target->extended_addr);
+ struct ieee802154_pan_device *pan_device;
+
+ ASSERT_RTNL();
+
+ if (cfg802154_device_is_parent(wpan_dev, target))
+ return mac802154_disassociate_from_parent(wpan_phy, wpan_dev);
+
+ pan_device = cfg802154_device_is_child(wpan_dev, target);
+ if (pan_device)
+ return mac802154_disassociate_child(wpan_phy, wpan_dev,
+ pan_device);
+
+ dev_err(&wpan_dev->netdev->dev,
+ "Device %8phC is not associated with us\n", &teaddr);
+
+ return -EINVAL;
+}
+
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
static void
ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -595,6 +694,7 @@ const struct cfg802154_ops mac802154_config_ops = {
.send_beacons = mac802154_send_beacons,
.stop_beacons = mac802154_stop_beacons,
.associate = mac802154_associate,
+ .disassociate = mac802154_disassociate,
#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 fff67676b400..92252f86c69c 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -315,6 +315,10 @@ static inline bool mac802154_is_associating(struct ieee802154_local *local)
return test_bit(IEEE802154_IS_ASSOCIATING, &local->ongoing);
}
+int mac802154_send_disassociation_notif(struct ieee802154_sub_if_data *sdata,
+ struct ieee802154_pan_device *target,
+ u8 reason);
+
/* interface handling */
int ieee802154_iface_init(void);
void ieee802154_iface_exit(void);
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index 5dd50e1ce329..e2f2e1235ec6 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -637,3 +637,63 @@ int mac802154_process_association_resp(struct ieee802154_sub_if_data *sdata,
return 0;
}
+
+int mac802154_send_disassociation_notif(struct ieee802154_sub_if_data *sdata,
+ struct ieee802154_pan_device *target,
+ u8 reason)
+{
+ struct ieee802154_disassociation_notif_frame frame = {};
+ u64 teaddr = swab64((__force u64)target->extended_addr);
+ struct ieee802154_local *local = sdata->local;
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct sk_buff *skb;
+ int ret;
+
+ frame.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
+ frame.mhr.fc.security_enabled = 0;
+ frame.mhr.fc.frame_pending = 0;
+ frame.mhr.fc.ack_request = 1;
+ frame.mhr.fc.intra_pan = 1;
+ frame.mhr.fc.dest_addr_mode = (target->mode == IEEE802154_ADDR_LONG) ?
+ IEEE802154_EXTENDED_ADDRESSING : IEEE802154_SHORT_ADDRESSING;
+ frame.mhr.fc.version = IEEE802154_2003_STD;
+ frame.mhr.fc.source_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+ frame.mhr.source.mode = IEEE802154_ADDR_LONG;
+ frame.mhr.source.pan_id = wpan_dev->pan_id;
+ frame.mhr.source.extended_addr = wpan_dev->extended_addr;
+ frame.mhr.dest.mode = target->mode;
+ frame.mhr.dest.pan_id = wpan_dev->pan_id;
+ if (target->mode == IEEE802154_ADDR_LONG)
+ frame.mhr.dest.extended_addr = target->extended_addr;
+ else
+ frame.mhr.dest.short_addr = target->short_addr;
+ frame.mhr.seq = atomic_inc_return(&wpan_dev->dsn) & 0xFF;
+ frame.mac_pl.cmd_id = IEEE802154_CMD_DISASSOCIATION_NOTIFY;
+ frame.disassoc_pl = reason;
+
+ skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ + sizeof(frame.disassoc_pl),
+ GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
+ skb->dev = sdata->dev;
+
+ ret = ieee802154_mac_cmd_push(skb, &frame, &frame.disassoc_pl,
+ sizeof(frame.disassoc_pl));
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ ret = ieee802154_mlme_tx_one_locked(local, sdata, skb);
+ if (ret) {
+ dev_warn(&sdata->dev->dev,
+ "No DISASSOC ACK received from %8phC\n", &teaddr);
+ if (ret > 0)
+ ret = (ret == IEEE802154_NO_ACK) ? -EREMOTEIO : -EIO;
+ return ret;
+ }
+
+ dev_dbg(&sdata->dev->dev, "DISASSOC ACK received from %8phC\n", &teaddr);
+ return 0;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (5 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 06/11] mac802154: Handle disassociations Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-25 0:13 ` Alexander Aring
2023-09-27 1:37 ` Alexander Aring
2023-09-22 15:50 ` [PATCH wpan-next v4 08/11] ieee802154: Add support for limiting the number of associated devices Miquel Raynal
` (3 subsequent siblings)
10 siblings, 2 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Coordinators may have to handle association requests from peers which
want to join the PAN. The logic involves:
- Acknowledging the request (done by hardware)
- If requested, a random short address that is free on this PAN should
be chosen for the device.
- Sending an association response with the short address allocated for
the peer and expecting it to be ack'ed.
If anything fails during this procedure, the peer is considered not
associated.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 7 ++
include/net/ieee802154_netdev.h | 6 ++
net/ieee802154/core.c | 7 ++
net/ieee802154/pan.c | 30 +++++++
net/mac802154/ieee802154_i.h | 2 +
net/mac802154/rx.c | 8 ++
net/mac802154/scan.c | 142 ++++++++++++++++++++++++++++++++
7 files changed, 202 insertions(+)
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 9b036ab20079..c844ae63bc04 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -583,4 +583,11 @@ struct ieee802154_pan_device *
cfg802154_device_is_child(struct wpan_dev *wpan_dev,
struct ieee802154_addr *target);
+/**
+ * cfg802154_get_free_short_addr - Get a free address among the known devices
+ * @wpan_dev: the wpan device
+ * @return: a random short address expectedly unused on our PAN
+ */
+__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev);
+
#endif /* __NET_CFG802154_H */
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 16194356cfe7..4de858f9929e 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -211,6 +211,12 @@ struct ieee802154_association_req_frame {
struct ieee802154_assoc_req_pl assoc_req_pl;
};
+struct ieee802154_association_resp_frame {
+ struct ieee802154_hdr mhr;
+ struct ieee802154_mac_cmd_pl mac_pl;
+ struct ieee802154_assoc_resp_pl assoc_resp_pl;
+};
+
struct ieee802154_disassociation_notif_frame {
struct ieee802154_hdr mhr;
struct ieee802154_mac_cmd_pl mac_pl;
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index a08d75dd56ad..1670a71327a7 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -200,11 +200,18 @@ EXPORT_SYMBOL(wpan_phy_free);
static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
{
+ struct ieee802154_pan_device *child, *tmp;
+
mutex_lock(&wpan_dev->association_lock);
kfree(wpan_dev->parent);
wpan_dev->parent = NULL;
+ list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
+ list_del(&child->node);
+ kfree(child);
+ }
+
mutex_unlock(&wpan_dev->association_lock);
}
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
index 9e1f1973c294..e99c64054dcb 100644
--- a/net/ieee802154/pan.c
+++ b/net/ieee802154/pan.c
@@ -73,3 +73,33 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
return NULL;
}
EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
+
+__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
+{
+ struct ieee802154_pan_device *child;
+ __le16 addr;
+
+ lockdep_assert_held(&wpan_dev->association_lock);
+
+ do {
+ get_random_bytes(&addr, 2);
+ if (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST) ||
+ addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC))
+ continue;
+
+ if (wpan_dev->short_addr == addr)
+ continue;
+
+ if (wpan_dev->parent && wpan_dev->parent->short_addr == addr)
+ continue;
+
+ list_for_each_entry(child, &wpan_dev->children, node)
+ if (child->short_addr == addr)
+ continue;
+
+ break;
+ } while (1);
+
+ return addr;
+}
+EXPORT_SYMBOL_GPL(cfg802154_get_free_short_addr);
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 92252f86c69c..432bfa87249e 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -318,6 +318,8 @@ static inline bool mac802154_is_associating(struct ieee802154_local *local)
int mac802154_send_disassociation_notif(struct ieee802154_sub_if_data *sdata,
struct ieee802154_pan_device *target,
u8 reason);
+int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb);
/* interface handling */
int ieee802154_iface_init(void);
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index d0e08613a36b..96040b63a4fc 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -102,6 +102,14 @@ void mac802154_rx_mac_cmd_worker(struct work_struct *work)
mac802154_process_association_resp(mac_pkt->sdata, mac_pkt->skb);
break;
+ case IEEE802154_CMD_ASSOCIATION_REQ:
+ dev_dbg(&mac_pkt->sdata->dev->dev, "processing ASSOC REQ\n");
+ if (mac_pkt->sdata->wpan_dev.iftype != NL802154_IFTYPE_COORD)
+ break;
+
+ mac802154_process_association_req(mac_pkt->sdata, mac_pkt->skb);
+ break;
+
default:
break;
}
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index e2f2e1235ec6..d5f66c204bc5 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -697,3 +697,145 @@ int mac802154_send_disassociation_notif(struct ieee802154_sub_if_data *sdata,
dev_dbg(&sdata->dev->dev, "DISASSOC ACK received from %8phC\n", &teaddr);
return 0;
}
+
+static int
+mac802154_send_association_resp_locked(struct ieee802154_sub_if_data *sdata,
+ struct ieee802154_pan_device *target,
+ struct ieee802154_assoc_resp_pl *assoc_resp_pl)
+{
+ u64 teaddr = swab64((__force u64)target->extended_addr);
+ struct ieee802154_association_resp_frame frame = {};
+ struct ieee802154_local *local = sdata->local;
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct sk_buff *skb;
+ int ret;
+
+ frame.mhr.fc.type = IEEE802154_FC_TYPE_MAC_CMD;
+ frame.mhr.fc.security_enabled = 0;
+ frame.mhr.fc.frame_pending = 0;
+ frame.mhr.fc.ack_request = 1; /* We always expect an ack here */
+ frame.mhr.fc.intra_pan = 1;
+ frame.mhr.fc.dest_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+ frame.mhr.fc.version = IEEE802154_2003_STD;
+ frame.mhr.fc.source_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+ frame.mhr.source.mode = IEEE802154_ADDR_LONG;
+ frame.mhr.source.extended_addr = wpan_dev->extended_addr;
+ frame.mhr.dest.mode = IEEE802154_ADDR_LONG;
+ frame.mhr.dest.pan_id = wpan_dev->pan_id;
+ frame.mhr.dest.extended_addr = target->extended_addr;
+ frame.mhr.seq = atomic_inc_return(&wpan_dev->dsn) & 0xFF;
+ frame.mac_pl.cmd_id = IEEE802154_CMD_ASSOCIATION_RESP;
+
+ skb = alloc_skb(IEEE802154_MAC_CMD_SKB_SZ + sizeof(*assoc_resp_pl),
+ GFP_KERNEL);
+ if (!skb)
+ return -ENOBUFS;
+
+ skb->dev = sdata->dev;
+
+ ret = ieee802154_mac_cmd_push(skb, &frame, assoc_resp_pl,
+ sizeof(*assoc_resp_pl));
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ ret = ieee802154_mlme_tx_locked(local, sdata, skb);
+ if (ret) {
+ dev_warn(&sdata->dev->dev,
+ "No ASSOC RESP ACK received from %8phC\n", &teaddr);
+ if (ret > 0)
+ ret = (ret == IEEE802154_NO_ACK) ? -EREMOTEIO : -EIO;
+ return ret;
+ }
+
+ return 0;
+}
+
+int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb)
+{
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct ieee802154_addr *src = &mac_cb(skb)->source;
+ struct ieee802154_addr *dest = &mac_cb(skb)->dest;
+ struct ieee802154_assoc_resp_pl assoc_resp_pl = {};
+ struct ieee802154_assoc_req_pl assoc_req_pl;
+ struct ieee802154_pan_device *child, *exchild;
+ struct ieee802154_addr tmp = {};
+ u64 ceaddr;
+ int ret;
+
+ if (skb->len != sizeof(assoc_req_pl))
+ return -EINVAL;
+
+ if (unlikely(src->mode != IEEE802154_EXTENDED_ADDRESSING))
+ return -EINVAL;
+
+ if (unlikely(dest->pan_id != wpan_dev->pan_id))
+ return -ENODEV;
+
+ if (dest->mode == IEEE802154_EXTENDED_ADDRESSING &&
+ unlikely(dest->extended_addr != wpan_dev->extended_addr))
+ return -ENODEV;
+ else if (dest->mode == IEEE802154_SHORT_ADDRESSING &&
+ unlikely(dest->short_addr != wpan_dev->short_addr))
+ return -ENODEV;
+
+ mutex_lock(&wpan_dev->association_lock);
+
+ memcpy(&assoc_req_pl, skb->data, sizeof(assoc_req_pl));
+ if (assoc_req_pl.assoc_type) {
+ dev_err(&skb->dev->dev, "Fast associations not supported yet\n");
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
+
+ child = kzalloc(sizeof(*child), GFP_KERNEL);
+ if (!child) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ child->extended_addr = src->extended_addr;
+ child->mode = IEEE802154_EXTENDED_ADDRESSING;
+ ceaddr = swab64((__force u64)child->extended_addr);
+
+ assoc_resp_pl.status = IEEE802154_ASSOCIATION_SUCCESSFUL;
+ if (assoc_req_pl.alloc_addr) {
+ assoc_resp_pl.short_addr = cfg802154_get_free_short_addr(wpan_dev);
+ child->mode = IEEE802154_SHORT_ADDRESSING;
+ } else {
+ assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+ }
+ child->short_addr = assoc_resp_pl.short_addr;
+ dev_dbg(&sdata->dev->dev,
+ "Accepting ASSOC REQ from child %8phC, providing short address 0x%04x\n",
+ &ceaddr, le16_to_cpu(child->short_addr));
+
+ ret = mac802154_send_association_resp_locked(sdata, child, &assoc_resp_pl);
+ if (ret) {
+ kfree(child);
+ goto unlock;
+ }
+
+ dev_dbg(&sdata->dev->dev,
+ "Successful association with new child %8phC\n", &ceaddr);
+
+ /* Ensure this child is not already associated (might happen due to
+ * retransmissions), in this case drop the ex structure.
+ */
+ tmp.mode = child->mode;
+ tmp.extended_addr = child->extended_addr;
+ exchild = cfg802154_device_is_child(wpan_dev, &tmp);
+ if (exchild) {
+ dev_dbg(&sdata->dev->dev,
+ "Child %8phC was already known\n", &ceaddr);
+ list_del(&exchild->node);
+ }
+
+ list_add(&child->node, &wpan_dev->children);
+
+unlock:
+ mutex_unlock(&wpan_dev->association_lock);
+ return ret;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-22 15:50 ` [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers Miquel Raynal
@ 2023-09-25 0:13 ` Alexander Aring
2023-09-25 7:43 ` Miquel Raynal
2023-09-27 1:37 ` Alexander Aring
1 sibling, 1 reply; 25+ messages in thread
From: Alexander Aring @ 2023-09-25 0:13 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Coordinators may have to handle association requests from peers which
> want to join the PAN. The logic involves:
> - Acknowledging the request (done by hardware)
> - If requested, a random short address that is free on this PAN should
> be chosen for the device.
> - Sending an association response with the short address allocated for
> the peer and expecting it to be ack'ed.
>
> If anything fails during this procedure, the peer is considered not
> associated.
>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> ---
> include/net/cfg802154.h | 7 ++
> include/net/ieee802154_netdev.h | 6 ++
> net/ieee802154/core.c | 7 ++
> net/ieee802154/pan.c | 30 +++++++
> net/mac802154/ieee802154_i.h | 2 +
> net/mac802154/rx.c | 8 ++
> net/mac802154/scan.c | 142 ++++++++++++++++++++++++++++++++
> 7 files changed, 202 insertions(+)
>
> diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> index 9b036ab20079..c844ae63bc04 100644
> --- a/include/net/cfg802154.h
> +++ b/include/net/cfg802154.h
> @@ -583,4 +583,11 @@ struct ieee802154_pan_device *
> cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> struct ieee802154_addr *target);
>
> +/**
> + * cfg802154_get_free_short_addr - Get a free address among the known devices
> + * @wpan_dev: the wpan device
> + * @return: a random short address expectedly unused on our PAN
> + */
> +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev);
> +
> #endif /* __NET_CFG802154_H */
> diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
> index 16194356cfe7..4de858f9929e 100644
> --- a/include/net/ieee802154_netdev.h
> +++ b/include/net/ieee802154_netdev.h
> @@ -211,6 +211,12 @@ struct ieee802154_association_req_frame {
> struct ieee802154_assoc_req_pl assoc_req_pl;
> };
>
> +struct ieee802154_association_resp_frame {
> + struct ieee802154_hdr mhr;
> + struct ieee802154_mac_cmd_pl mac_pl;
> + struct ieee802154_assoc_resp_pl assoc_resp_pl;
> +};
> +
> struct ieee802154_disassociation_notif_frame {
> struct ieee802154_hdr mhr;
> struct ieee802154_mac_cmd_pl mac_pl;
> diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
> index a08d75dd56ad..1670a71327a7 100644
> --- a/net/ieee802154/core.c
> +++ b/net/ieee802154/core.c
> @@ -200,11 +200,18 @@ EXPORT_SYMBOL(wpan_phy_free);
>
> static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
> {
> + struct ieee802154_pan_device *child, *tmp;
> +
> mutex_lock(&wpan_dev->association_lock);
>
> kfree(wpan_dev->parent);
> wpan_dev->parent = NULL;
>
> + list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
> + list_del(&child->node);
> + kfree(child);
> + }
> +
> mutex_unlock(&wpan_dev->association_lock);
> }
>
> diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
> index 9e1f1973c294..e99c64054dcb 100644
> --- a/net/ieee802154/pan.c
> +++ b/net/ieee802154/pan.c
> @@ -73,3 +73,33 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> return NULL;
> }
> EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
> +
> +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
> +{
> + struct ieee802154_pan_device *child;
> + __le16 addr;
> +
> + lockdep_assert_held(&wpan_dev->association_lock);
> +
> + do {
> + get_random_bytes(&addr, 2);
> + if (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST) ||
> + addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC))
> + continue;
> +
> + if (wpan_dev->short_addr == addr)
> + continue;
> +
> + if (wpan_dev->parent && wpan_dev->parent->short_addr == addr)
> + continue;
> +
> + list_for_each_entry(child, &wpan_dev->children, node)
> + if (child->short_addr == addr)
> + continue;
> +
> + break;
> + } while (1);
> +
I still believe that this random 2 bytes and check if it's already
being used is wrong here. We need something to use the next free
available number according to the data we are storing here.
However it is acceptable and can be changed later...
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-25 0:13 ` Alexander Aring
@ 2023-09-25 7:43 ` Miquel Raynal
2023-09-27 1:31 ` Alexander Aring
0 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-25 7:43 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi Alexander,
aahringo@redhat.com wrote on Sun, 24 Sep 2023 20:13:34 -0400:
> Hi,
>
> On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
> <miquel.raynal@bootlin.com> wrote:
> >
> > Coordinators may have to handle association requests from peers which
> > want to join the PAN. The logic involves:
> > - Acknowledging the request (done by hardware)
> > - If requested, a random short address that is free on this PAN should
> > be chosen for the device.
> > - Sending an association response with the short address allocated for
> > the peer and expecting it to be ack'ed.
> >
> > If anything fails during this procedure, the peer is considered not
> > associated.
> >
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
> > include/net/cfg802154.h | 7 ++
> > include/net/ieee802154_netdev.h | 6 ++
> > net/ieee802154/core.c | 7 ++
> > net/ieee802154/pan.c | 30 +++++++
> > net/mac802154/ieee802154_i.h | 2 +
> > net/mac802154/rx.c | 8 ++
> > net/mac802154/scan.c | 142 ++++++++++++++++++++++++++++++++
> > 7 files changed, 202 insertions(+)
> >
> > diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> > index 9b036ab20079..c844ae63bc04 100644
> > --- a/include/net/cfg802154.h
> > +++ b/include/net/cfg802154.h
> > @@ -583,4 +583,11 @@ struct ieee802154_pan_device *
> > cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > struct ieee802154_addr *target);
> >
> > +/**
> > + * cfg802154_get_free_short_addr - Get a free address among the known devices
> > + * @wpan_dev: the wpan device
> > + * @return: a random short address expectedly unused on our PAN
> > + */
> > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev);
> > +
> > #endif /* __NET_CFG802154_H */
> > diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
> > index 16194356cfe7..4de858f9929e 100644
> > --- a/include/net/ieee802154_netdev.h
> > +++ b/include/net/ieee802154_netdev.h
> > @@ -211,6 +211,12 @@ struct ieee802154_association_req_frame {
> > struct ieee802154_assoc_req_pl assoc_req_pl;
> > };
> >
> > +struct ieee802154_association_resp_frame {
> > + struct ieee802154_hdr mhr;
> > + struct ieee802154_mac_cmd_pl mac_pl;
> > + struct ieee802154_assoc_resp_pl assoc_resp_pl;
> > +};
> > +
> > struct ieee802154_disassociation_notif_frame {
> > struct ieee802154_hdr mhr;
> > struct ieee802154_mac_cmd_pl mac_pl;
> > diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
> > index a08d75dd56ad..1670a71327a7 100644
> > --- a/net/ieee802154/core.c
> > +++ b/net/ieee802154/core.c
> > @@ -200,11 +200,18 @@ EXPORT_SYMBOL(wpan_phy_free);
> >
> > static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
> > {
> > + struct ieee802154_pan_device *child, *tmp;
> > +
> > mutex_lock(&wpan_dev->association_lock);
> >
> > kfree(wpan_dev->parent);
> > wpan_dev->parent = NULL;
> >
> > + list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
> > + list_del(&child->node);
> > + kfree(child);
> > + }
> > +
> > mutex_unlock(&wpan_dev->association_lock);
> > }
> >
> > diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
> > index 9e1f1973c294..e99c64054dcb 100644
> > --- a/net/ieee802154/pan.c
> > +++ b/net/ieee802154/pan.c
> > @@ -73,3 +73,33 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > return NULL;
> > }
> > EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
> > +
> > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
> > +{
> > + struct ieee802154_pan_device *child;
> > + __le16 addr;
> > +
> > + lockdep_assert_held(&wpan_dev->association_lock);
> > +
> > + do {
> > + get_random_bytes(&addr, 2);
> > + if (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST) ||
> > + addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC))
> > + continue;
> > +
> > + if (wpan_dev->short_addr == addr)
> > + continue;
> > +
> > + if (wpan_dev->parent && wpan_dev->parent->short_addr == addr)
> > + continue;
> > +
> > + list_for_each_entry(child, &wpan_dev->children, node)
> > + if (child->short_addr == addr)
> > + continue;
> > +
> > + break;
> > + } while (1);
> > +
>
> I still believe that this random 2 bytes and check if it's already
> being used is wrong here. We need something to use the next free
> available number according to the data we are storing here.
This issue I still have in mind is when you have this typology:
device A -------> device B --------> device C <-------- device D
(leaf) (coord) (PAN coord) (leaf)
B associates with C
A associates with B
D associates with C
If B and C run Linux's stack, they will always have the same short
address. Yes this can be handled (realignment procedure). But any time
this happens, you'll have a load of predictable realignments when A and
D get in range with B or C.
> However it is acceptable and can be changed later...
Ok.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-25 7:43 ` Miquel Raynal
@ 2023-09-27 1:31 ` Alexander Aring
2023-09-27 14:39 ` Miquel Raynal
0 siblings, 1 reply; 25+ messages in thread
From: Alexander Aring @ 2023-09-27 1:31 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Mon, Sep 25, 2023 at 3:43 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> aahringo@redhat.com wrote on Sun, 24 Sep 2023 20:13:34 -0400:
>
> > Hi,
> >
> > On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
> > <miquel.raynal@bootlin.com> wrote:
> > >
> > > Coordinators may have to handle association requests from peers which
> > > want to join the PAN. The logic involves:
> > > - Acknowledging the request (done by hardware)
> > > - If requested, a random short address that is free on this PAN should
> > > be chosen for the device.
> > > - Sending an association response with the short address allocated for
> > > the peer and expecting it to be ack'ed.
> > >
> > > If anything fails during this procedure, the peer is considered not
> > > associated.
> > >
> > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > ---
> > > include/net/cfg802154.h | 7 ++
> > > include/net/ieee802154_netdev.h | 6 ++
> > > net/ieee802154/core.c | 7 ++
> > > net/ieee802154/pan.c | 30 +++++++
> > > net/mac802154/ieee802154_i.h | 2 +
> > > net/mac802154/rx.c | 8 ++
> > > net/mac802154/scan.c | 142 ++++++++++++++++++++++++++++++++
> > > 7 files changed, 202 insertions(+)
> > >
> > > diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> > > index 9b036ab20079..c844ae63bc04 100644
> > > --- a/include/net/cfg802154.h
> > > +++ b/include/net/cfg802154.h
> > > @@ -583,4 +583,11 @@ struct ieee802154_pan_device *
> > > cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > > struct ieee802154_addr *target);
> > >
> > > +/**
> > > + * cfg802154_get_free_short_addr - Get a free address among the known devices
> > > + * @wpan_dev: the wpan device
> > > + * @return: a random short address expectedly unused on our PAN
> > > + */
> > > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev);
> > > +
> > > #endif /* __NET_CFG802154_H */
> > > diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
> > > index 16194356cfe7..4de858f9929e 100644
> > > --- a/include/net/ieee802154_netdev.h
> > > +++ b/include/net/ieee802154_netdev.h
> > > @@ -211,6 +211,12 @@ struct ieee802154_association_req_frame {
> > > struct ieee802154_assoc_req_pl assoc_req_pl;
> > > };
> > >
> > > +struct ieee802154_association_resp_frame {
> > > + struct ieee802154_hdr mhr;
> > > + struct ieee802154_mac_cmd_pl mac_pl;
> > > + struct ieee802154_assoc_resp_pl assoc_resp_pl;
> > > +};
> > > +
> > > struct ieee802154_disassociation_notif_frame {
> > > struct ieee802154_hdr mhr;
> > > struct ieee802154_mac_cmd_pl mac_pl;
> > > diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
> > > index a08d75dd56ad..1670a71327a7 100644
> > > --- a/net/ieee802154/core.c
> > > +++ b/net/ieee802154/core.c
> > > @@ -200,11 +200,18 @@ EXPORT_SYMBOL(wpan_phy_free);
> > >
> > > static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
> > > {
> > > + struct ieee802154_pan_device *child, *tmp;
> > > +
> > > mutex_lock(&wpan_dev->association_lock);
> > >
> > > kfree(wpan_dev->parent);
> > > wpan_dev->parent = NULL;
> > >
> > > + list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
> > > + list_del(&child->node);
> > > + kfree(child);
> > > + }
> > > +
> > > mutex_unlock(&wpan_dev->association_lock);
> > > }
> > >
> > > diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
> > > index 9e1f1973c294..e99c64054dcb 100644
> > > --- a/net/ieee802154/pan.c
> > > +++ b/net/ieee802154/pan.c
> > > @@ -73,3 +73,33 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > > return NULL;
> > > }
> > > EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
> > > +
> > > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
> > > +{
> > > + struct ieee802154_pan_device *child;
> > > + __le16 addr;
> > > +
> > > + lockdep_assert_held(&wpan_dev->association_lock);
> > > +
> > > + do {
> > > + get_random_bytes(&addr, 2);
> > > + if (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST) ||
> > > + addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC))
> > > + continue;
> > > +
> > > + if (wpan_dev->short_addr == addr)
> > > + continue;
> > > +
> > > + if (wpan_dev->parent && wpan_dev->parent->short_addr == addr)
> > > + continue;
> > > +
> > > + list_for_each_entry(child, &wpan_dev->children, node)
> > > + if (child->short_addr == addr)
> > > + continue;
> > > +
> > > + break;
> > > + } while (1);
> > > +
> >
> > I still believe that this random 2 bytes and check if it's already
> > being used is wrong here. We need something to use the next free
> > available number according to the data we are storing here.
>
> This issue I still have in mind is when you have this typology:
>
> device A -------> device B --------> device C <-------- device D
> (leaf) (coord) (PAN coord) (leaf)
>
> B associates with C
> A associates with B
> D associates with C
>
> If B and C run Linux's stack, they will always have the same short
> address. Yes this can be handled (realignment procedure). But any time
> this happens, you'll have a load of predictable realignments when A and
> D get in range with B or C.
>
I see that it can be "more" predictable, but what happens when there
is the same short address case with the random number generator? It
sounds to me like there needs to be a kind of duplicate address
detection going on and then choose another one, if 802.15.4 even
handles this case...
I am also thinking that there is only one number left and the random
generator runs multiple times to find the last one aka "it's random
you can never be sure", when it always returns the same address.
However, that's only my thoughts about it and hopefully can be
improved in future.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-27 1:31 ` Alexander Aring
@ 2023-09-27 14:39 ` Miquel Raynal
0 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-27 14:39 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi Alexander,
aahringo@redhat.com wrote on Tue, 26 Sep 2023 21:31:09 -0400:
> Hi,
>
> On Mon, Sep 25, 2023 at 3:43 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
> >
> > Hi Alexander,
> >
> > aahringo@redhat.com wrote on Sun, 24 Sep 2023 20:13:34 -0400:
> >
> > > Hi,
> > >
> > > On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
> > > <miquel.raynal@bootlin.com> wrote:
> > > >
> > > > Coordinators may have to handle association requests from peers which
> > > > want to join the PAN. The logic involves:
> > > > - Acknowledging the request (done by hardware)
> > > > - If requested, a random short address that is free on this PAN should
> > > > be chosen for the device.
> > > > - Sending an association response with the short address allocated for
> > > > the peer and expecting it to be ack'ed.
> > > >
> > > > If anything fails during this procedure, the peer is considered not
> > > > associated.
> > > >
> > > > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > > > ---
> > > > include/net/cfg802154.h | 7 ++
> > > > include/net/ieee802154_netdev.h | 6 ++
> > > > net/ieee802154/core.c | 7 ++
> > > > net/ieee802154/pan.c | 30 +++++++
> > > > net/mac802154/ieee802154_i.h | 2 +
> > > > net/mac802154/rx.c | 8 ++
> > > > net/mac802154/scan.c | 142 ++++++++++++++++++++++++++++++++
> > > > 7 files changed, 202 insertions(+)
> > > >
> > > > diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> > > > index 9b036ab20079..c844ae63bc04 100644
> > > > --- a/include/net/cfg802154.h
> > > > +++ b/include/net/cfg802154.h
> > > > @@ -583,4 +583,11 @@ struct ieee802154_pan_device *
> > > > cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > > > struct ieee802154_addr *target);
> > > >
> > > > +/**
> > > > + * cfg802154_get_free_short_addr - Get a free address among the known devices
> > > > + * @wpan_dev: the wpan device
> > > > + * @return: a random short address expectedly unused on our PAN
> > > > + */
> > > > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev);
> > > > +
> > > > #endif /* __NET_CFG802154_H */
> > > > diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
> > > > index 16194356cfe7..4de858f9929e 100644
> > > > --- a/include/net/ieee802154_netdev.h
> > > > +++ b/include/net/ieee802154_netdev.h
> > > > @@ -211,6 +211,12 @@ struct ieee802154_association_req_frame {
> > > > struct ieee802154_assoc_req_pl assoc_req_pl;
> > > > };
> > > >
> > > > +struct ieee802154_association_resp_frame {
> > > > + struct ieee802154_hdr mhr;
> > > > + struct ieee802154_mac_cmd_pl mac_pl;
> > > > + struct ieee802154_assoc_resp_pl assoc_resp_pl;
> > > > +};
> > > > +
> > > > struct ieee802154_disassociation_notif_frame {
> > > > struct ieee802154_hdr mhr;
> > > > struct ieee802154_mac_cmd_pl mac_pl;
> > > > diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
> > > > index a08d75dd56ad..1670a71327a7 100644
> > > > --- a/net/ieee802154/core.c
> > > > +++ b/net/ieee802154/core.c
> > > > @@ -200,11 +200,18 @@ EXPORT_SYMBOL(wpan_phy_free);
> > > >
> > > > static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
> > > > {
> > > > + struct ieee802154_pan_device *child, *tmp;
> > > > +
> > > > mutex_lock(&wpan_dev->association_lock);
> > > >
> > > > kfree(wpan_dev->parent);
> > > > wpan_dev->parent = NULL;
> > > >
> > > > + list_for_each_entry_safe(child, tmp, &wpan_dev->children, node) {
> > > > + list_del(&child->node);
> > > > + kfree(child);
> > > > + }
> > > > +
> > > > mutex_unlock(&wpan_dev->association_lock);
> > > > }
> > > >
> > > > diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
> > > > index 9e1f1973c294..e99c64054dcb 100644
> > > > --- a/net/ieee802154/pan.c
> > > > +++ b/net/ieee802154/pan.c
> > > > @@ -73,3 +73,33 @@ cfg802154_device_is_child(struct wpan_dev *wpan_dev,
> > > > return NULL;
> > > > }
> > > > EXPORT_SYMBOL_GPL(cfg802154_device_is_child);
> > > > +
> > > > +__le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
> > > > +{
> > > > + struct ieee802154_pan_device *child;
> > > > + __le16 addr;
> > > > +
> > > > + lockdep_assert_held(&wpan_dev->association_lock);
> > > > +
> > > > + do {
> > > > + get_random_bytes(&addr, 2);
> > > > + if (addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST) ||
> > > > + addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC))
> > > > + continue;
> > > > +
> > > > + if (wpan_dev->short_addr == addr)
> > > > + continue;
> > > > +
> > > > + if (wpan_dev->parent && wpan_dev->parent->short_addr == addr)
> > > > + continue;
> > > > +
> > > > + list_for_each_entry(child, &wpan_dev->children, node)
> > > > + if (child->short_addr == addr)
> > > > + continue;
> > > > +
> > > > + break;
> > > > + } while (1);
> > > > +
> > >
> > > I still believe that this random 2 bytes and check if it's already
> > > being used is wrong here. We need something to use the next free
> > > available number according to the data we are storing here.
> >
> > This issue I still have in mind is when you have this typology:
> >
> > device A -------> device B --------> device C <-------- device D
> > (leaf) (coord) (PAN coord) (leaf)
> >
> > B associates with C
> > A associates with B
> > D associates with C
> >
> > If B and C run Linux's stack, they will always have the same short
> > address. Yes this can be handled (realignment procedure). But any time
> > this happens, you'll have a load of predictable realignments when A and
> > D get in range with B or C.
> >
>
> I see that it can be "more" predictable, but what happens when there
> is the same short address case with the random number generator? It
> sounds to me like there needs to be a kind of duplicate address
> detection going on and then choose another one, if 802.15.4 even
> handles this case...
Yes it may happen, and yes it is handled by the spec (I did not
implement it yet). When such a situation occurs (two devices using the
same short address in a given PAN), the third-party device which
detects the faulty situation must notify its coordinator and the
coordinator (IIRC) must allocate a new short address as part of a
realignment procedure.
> I am also thinking that there is only one number left and the random
> generator runs multiple times to find the last one aka "it's random
> you can never be sure", when it always returns the same address.
I'll try to summarize the two issues and solutions we have:
- incremental short address: if two coordinators distribute
short addresses in a PAN, at the time we perform a realignment
procedure, if Coord A has allocated 1 short address (0) and Coord B
in the same PAN has allocated 10 short addresses (from 0 to 9), you
know that the device that needs a new address will be given 1, which
will lead to a realignment, then 2, then 3... and produce a *lot* of
noise. However despite being long on big network, we can assume the
time to find the relevant address is bounded.
- random short address: no conflict should happen following a
realignment procedure (assuming regular-sized networks, probability
is very low, close to 1/65000) however in case we have a huge
network, the time taken to find a free slot is unbounded.
At this stage I believe the former issue is more likely to happen than
the second, but the second is a bit critical as it can lead to DoS
situations. One easy way to mitigate this is to limit the number of
devices on the network (as you said in another mail, we can refuse
devices arbitrarily), which is the first denial procedure I've
implemented, knowing that it should be improved as well, as that can be
done later without much additional constraints.
> However, that's only my thoughts about it and hopefully can be
> improved in future.
Yes, I am not convinced this is the perfect choice but at least it's
simple enough and will work like a charm on small networks.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-22 15:50 ` [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers Miquel Raynal
2023-09-25 0:13 ` Alexander Aring
@ 2023-09-27 1:37 ` Alexander Aring
2023-09-27 15:40 ` Miquel Raynal
1 sibling, 1 reply; 25+ messages in thread
From: Alexander Aring @ 2023-09-27 1:37 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Coordinators may have to handle association requests from peers which
> want to join the PAN. The logic involves:
> - Acknowledging the request (done by hardware)
> - If requested, a random short address that is free on this PAN should
> be chosen for the device.
> - Sending an association response with the short address allocated for
> the peer and expecting it to be ack'ed.
>
> If anything fails during this procedure, the peer is considered not
> associated.
I thought a coordinator can also reject requests for _any_ reason and
it's very user specific whatever that reason is.
If we have such a case (that it is very user specific what to do
exactly) this should be able to be controlled by the user space to
have there a logic to tell the kernel to accept or reject the
association.
However, I am fine with this solution, but I think we might want to
change this behaviour in the future so that an application in the user
space has the logic to tell the kernel to accept or reject an
association. That would make sense?
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-27 1:37 ` Alexander Aring
@ 2023-09-27 15:40 ` Miquel Raynal
2023-09-29 0:19 ` Alexander Aring
0 siblings, 1 reply; 25+ messages in thread
From: Miquel Raynal @ 2023-09-27 15:40 UTC (permalink / raw)
To: Alexander Aring
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi Alexander,
aahringo@redhat.com wrote on Tue, 26 Sep 2023 21:37:23 -0400:
> Hi,
>
> On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
> <miquel.raynal@bootlin.com> wrote:
> >
> > Coordinators may have to handle association requests from peers which
> > want to join the PAN. The logic involves:
> > - Acknowledging the request (done by hardware)
> > - If requested, a random short address that is free on this PAN should
> > be chosen for the device.
> > - Sending an association response with the short address allocated for
> > the peer and expecting it to be ack'ed.
> >
> > If anything fails during this procedure, the peer is considered not
> > associated.
>
> I thought a coordinator can also reject requests for _any_ reason and
> it's very user specific whatever that reason is.
Absolutely.
> If we have such a case (that it is very user specific what to do
> exactly) this should be able to be controlled by the user space to
> have there a logic to tell the kernel to accept or reject the
> association.
Agreed (not implemented yet, though).
> However, I am fine with this solution, but I think we might want to
> change this behaviour in the future so that an application in the user
> space has the logic to tell the kernel to accept or reject an
> association. That would make sense?
Definitely, yes.
Thanks,
Miquèl
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers
2023-09-27 15:40 ` Miquel Raynal
@ 2023-09-29 0:19 ` Alexander Aring
0 siblings, 0 replies; 25+ messages in thread
From: Alexander Aring @ 2023-09-29 0:19 UTC (permalink / raw)
To: Miquel Raynal
Cc: Alexander Aring, Stefan Schmidt, linux-wpan, David S. Miller,
Jakub Kicinski, Paolo Abeni, Eric Dumazet, netdev, David Girault,
Romuald Despres, Frederic Blain, Nicolas Schodet,
Guilhem Imberton, Thomas Petazzoni
Hi,
On Wed, Sep 27, 2023 at 11:40 AM Miquel Raynal
<miquel.raynal@bootlin.com> wrote:
>
> Hi Alexander,
>
> aahringo@redhat.com wrote on Tue, 26 Sep 2023 21:37:23 -0400:
>
> > Hi,
> >
> > On Fri, Sep 22, 2023 at 11:51 AM Miquel Raynal
> > <miquel.raynal@bootlin.com> wrote:
> > >
> > > Coordinators may have to handle association requests from peers which
> > > want to join the PAN. The logic involves:
> > > - Acknowledging the request (done by hardware)
> > > - If requested, a random short address that is free on this PAN should
> > > be chosen for the device.
> > > - Sending an association response with the short address allocated for
> > > the peer and expecting it to be ack'ed.
> > >
> > > If anything fails during this procedure, the peer is considered not
> > > associated.
> >
> > I thought a coordinator can also reject requests for _any_ reason and
> > it's very user specific whatever that reason is.
>
> Absolutely.
>
> > If we have such a case (that it is very user specific what to do
> > exactly) this should be able to be controlled by the user space to
> > have there a logic to tell the kernel to accept or reject the
> > association.
>
> Agreed (not implemented yet, though).
>
> > However, I am fine with this solution, but I think we might want to
> > change this behaviour in the future so that an application in the user
> > space has the logic to tell the kernel to accept or reject an
> > association. That would make sense?
>
> Definitely, yes.
ok, thanks to have some agreement here for the future.
- Alex
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH wpan-next v4 08/11] ieee802154: Add support for limiting the number of associated devices
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (6 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 07/11] mac802154: Handle association requests from peers Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 09/11] mac802154: Follow " Miquel Raynal
` (2 subsequent siblings)
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Coordinators may refuse associations. We need a user input for
that. Let's add a new netlink command which can provide a maximum number
of devices we accept to associate with as a first step. Later, we could
also forward the request to userspace and check whether the association
should be accepted or not.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 8 ++++++++
include/net/nl802154.h | 2 ++
net/ieee802154/core.c | 1 +
net/ieee802154/nl802154.c | 28 ++++++++++++++++++++++++++++
net/ieee802154/pan.c | 8 ++++++++
5 files changed, 47 insertions(+)
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index c844ae63bc04..0d3e9af00198 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -506,6 +506,7 @@ struct wpan_dev {
struct mutex association_lock;
struct ieee802154_pan_device *parent;
struct list_head children;
+ unsigned int max_associations;
};
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
@@ -583,6 +584,13 @@ struct ieee802154_pan_device *
cfg802154_device_is_child(struct wpan_dev *wpan_dev,
struct ieee802154_addr *target);
+/**
+ * cfg802154_set_max_associations - Limit the number of future associations
+ * @wpan_dev: the wpan device
+ * @max: the maximum number of devices we accept to associate
+ */
+void cfg802154_set_max_associations(struct wpan_dev *wpan_dev, unsigned int max);
+
/**
* cfg802154_get_free_short_addr - Get a free address among the known devices
* @wpan_dev: the wpan device
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 8a47c14c72f0..8b26faae49e8 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -80,6 +80,7 @@ enum nl802154_commands {
NL802154_CMD_STOP_BEACONS,
NL802154_CMD_ASSOCIATE,
NL802154_CMD_DISASSOCIATE,
+ NL802154_CMD_SET_MAX_ASSOCIATIONS,
/* add new commands above here */
@@ -149,6 +150,7 @@ enum nl802154_attrs {
NL802154_ATTR_SCAN_DURATION,
NL802154_ATTR_SCAN_DONE_REASON,
NL802154_ATTR_BEACON_INTERVAL,
+ NL802154_ATTR_MAX_ASSOCIATIONS,
/* add attributes here, update the policy in nl802154.c */
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 1670a71327a7..2d6fe45efa05 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -295,6 +295,7 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
rdev->devlist_generation++;
mutex_init(&wpan_dev->association_lock);
INIT_LIST_HEAD(&wpan_dev->children);
+ wpan_dev->max_associations = SZ_16K;
wpan_dev->netdev = dev;
break;
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index 5820fe425ddd..e16e57fc34d0 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -234,6 +234,7 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
NL802154_SCAN_DONE_REASON_ABORTED),
[NL802154_ATTR_BEACON_INTERVAL] =
NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION),
+ [NL802154_ATTR_MAX_ASSOCIATIONS] = { .type = NLA_U32 },
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
@@ -1696,6 +1697,26 @@ static int nl802154_disassociate(struct sk_buff *skb, struct genl_info *info)
return 0;
}
+static int nl802154_set_max_associations(struct sk_buff *skb, struct genl_info *info)
+{
+ struct net_device *dev = info->user_ptr[1];
+ struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
+ unsigned int max_assoc;
+
+ if (!info->attrs[NL802154_ATTR_MAX_ASSOCIATIONS]) {
+ NL_SET_ERR_MSG(info->extack, "No maximum number of association given");
+ return -EINVAL;
+ }
+
+ max_assoc = nla_get_u32(info->attrs[NL802154_ATTR_MAX_ASSOCIATIONS]);
+
+ mutex_lock(&wpan_dev->association_lock);
+ cfg802154_set_max_associations(wpan_dev, max_assoc);
+ mutex_unlock(&wpan_dev->association_lock);
+
+ return 0;
+}
+
#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 },
@@ -2833,6 +2854,13 @@ static const struct genl_ops nl802154_ops[] = {
NL802154_FLAG_CHECK_NETDEV_UP |
NL802154_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL802154_CMD_SET_MAX_ASSOCIATIONS,
+ .doit = nl802154_set_max_associations,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL802154_FLAG_NEED_NETDEV |
+ NL802154_FLAG_NEED_RTNL,
+ },
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
{
.cmd = NL802154_CMD_SET_SEC_PARAMS,
diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c
index e99c64054dcb..8d4a7b955b2a 100644
--- a/net/ieee802154/pan.c
+++ b/net/ieee802154/pan.c
@@ -103,3 +103,11 @@ __le16 cfg802154_get_free_short_addr(struct wpan_dev *wpan_dev)
return addr;
}
EXPORT_SYMBOL_GPL(cfg802154_get_free_short_addr);
+
+void cfg802154_set_max_associations(struct wpan_dev *wpan_dev, unsigned int max)
+{
+ lockdep_assert_held(&wpan_dev->association_lock);
+
+ wpan_dev->max_associations = max;
+}
+EXPORT_SYMBOL_GPL(cfg802154_set_max_associations);
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 09/11] mac802154: Follow the number of associated devices
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (7 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 08/11] ieee802154: Add support for limiting the number of associated devices Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 10/11] mac802154: Handle disassociation notifications from peers Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 11/11] ieee802154: Give the user the association list Miquel Raynal
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Track the count of associated devices. Limit the number of associations
using the value provided by the user if any. If we reach the maximum
number of associations, we tell the device we are at capacity. If the
user do not want to accept any more associations, it may specify the
value 0 to the maximum number of associations, which will lead to an
access denied error status returned to the peers trying to associate.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/cfg802154.h | 1 +
net/ieee802154/core.c | 2 ++
net/mac802154/cfg.c | 1 +
net/mac802154/scan.c | 33 +++++++++++++++++++++++----------
4 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
index 0d3e9af00198..a64bbcd71f10 100644
--- a/include/net/cfg802154.h
+++ b/include/net/cfg802154.h
@@ -507,6 +507,7 @@ struct wpan_dev {
struct ieee802154_pan_device *parent;
struct list_head children;
unsigned int max_associations;
+ unsigned int nchildren;
};
#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
index 2d6fe45efa05..60e8fff1347e 100644
--- a/net/ieee802154/core.c
+++ b/net/ieee802154/core.c
@@ -212,6 +212,8 @@ static void cfg802154_free_peer_structures(struct wpan_dev *wpan_dev)
kfree(child);
}
+ wpan_dev->nchildren = 0;
+
mutex_unlock(&wpan_dev->association_lock);
}
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 0d0aed788f57..4a85fa674f66 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -454,6 +454,7 @@ static int mac802154_disassociate_child(struct wpan_phy *wpan_phy,
return ret;
list_del(&child->node);
+ wpan_dev->nchildren--;
kfree(child);
return 0;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index d5f66c204bc5..81d2c2bb1f09 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -800,20 +800,32 @@ int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
child->mode = IEEE802154_EXTENDED_ADDRESSING;
ceaddr = swab64((__force u64)child->extended_addr);
- assoc_resp_pl.status = IEEE802154_ASSOCIATION_SUCCESSFUL;
- if (assoc_req_pl.alloc_addr) {
- assoc_resp_pl.short_addr = cfg802154_get_free_short_addr(wpan_dev);
- child->mode = IEEE802154_SHORT_ADDRESSING;
+ if (wpan_dev->nchildren >= wpan_dev->max_associations) {
+ if (!wpan_dev->max_associations)
+ assoc_resp_pl.status = IEEE802154_PAN_ACCESS_DENIED;
+ else
+ assoc_resp_pl.status = IEEE802154_PAN_AT_CAPACITY;
+ assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST);
+ dev_dbg(&sdata->dev->dev,
+ "Refusing ASSOC REQ from child %8phC, %s\n", &ceaddr,
+ assoc_resp_pl.status == IEEE802154_PAN_ACCESS_DENIED ?
+ "access denied" : "too many children");
} else {
- assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+ assoc_resp_pl.status = IEEE802154_ASSOCIATION_SUCCESSFUL;
+ if (assoc_req_pl.alloc_addr) {
+ assoc_resp_pl.short_addr = cfg802154_get_free_short_addr(wpan_dev);
+ child->mode = IEEE802154_SHORT_ADDRESSING;
+ } else {
+ assoc_resp_pl.short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
+ }
+ child->short_addr = assoc_resp_pl.short_addr;
+ dev_dbg(&sdata->dev->dev,
+ "Accepting ASSOC REQ from child %8phC, providing short address 0x%04x\n",
+ &ceaddr, le16_to_cpu(child->short_addr));
}
- child->short_addr = assoc_resp_pl.short_addr;
- dev_dbg(&sdata->dev->dev,
- "Accepting ASSOC REQ from child %8phC, providing short address 0x%04x\n",
- &ceaddr, le16_to_cpu(child->short_addr));
ret = mac802154_send_association_resp_locked(sdata, child, &assoc_resp_pl);
- if (ret) {
+ if (ret || assoc_resp_pl.status != IEEE802154_ASSOCIATION_SUCCESSFUL) {
kfree(child);
goto unlock;
}
@@ -834,6 +846,7 @@ int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
}
list_add(&child->node, &wpan_dev->children);
+ wpan_dev->nchildren++;
unlock:
mutex_unlock(&wpan_dev->association_lock);
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 10/11] mac802154: Handle disassociation notifications from peers
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (8 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 09/11] mac802154: Follow " Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
2023-09-22 15:50 ` [PATCH wpan-next v4 11/11] ieee802154: Give the user the association list Miquel Raynal
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Peers may decided to disassociate from us, their coordinator, in this
case they will send a disassociation notification which we must
acknowledge. If we don't, the peer device considers itself disassociated
anyway. We also need to drop the reference to this child from our
internal structures.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
net/mac802154/ieee802154_i.h | 2 ++
net/mac802154/rx.c | 8 ++++++
net/mac802154/scan.c | 55 ++++++++++++++++++++++++++++++++++++
3 files changed, 65 insertions(+)
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 432bfa87249e..08dd521a51a5 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -318,6 +318,8 @@ static inline bool mac802154_is_associating(struct ieee802154_local *local)
int mac802154_send_disassociation_notif(struct ieee802154_sub_if_data *sdata,
struct ieee802154_pan_device *target,
u8 reason);
+int mac802154_process_disassociation_notif(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb);
int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
struct sk_buff *skb);
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index 96040b63a4fc..0024341ef9c5 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -110,6 +110,14 @@ void mac802154_rx_mac_cmd_worker(struct work_struct *work)
mac802154_process_association_req(mac_pkt->sdata, mac_pkt->skb);
break;
+ case IEEE802154_CMD_DISASSOCIATION_NOTIFY:
+ dev_dbg(&mac_pkt->sdata->dev->dev, "processing DISASSOC NOTIF\n");
+ if (mac_pkt->sdata->wpan_dev.iftype != NL802154_IFTYPE_COORD)
+ break;
+
+ mac802154_process_disassociation_notif(mac_pkt->sdata, mac_pkt->skb);
+ break;
+
default:
break;
}
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index 81d2c2bb1f09..7597072aed57 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -852,3 +852,58 @@ int mac802154_process_association_req(struct ieee802154_sub_if_data *sdata,
mutex_unlock(&wpan_dev->association_lock);
return ret;
}
+
+int mac802154_process_disassociation_notif(struct ieee802154_sub_if_data *sdata,
+ struct sk_buff *skb)
+{
+ struct ieee802154_addr *src = &mac_cb(skb)->source;
+ struct ieee802154_addr *dest = &mac_cb(skb)->dest;
+ struct wpan_dev *wpan_dev = &sdata->wpan_dev;
+ struct ieee802154_pan_device *child;
+ struct ieee802154_addr target;
+ bool parent;
+ u64 teaddr;
+
+ if (skb->len != sizeof(u8))
+ return -EINVAL;
+
+ if (unlikely(src->mode != IEEE802154_EXTENDED_ADDRESSING))
+ return -EINVAL;
+
+ if (dest->mode == IEEE802154_EXTENDED_ADDRESSING &&
+ unlikely(dest->extended_addr != wpan_dev->extended_addr))
+ return -ENODEV;
+ else if (dest->mode == IEEE802154_SHORT_ADDRESSING &&
+ unlikely(dest->short_addr != wpan_dev->short_addr))
+ return -ENODEV;
+
+ if (dest->pan_id != wpan_dev->pan_id)
+ return -ENODEV;
+
+ target.mode = IEEE802154_EXTENDED_ADDRESSING;
+ target.extended_addr = src->extended_addr;
+ teaddr = swab64((__force u64)target.extended_addr);
+ dev_dbg(&skb->dev->dev, "Processing DISASSOC NOTIF from %8phC\n", &teaddr);
+
+ mutex_lock(&wpan_dev->association_lock);
+ parent = cfg802154_device_is_parent(wpan_dev, &target);
+ if (!parent)
+ child = cfg802154_device_is_child(wpan_dev, &target);
+ if (!parent && !child) {
+ mutex_unlock(&wpan_dev->association_lock);
+ return -EINVAL;
+ }
+
+ if (parent) {
+ kfree(wpan_dev->parent);
+ wpan_dev->parent = NULL;
+ } else {
+ list_del(&child->node);
+ kfree(child);
+ wpan_dev->nchildren--;
+ }
+
+ mutex_unlock(&wpan_dev->association_lock);
+
+ return 0;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread* [PATCH wpan-next v4 11/11] ieee802154: Give the user the association list
2023-09-22 15:50 [PATCH wpan-next v4 00/11] ieee802154: Associations between devices Miquel Raynal
` (9 preceding siblings ...)
2023-09-22 15:50 ` [PATCH wpan-next v4 10/11] mac802154: Handle disassociation notifications from peers Miquel Raynal
@ 2023-09-22 15:50 ` Miquel Raynal
10 siblings, 0 replies; 25+ messages in thread
From: Miquel Raynal @ 2023-09-22 15:50 UTC (permalink / raw)
To: Alexander Aring, Stefan Schmidt, linux-wpan
Cc: David S. Miller, Jakub Kicinski, Paolo Abeni, Eric Dumazet,
netdev, David Girault, Romuald Despres, Frederic Blain,
Nicolas Schodet, Guilhem Imberton, Thomas Petazzoni,
Miquel Raynal
Upon request, we must be able to provide to the user the list of
associations currently in place. Let's add a new netlink command and
attribute for this purpose.
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
include/net/nl802154.h | 18 ++++++-
net/ieee802154/nl802154.c | 103 +++++++++++++++++++++++++++++++++++++-
2 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 8b26faae49e8..4c752f799957 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -81,6 +81,7 @@ enum nl802154_commands {
NL802154_CMD_ASSOCIATE,
NL802154_CMD_DISASSOCIATE,
NL802154_CMD_SET_MAX_ASSOCIATIONS,
+ NL802154_CMD_LIST_ASSOCIATIONS,
/* add new commands above here */
@@ -151,6 +152,7 @@ enum nl802154_attrs {
NL802154_ATTR_SCAN_DONE_REASON,
NL802154_ATTR_BEACON_INTERVAL,
NL802154_ATTR_MAX_ASSOCIATIONS,
+ NL802154_ATTR_PEER,
/* add attributes here, update the policy in nl802154.c */
@@ -389,8 +391,6 @@ enum nl802154_supported_bool_states {
NL802154_SUPPORTED_BOOL_MAX = __NL802154_SUPPORTED_BOOL_AFTER_LAST - 1
};
-#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
-
enum nl802154_dev_addr_modes {
NL802154_DEV_ADDR_NONE,
__NL802154_DEV_ADDR_INVALID,
@@ -410,12 +410,26 @@ enum nl802154_dev_addr_attrs {
NL802154_DEV_ADDR_ATTR_SHORT,
NL802154_DEV_ADDR_ATTR_EXTENDED,
NL802154_DEV_ADDR_ATTR_PAD,
+ NL802154_DEV_ADDR_ATTR_PEER_TYPE,
/* keep last */
__NL802154_DEV_ADDR_ATTR_AFTER_LAST,
NL802154_DEV_ADDR_ATTR_MAX = __NL802154_DEV_ADDR_ATTR_AFTER_LAST - 1
};
+enum nl802154_peer_type {
+ NL802154_PEER_TYPE_UNSPEC,
+
+ NL802154_PEER_TYPE_PARENT,
+ NL802154_PEER_TYPE_CHILD,
+
+ /* keep last */
+ __NL802154_PEER_TYPE_AFTER_LAST,
+ NL802154_PEER_TYPE_MAX = __NL802154_PEER_TYPE_AFTER_LAST - 1
+};
+
+#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
+
enum nl802154_key_id_modes {
NL802154_KEY_ID_MODE_IMPLICIT,
NL802154_KEY_ID_MODE_INDEX,
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
index e16e57fc34d0..e4d290d0e0a0 100644
--- a/net/ieee802154/nl802154.c
+++ b/net/ieee802154/nl802154.c
@@ -235,6 +235,7 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
[NL802154_ATTR_BEACON_INTERVAL] =
NLA_POLICY_MAX(NLA_U8, IEEE802154_ACTIVE_SCAN_DURATION),
[NL802154_ATTR_MAX_ASSOCIATIONS] = { .type = NLA_U32 },
+ [NL802154_ATTR_PEER] = { .type = NLA_NESTED },
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
[NL802154_ATTR_SEC_ENABLED] = { .type = NLA_U8, },
@@ -249,7 +250,6 @@ static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
};
-#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
static int
nl802154_prepare_wpan_dev_dump(struct sk_buff *skb,
struct netlink_callback *cb,
@@ -308,7 +308,6 @@ nl802154_finish_wpan_dev_dump(struct cfg802154_registered_device *rdev)
{
rtnl_unlock();
}
-#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
/* message building helper */
static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
@@ -1717,6 +1716,101 @@ static int nl802154_set_max_associations(struct sk_buff *skb, struct genl_info *
return 0;
}
+static int nl802154_send_peer_info(struct sk_buff *msg,
+ struct netlink_callback *cb,
+ u32 seq, int flags,
+ struct cfg802154_registered_device *rdev,
+ struct wpan_dev *wpan_dev,
+ struct ieee802154_pan_device *peer,
+ enum nl802154_peer_type type)
+{
+ struct nlattr *nla;
+ void *hdr;
+
+ ASSERT_RTNL();
+
+ hdr = nl802154hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
+ NL802154_CMD_LIST_ASSOCIATIONS);
+ if (!hdr)
+ return -ENOBUFS;
+
+ genl_dump_check_consistent(cb, hdr);
+
+ nla = nla_nest_start_noflag(msg, NL802154_ATTR_PEER);
+ if (!nla)
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL802154_DEV_ADDR_ATTR_PEER_TYPE, type))
+ goto nla_put_failure;
+
+ if (nla_put_u8(msg, NL802154_DEV_ADDR_ATTR_MODE, peer->mode))
+ goto nla_put_failure;
+
+ if (nla_put(msg, NL802154_DEV_ADDR_ATTR_SHORT,
+ IEEE802154_SHORT_ADDR_LEN, &peer->short_addr))
+ goto nla_put_failure;
+
+ if (nla_put(msg, NL802154_DEV_ADDR_ATTR_EXTENDED,
+ IEEE802154_EXTENDED_ADDR_LEN, &peer->extended_addr))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, nla);
+
+ genlmsg_end(msg, hdr);
+
+ return 0;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ return -EMSGSIZE;
+}
+
+static int nl802154_list_associations(struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct cfg802154_registered_device *rdev;
+ struct ieee802154_pan_device *child;
+ struct wpan_dev *wpan_dev;
+ int err;
+
+ err = nl802154_prepare_wpan_dev_dump(skb, cb, &rdev, &wpan_dev);
+ if (err)
+ return err;
+
+ mutex_lock(&wpan_dev->association_lock);
+
+ if (cb->args[2])
+ goto out;
+
+ if (wpan_dev->parent) {
+ err = nl802154_send_peer_info(skb, cb, cb->nlh->nlmsg_seq,
+ NLM_F_MULTI, rdev, wpan_dev,
+ wpan_dev->parent,
+ NL802154_PEER_TYPE_PARENT);
+ if (err < 0)
+ goto out_err;
+ }
+
+ list_for_each_entry(child, &wpan_dev->children, node) {
+ err = nl802154_send_peer_info(skb, cb, cb->nlh->nlmsg_seq,
+ NLM_F_MULTI, rdev, wpan_dev,
+ child,
+ NL802154_PEER_TYPE_CHILD);
+ if (err < 0)
+ goto out_err;
+ }
+
+ cb->args[2] = 1;
+out:
+ err = skb->len;
+out_err:
+ mutex_unlock(&wpan_dev->association_lock);
+
+ nl802154_finish_wpan_dev_dump(rdev);
+
+ return err;
+}
+
#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 },
@@ -2861,6 +2955,11 @@ static const struct genl_ops nl802154_ops[] = {
.internal_flags = NL802154_FLAG_NEED_NETDEV |
NL802154_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL802154_CMD_LIST_ASSOCIATIONS,
+ .dumpit = nl802154_list_associations,
+ /* can be retrieved by unprivileged users */
+ },
#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
{
.cmd = NL802154_CMD_SET_SEC_PARAMS,
--
2.34.1
^ permalink raw reply related [flat|nested] 25+ messages in thread