]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
mac802154: Follow the number of associated devices
authorMiquel Raynal <miquel.raynal@bootlin.com>
Wed, 27 Sep 2023 18:12:12 +0000 (20:12 +0200)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Mon, 20 Nov 2023 10:43:19 +0000 (11:43 +0100)
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>
Acked-by: Stefan Schmidt <stefan@datenfreihafen.org>
Acked-by: Alexander Aring <aahringo@redhat.com>
Link: https://lore.kernel.org/linux-wpan/20230927181214.129346-10-miquel.raynal@bootlin.com
include/net/cfg802154.h
net/ieee802154/core.c
net/mac802154/cfg.c
net/mac802154/scan.c

index 0d3e9af00198b7ac9dd3a8617bb769b4e11c2f26..a64bbcd71f1038d205f424775a9ccca58c2ae8b4 100644 (file)
@@ -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)
index 2d6fe45efa052f1483cf254ade991ccdbc998b2e..60e8fff1347ee8c02863e63ccec0a8e79e33015a 100644 (file)
@@ -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);
 }
 
index 083de2d3fe375d27092f9865224757c7fc05ce76..17e2032fac2420d8fcd042634752945fe6f48637 100644 (file)
@@ -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;
index d5f66c204bc5ed2277eaaca7922fe1e40d337d93..81d2c2bb1f09a9213143e81202942e734112464d 100644 (file)
@@ -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);