diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2023-09-27 20:12:10 +0200 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2023-11-20 11:43:03 +0100 |
commit | 601f160b61b2152ef84a663f856350d5dd9e752a (patch) | |
tree | 035f2a6481882b2079378a5075c41c39e27612ff /net/ieee802154 | |
parent | 9860d9be89f420f3793fb798faadea11c723e08a (diff) |
mac802154: Handle association requests from peers
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>
Acked-by: Stefan Schmidt <stefan@datenfreihafen.org>
Acked-by: Alexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/linux-wpan/20230927181214.129346-8-miquel.raynal@bootlin.com
Diffstat (limited to 'net/ieee802154')
-rw-r--r-- | net/ieee802154/core.c | 7 | ||||
-rw-r--r-- | net/ieee802154/pan.c | 30 |
2 files changed, 37 insertions, 0 deletions
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 43b8d2df2186..545461069197 100644 --- a/net/ieee802154/pan.c +++ b/net/ieee802154/pan.c @@ -63,3 +63,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); |