Message ID | 20221102151915.1007815-3-miquel.raynal@bootlin.com (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | IEEE 802.15.4 PAN discovery handling | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Guessing tree name failed - patch did not apply |
Hi, On Wed, Nov 2, 2022 at 11:20 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote: > > Let's introduce helpers for giving the MAC layer a generic interface for > advertising discovered coordinators/PANs upon beacon reception. This > support requires the MAC layers to: > - Allocate a coordinator/PAN descriptor and fill it. > - Register this structure, giving the generic ieee802154 layer the > necessary information about the coordinator/PAN the beacon originates > from. > - To flush all the allocated structures once the scan is done. > > The generic layer keeps a temporary list of the discovered coordinators > to tell the user whether or not the beacon comes from a new device or > not, so stateless userspace applications might not spam the user with > identical information if not required. > > Co-developed-by: David Girault <david.girault@qorvo.com> > Signed-off-by: David Girault <david.girault@qorvo.com> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> > --- > include/net/cfg802154.h | 12 ++++ > net/ieee802154/Makefile | 2 +- > net/ieee802154/core.c | 2 + > net/ieee802154/nl802154.c | 2 + > net/ieee802154/pan.c | 114 ++++++++++++++++++++++++++++++++++++++ > 5 files changed, 131 insertions(+), 1 deletion(-) > create mode 100644 net/ieee802154/pan.c > > diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h > index 8d67d9ed438d..3057b4e0726c 100644 > --- a/include/net/cfg802154.h > +++ b/include/net/cfg802154.h > @@ -401,6 +401,10 @@ struct wpan_dev { > > /* fallback for acknowledgment bit setting */ > bool ackreq; > + > + /* Coordinators management during scans */ > + spinlock_t coord_list_lock; > + struct list_head coord_list; > }; > > #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) > @@ -451,4 +455,12 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy) > > void ieee802154_configure_durations(struct wpan_phy *phy); > > +struct ieee802154_coord_desc * > +cfg802154_alloc_coordinator(struct ieee802154_addr *coord, gfp_t gfp); > +void cfg802154_free_coordinator_desc(struct ieee802154_coord_desc *desc); > +void cfg802154_record_coordinator(struct wpan_phy *wpan_phy, > + struct wpan_dev *wpan_dev, > + struct ieee802154_coord_desc *desc); > +void cfg802154_flush_known_coordinators(struct wpan_dev *wpan_dev); > + > #endif /* __NET_CFG802154_H */ > diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile > index f05b7bdae2aa..6b7c66de730d 100644 > --- a/net/ieee802154/Makefile > +++ b/net/ieee802154/Makefile > @@ -4,7 +4,7 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o > obj-y += 6lowpan/ > > ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ > - header_ops.o sysfs.o nl802154.o trace.o > + header_ops.o sysfs.o nl802154.o pan.o trace.o > ieee802154_socket-y := socket.o > > CFLAGS_trace.o := -I$(src) > diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c > index 57546e07e06a..091eb467fde6 100644 > --- a/net/ieee802154/core.c > +++ b/net/ieee802154/core.c > @@ -276,6 +276,8 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb, > wpan_dev->identifier = ++rdev->wpan_dev_id; > list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list); > rdev->devlist_generation++; > + spin_lock_init(&wpan_dev->coord_list_lock); > + INIT_LIST_HEAD(&wpan_dev->coord_list); > > wpan_dev->netdev = dev; > break; > diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c > index f6fb7a228747..b6bd04fe160b 100644 > --- a/net/ieee802154/nl802154.c > +++ b/net/ieee802154/nl802154.c > @@ -1368,6 +1368,8 @@ static int nl802154_advertise_coordinator(struct wpan_phy *wpan_phy, > struct sk_buff *msg; > int ret; > > + lockdep_assert(&wpan_dev->coord_list_lock); > + > msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); > if (!msg) > return -ENOMEM; > diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c > new file mode 100644 > index 000000000000..0d4f752a090a > --- /dev/null > +++ b/net/ieee802154/pan.c > @@ -0,0 +1,114 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* > + * IEEE 802.15.4 PAN management > + * > + * Copyright (C) 2021 Qorvo US, Inc > + * Authors: > + * - David Girault <david.girault@qorvo.com> > + * - Miquel Raynal <miquel.raynal@bootlin.com> > + */ > + > +#include <linux/slab.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/device.h> > + > +#include <net/cfg802154.h> > +#include <net/af_ieee802154.h> > + > +#include "ieee802154.h" > +#include "../ieee802154/nl802154.h" > + > +struct ieee802154_coord_desc * > +cfg802154_alloc_coordinator(struct ieee802154_addr *coord, gfp_t gfp) > +{ > + struct ieee802154_coord_desc *desc; > + > + desc = kzalloc(sizeof(*desc), gfp); > + if (!desc) > + return ERR_PTR(-ENOMEM); > + > + desc->addr = kzalloc(sizeof(*coord), gfp); > + if (!desc->addr) { > + kfree(desc); > + return ERR_PTR(-ENOMEM); > + } > + > + memcpy(desc->addr, coord, sizeof(*coord)); > + > + return desc; > +} > +EXPORT_SYMBOL_GPL(cfg802154_alloc_coordinator); > + > +void cfg802154_free_coordinator_desc(struct ieee802154_coord_desc *desc) > +{ > + kfree(desc->addr); > + kfree(desc); > +} > +EXPORT_SYMBOL_GPL(cfg802154_free_coordinator_desc); > + > +static bool > +cfg802154_is_same_coordinator(struct ieee802154_coord_desc *a, > + struct ieee802154_coord_desc *b) > +{ > + if (a->addr->pan_id != b->addr->pan_id) > + return false; > + > + if (a->addr->mode != b->addr->mode) > + return false; > + > + if (a->addr->mode == IEEE802154_ADDR_SHORT && > + a->addr->short_addr == b->addr->short_addr) > + return true; > + else if (a->addr->mode == IEEE802154_ADDR_LONG && > + a->addr->extended_addr == b->addr->extended_addr) > + return true; > + > + return false; semantic is a little bit different, can we use "ieee802154_addr_equal()" here? - Alex
Hi Alexander, > > +static bool > > +cfg802154_is_same_coordinator(struct ieee802154_coord_desc *a, > > + struct ieee802154_coord_desc *b) > > +{ > > + if (a->addr->pan_id != b->addr->pan_id) > > + return false; > > + > > + if (a->addr->mode != b->addr->mode) > > + return false; > > + > > + if (a->addr->mode == IEEE802154_ADDR_SHORT && > > + a->addr->short_addr == b->addr->short_addr) > > + return true; > > + else if (a->addr->mode == IEEE802154_ADDR_LONG && > > + a->addr->extended_addr == b->addr->extended_addr) > > + return true; > > + > > + return false; > > semantic is a little bit different, can we use "ieee802154_addr_equal()" here? No problem, I will. Thanks, Miquèl
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 8d67d9ed438d..3057b4e0726c 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -401,6 +401,10 @@ struct wpan_dev { /* fallback for acknowledgment bit setting */ bool ackreq; + + /* Coordinators management during scans */ + spinlock_t coord_list_lock; + struct list_head coord_list; }; #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev) @@ -451,4 +455,12 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy) void ieee802154_configure_durations(struct wpan_phy *phy); +struct ieee802154_coord_desc * +cfg802154_alloc_coordinator(struct ieee802154_addr *coord, gfp_t gfp); +void cfg802154_free_coordinator_desc(struct ieee802154_coord_desc *desc); +void cfg802154_record_coordinator(struct wpan_phy *wpan_phy, + struct wpan_dev *wpan_dev, + struct ieee802154_coord_desc *desc); +void cfg802154_flush_known_coordinators(struct wpan_dev *wpan_dev); + #endif /* __NET_CFG802154_H */ diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index f05b7bdae2aa..6b7c66de730d 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_IEEE802154_SOCKET) += ieee802154_socket.o obj-y += 6lowpan/ ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \ - header_ops.o sysfs.o nl802154.o trace.o + header_ops.o sysfs.o nl802154.o pan.o trace.o ieee802154_socket-y := socket.o CFLAGS_trace.o := -I$(src) diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c index 57546e07e06a..091eb467fde6 100644 --- a/net/ieee802154/core.c +++ b/net/ieee802154/core.c @@ -276,6 +276,8 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb, wpan_dev->identifier = ++rdev->wpan_dev_id; list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list); rdev->devlist_generation++; + spin_lock_init(&wpan_dev->coord_list_lock); + INIT_LIST_HEAD(&wpan_dev->coord_list); wpan_dev->netdev = dev; break; diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index f6fb7a228747..b6bd04fe160b 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1368,6 +1368,8 @@ static int nl802154_advertise_coordinator(struct wpan_phy *wpan_phy, struct sk_buff *msg; int ret; + lockdep_assert(&wpan_dev->coord_list_lock); + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!msg) return -ENOMEM; diff --git a/net/ieee802154/pan.c b/net/ieee802154/pan.c new file mode 100644 index 000000000000..0d4f752a090a --- /dev/null +++ b/net/ieee802154/pan.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IEEE 802.15.4 PAN management + * + * Copyright (C) 2021 Qorvo US, Inc + * Authors: + * - David Girault <david.girault@qorvo.com> + * - Miquel Raynal <miquel.raynal@bootlin.com> + */ + +#include <linux/slab.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/device.h> + +#include <net/cfg802154.h> +#include <net/af_ieee802154.h> + +#include "ieee802154.h" +#include "../ieee802154/nl802154.h" + +struct ieee802154_coord_desc * +cfg802154_alloc_coordinator(struct ieee802154_addr *coord, gfp_t gfp) +{ + struct ieee802154_coord_desc *desc; + + desc = kzalloc(sizeof(*desc), gfp); + if (!desc) + return ERR_PTR(-ENOMEM); + + desc->addr = kzalloc(sizeof(*coord), gfp); + if (!desc->addr) { + kfree(desc); + return ERR_PTR(-ENOMEM); + } + + memcpy(desc->addr, coord, sizeof(*coord)); + + return desc; +} +EXPORT_SYMBOL_GPL(cfg802154_alloc_coordinator); + +void cfg802154_free_coordinator_desc(struct ieee802154_coord_desc *desc) +{ + kfree(desc->addr); + kfree(desc); +} +EXPORT_SYMBOL_GPL(cfg802154_free_coordinator_desc); + +static bool +cfg802154_is_same_coordinator(struct ieee802154_coord_desc *a, + struct ieee802154_coord_desc *b) +{ + if (a->addr->pan_id != b->addr->pan_id) + return false; + + if (a->addr->mode != b->addr->mode) + return false; + + if (a->addr->mode == IEEE802154_ADDR_SHORT && + a->addr->short_addr == b->addr->short_addr) + return true; + else if (a->addr->mode == IEEE802154_ADDR_LONG && + a->addr->extended_addr == b->addr->extended_addr) + return true; + + return false; +} + +static bool +cfg802154_coordinator_is_known(struct wpan_dev *wpan_dev, + struct ieee802154_coord_desc *desc) +{ + struct ieee802154_coord_desc *item; + + list_for_each_entry(item, &wpan_dev->coord_list, node) + if (cfg802154_is_same_coordinator(item, desc)) + return true; + + return false; +} + +void cfg802154_record_coordinator(struct wpan_phy *wpan_phy, + struct wpan_dev *wpan_dev, + struct ieee802154_coord_desc *desc) +{ + spin_lock_bh(&wpan_dev->coord_list_lock); + + if (cfg802154_coordinator_is_known(wpan_dev, desc)) { + nl802154_advertise_known_coordinator(wpan_phy, wpan_dev, desc); + cfg802154_free_coordinator_desc(desc); + } else { + list_add_tail(&desc->node, &wpan_dev->coord_list); + nl802154_advertise_new_coordinator(wpan_phy, wpan_dev, desc); + } + + spin_unlock_bh(&wpan_dev->coord_list_lock); +} +EXPORT_SYMBOL_GPL(cfg802154_record_coordinator); + +void cfg802154_flush_known_coordinators(struct wpan_dev *wpan_dev) +{ + struct ieee802154_coord_desc *desc, *tmp; + + spin_lock_bh(&wpan_dev->coord_list_lock); + + list_for_each_entry_safe(desc, tmp, &wpan_dev->coord_list, node) { + list_del(&desc->node); + cfg802154_free_coordinator_desc(desc); + } + + spin_unlock_bh(&wpan_dev->coord_list_lock); +} +EXPORT_SYMBOL_GPL(cfg802154_flush_known_coordinators);