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);
{
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?
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)
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
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;
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);
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 */
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;
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;
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);
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);