Re: [PATCH wpan-next 04/11] mac802154: Handle associating

Alexander Aring
2023-06-03T10:10:43Z

Hi,

On Thu, Jun 1, 2023 at 11:50 AM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> 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/linux/ieee802154.h | 1 +
> include/net/cfg802154.h | 1 +
> include/net/ieee802154_netdev.h | 5 ++
> net/ieee802154/core.c | 14 ++++
> net/mac802154/cfg.c | 72 ++++++++++++++++++
> net/mac802154/ieee802154_i.h | 19 +++++
> net/mac802154/main.c | 2 +
> net/mac802154/rx.c | 9 +++
> net/mac802154/scan.c | 127 ++++++++++++++++++++++++++++++++
> 9 files changed, 250 insertions(+)
>
> diff --git a/include/linux/ieee802154.h b/include/linux/ieee802154.h
> index 140f61ec0f5f..c72bd76cac1b 100644
> --- a/include/linux/ieee802154.h
> +++ b/include/linux/ieee802154.h
> @@ -37,6 +37,7 @@
> IEEE802154_FCS_LEN)
>
> #define IEEE802154_PAN_ID_BROADCAST 0xffff
> +#define IEEE802154_ADDR_LONG_BROADCAST 0xffffffffffffffffULL
> #define IEEE802154_ADDR_SHORT_BROADCAST 0xffff
> #define IEEE802154_ADDR_SHORT_UNSPEC 0xfffe
>
> diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
> index 3b9d65455b9a..dd0964d351cd 100644
> --- a/include/net/cfg802154.h
> +++ b/include/net/cfg802154.h
> @@ -502,6 +502,7 @@ struct wpan_dev {
> struct mutex association_lock;
> struct ieee802154_pan_device *parent;
> struct list_head children;
> + unsigned int association_generation;
> };
>
> #define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
> 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..8bf01bb7e858 100644
> --- a/net/ieee802154/core.c
> +++ b/net/ieee802154/core.c
> @@ -198,6 +198,18 @@ 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);
> +
> + if (wpan_dev->parent)
> + kfree(wpan_dev->parent);
> +
> + wpan_dev->association_generation++;
> +
> + mutex_unlock(&wpan_dev->association_lock);
> +}
> +
> int cfg802154_switch_netns(struct cfg802154_registered_device *rdev,
> struct net *net)
> {
> @@ -293,6 +305,8 @@ static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
> rdev->opencount++;
> break;
> case NETDEV_UNREGISTER:
> + cfg802154_free_peer_structures(wpan_dev);
> +

I think the comment below is not relevant here, but I have also no
idea if this is still the case.

> /* 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..89112d2bcee7 100644
> --- a/net/mac802154/cfg.c
> +++ b/net/mac802154/cfg.c
> @@ -315,6 +315,77 @@ 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;
> + }
> +
> + parent = kzalloc(sizeof(*parent), GFP_KERNEL);
> + if (!parent)
> + return -ENOMEM;
> +
> + parent->pan_id = coord->pan_id;
> + parent->mode = coord->mode;
> + if (parent->mode == IEEE802154_SHORT_ADDRESSING) {
> + parent->short_addr = coord->short_addr;
> + parent->extended_addr = cpu_to_le64(IEEE802154_ADDR_LONG_BROADCAST);

There is no IEEE802154_ADDR_LONG_BROADCAST (extended address) address.
The broadcast address is always a short address 0xffff. (Talkin about
destination addresses).

Just to clarify we can have here two different types/length of mac
addresses being used, whereas the extended address is always present.
We have the monitor interface set to an invalid extended address
0x0...0 (talking about source address) which is a reserved EUI64 (what
long/extended address is) address, 0xffff...ffff is also being
reserved. Monitors get their address from the socket interface.

If there is a parent, an extended address is always present and known.
A short address can be set, but is not required as a node to have.
Sure if a node has a short address, you want to use a short address
because it saves payload.
Also remember when an address is unique in the network, an extended
address (LONG) is always being unique, a short address is unique in
combination of pan id + short address.

If you save some neighbors you want to store the extended and if
present panid/shortaddress.

Or I do not understand something here?

btw: as you probably noticed, the netdev interface dev_addr is an
extended address (because it's always present). Now there comes the
ugly part, netdevs cannot deal with other dev_addrs with different
length, that's why it's stored in the wpan specific dev structure and
things don't get easy and solutions need to be found how to make it
working... get prepared to get crazy...

- Alex