ieee802154: setting extended address while iface add
authorAlexander Aring <alex.aring@gmail.com>
Mon, 17 Nov 2014 07:20:52 +0000 (08:20 +0100)
committerMarcel Holtmann <marcel@holtmann.org>
Mon, 17 Nov 2014 08:49:16 +0000 (09:49 +0100)
This patch adds support for setting an extended address while
registration a new interface. If ieee802154_is_valid_extended_addr
getting as parameter and invalid extended address then the perm address
is fallback. This is useful to make some default handling while for
example default registration of a wpan interface while phy registration.

Signed-off-by: Alexander Aring <alex.aring@gmail.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
include/net/cfg802154.h
net/ieee802154/nl802154.c
net/ieee802154/rdev-ops.h
net/mac802154/cfg.c
net/mac802154/ieee802154_i.h
net/mac802154/iface.c
net/mac802154/main.c

index 24c7321f364736f941dc1ffac5f9e4725b327563..4a9bb0e3db2b287048186ea29537dad06c815702 100644 (file)
@@ -41,7 +41,8 @@ struct cfg802154_ops {
                                               struct net_device *dev);
        int     (*add_virtual_intf)(struct wpan_phy *wpan_phy,
                                    const char *name,
-                                   enum nl802154_iftype type);
+                                   enum nl802154_iftype type,
+                                   __le64 extended_addr);
        int     (*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
        int     (*set_pan_id)(struct wpan_phy *wpan_phy,
                              struct wpan_dev *wpan_dev, u16 pan_id);
index e7224f3c15846e7125d75190be678428008cce57..49c4d8a5004a36bf20b53f2d4bc1d360114580a8 100644 (file)
@@ -555,6 +555,7 @@ static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg802154_registered_device *rdev = info->user_ptr[0];
        enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
+       __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
 
        /* TODO avoid failing a new interface
         * creation due to pending removal?
@@ -569,12 +570,17 @@ static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
                        return -EINVAL;
        }
 
+       /* TODO add nla_get_le64 to netlink */
+       if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
+               extended_addr = (__force __le64)nla_get_u64(
+                               info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
+
        if (!rdev->ops->add_virtual_intf)
                return -EOPNOTSUPP;
 
        return rdev_add_virtual_intf(rdev,
                                     nla_data(info->attrs[NL802154_ATTR_IFNAME]),
-                                    type);
+                                    type, extended_addr);
 }
 
 static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
index d3a4f94c5fdcc7a869c5131060a47f71c4a98871..06e97542dafb59fe85f74da1fc262507e0340770 100644 (file)
@@ -22,9 +22,10 @@ rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
 
 static inline int
 rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name,
-                     enum nl802154_iftype type)
+                     enum nl802154_iftype type, __le64 extended_addr)
 {
-       return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type);
+       return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type,
+                                          extended_addr);
 }
 
 static inline int
index ae1a9ef2d42c0275eba9c1a1dee88f22640070d7..568d712bfc8caff711bdb1b78b2274fcc0371af2 100644 (file)
@@ -28,7 +28,8 @@ ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
        struct net_device *dev;
 
        rtnl_lock();
-       dev = ieee802154_if_add(local, name, type);
+       dev = ieee802154_if_add(local, name, type,
+                               cpu_to_le64(0x0000000000000000ULL));
        rtnl_unlock();
 
        return dev;
@@ -44,12 +45,12 @@ static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
 
 static int
 ieee802154_add_iface(struct wpan_phy *phy, const char *name,
-                    enum nl802154_iftype type)
+                    enum nl802154_iftype type, __le64 extended_addr)
 {
        struct ieee802154_local *local = wpan_phy_priv(phy);
        struct net_device *err;
 
-       err = ieee802154_if_add(local, name, type);
+       err = ieee802154_if_add(local, name, type, extended_addr);
        if (IS_ERR(err))
                return PTR_ERR(err);
 
index 46553830896d1d68d9b887b2152f7804c6d96c46..cc691637d24b844513c577ec8b0256cadbc98452 100644 (file)
@@ -176,7 +176,7 @@ void ieee802154_iface_exit(void);
 void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata);
 struct net_device *
 ieee802154_if_add(struct ieee802154_local *local, const char *name,
-                 enum nl802154_iftype type);
+                 enum nl802154_iftype type, __le64 extended_addr);
 void ieee802154_remove_interfaces(struct ieee802154_local *local);
 
 #endif /* __IEEE802154_I_H */
index ba63ac93ae9046514e207acd5c9960e180dea36b..38dfc72d24b689483facf8404d12970978cb3e56 100644 (file)
@@ -458,7 +458,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
 
 struct net_device *
 ieee802154_if_add(struct ieee802154_local *local, const char *name,
-                 enum nl802154_iftype type)
+                 enum nl802154_iftype type, __le64 extended_addr)
 {
        struct net_device *ndev = NULL;
        struct ieee802154_sub_if_data *sdata = NULL;
@@ -477,9 +477,16 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name,
        if (ret < 0)
                goto err;
 
+       ieee802154_le64_to_be64(ndev->perm_addr,
+                               &local->hw.phy->perm_extended_addr);
        switch (type) {
        case NL802154_IFTYPE_NODE:
                ndev->type = ARPHRD_IEEE802154;
+               if (ieee802154_is_valid_extended_addr(extended_addr))
+                       ieee802154_le64_to_be64(ndev->dev_addr, &extended_addr);
+               else
+                       memcpy(ndev->dev_addr, ndev->perm_addr,
+                              IEEE802154_EXTENDED_ADDR_LEN);
                break;
        case NL802154_IFTYPE_MONITOR:
                ndev->type = ARPHRD_IEEE802154_MONITOR;
@@ -489,9 +496,6 @@ ieee802154_if_add(struct ieee802154_local *local, const char *name,
                goto err;
        }
 
-       ieee802154_le64_to_be64(ndev->perm_addr,
-                               &local->hw.phy->perm_extended_addr);
-       memcpy(ndev->dev_addr, ndev->perm_addr, IEEE802154_EXTENDED_ADDR_LEN);
        /* TODO check this */
        SET_NETDEV_DEV(ndev, &local->phy->dev);
        sdata = netdev_priv(ndev);
index bbb19dd585a07646c7452be8edd56cca3c9d5b43..8500378c8318cd3b5b7e3a368f44080b40c5900f 100644 (file)
@@ -161,7 +161,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw)
 
        rtnl_lock();
 
-       dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE);
+       dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE,
+                               cpu_to_le64(0x0000000000000000ULL));
        if (IS_ERR(dev)) {
                rtnl_unlock();
                rc = PTR_ERR(dev);