Commit 2f87e9cf authored by Cindy Lu's avatar Cindy Lu Committed by Michael S. Tsirkin

vdpa: support set mac address from vdpa tool

Add new UAPI to support the mac address from vdpa tool
Function vdpa_nl_cmd_dev_attr_set_doit() will get the
new MAC address from the vdpa tool and then set it to the device.

The usage is: vdpa dev set name vdpa_name mac **:**:**:**:**:**

Here is example:
root@L1# vdpa -jp dev config show vdpa0
{
    "config": {
        "vdpa0": {
            "mac": "82:4d:e9:5d:d7:e6",
            "link ": "up",
            "link_announce ": false,
            "mtu": 1500
        }
    }
}

root@L1# vdpa dev set name vdpa0 mac 00:11:22:33:44:55

root@L1# vdpa -jp dev config show vdpa0
{
    "config": {
        "vdpa0": {
            "mac": "00:11:22:33:44:55",
            "link ": "up",
            "link_announce ": false,
            "mtu": 1500
        }
    }
}
Signed-off-by: default avatarCindy Lu <lulu@redhat.com>
Message-Id: <20240731031653.1047692-2-lulu@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Acked-by: default avatarJason Wang <jasowang@redhat.com>
parent a8927f69
...@@ -1361,6 +1361,80 @@ static int vdpa_nl_cmd_dev_config_get_doit(struct sk_buff *skb, struct genl_info ...@@ -1361,6 +1361,80 @@ static int vdpa_nl_cmd_dev_config_get_doit(struct sk_buff *skb, struct genl_info
return err; return err;
} }
static int vdpa_dev_net_device_attr_set(struct vdpa_device *vdev,
struct genl_info *info)
{
struct vdpa_dev_set_config set_config = {};
struct vdpa_mgmt_dev *mdev = vdev->mdev;
struct nlattr **nl_attrs = info->attrs;
const u8 *macaddr;
int err = -EOPNOTSUPP;
down_write(&vdev->cf_lock);
if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]) {
set_config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR);
macaddr = nla_data(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]);
if (is_valid_ether_addr(macaddr)) {
ether_addr_copy(set_config.net.mac, macaddr);
if (mdev->ops->dev_set_attr) {
err = mdev->ops->dev_set_attr(mdev, vdev,
&set_config);
} else {
NL_SET_ERR_MSG_FMT_MOD(info->extack,
"Operation not supported by the device.");
}
} else {
NL_SET_ERR_MSG_FMT_MOD(info->extack,
"Invalid MAC address");
}
}
up_write(&vdev->cf_lock);
return err;
}
static int vdpa_nl_cmd_dev_attr_set_doit(struct sk_buff *skb,
struct genl_info *info)
{
struct vdpa_device *vdev;
struct device *dev;
const char *name;
u64 classes;
int err = 0;
if (!info->attrs[VDPA_ATTR_DEV_NAME])
return -EINVAL;
name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]);
down_write(&vdpa_dev_lock);
dev = bus_find_device(&vdpa_bus, NULL, name, vdpa_name_match);
if (!dev) {
NL_SET_ERR_MSG_MOD(info->extack, "device not found");
err = -ENODEV;
goto dev_err;
}
vdev = container_of(dev, struct vdpa_device, dev);
if (!vdev->mdev) {
NL_SET_ERR_MSG_MOD(info->extack, "unmanaged vdpa device");
err = -EINVAL;
goto mdev_err;
}
classes = vdpa_mgmtdev_get_classes(vdev->mdev, NULL);
if (classes & BIT_ULL(VIRTIO_ID_NET)) {
err = vdpa_dev_net_device_attr_set(vdev, info);
} else {
NL_SET_ERR_MSG_FMT_MOD(info->extack, "%s device not supported",
name);
}
mdev_err:
put_device(dev);
dev_err:
up_write(&vdpa_dev_lock);
return err;
}
static int vdpa_dev_config_dump(struct device *dev, void *data) static int vdpa_dev_config_dump(struct device *dev, void *data)
{ {
struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev);
...@@ -1497,6 +1571,11 @@ static const struct genl_ops vdpa_nl_ops[] = { ...@@ -1497,6 +1571,11 @@ static const struct genl_ops vdpa_nl_ops[] = {
.doit = vdpa_nl_cmd_dev_stats_get_doit, .doit = vdpa_nl_cmd_dev_stats_get_doit,
.flags = GENL_ADMIN_PERM, .flags = GENL_ADMIN_PERM,
}, },
{
.cmd = VDPA_CMD_DEV_ATTR_SET,
.doit = vdpa_nl_cmd_dev_attr_set_doit,
.flags = GENL_ADMIN_PERM,
},
}; };
static struct genl_family vdpa_nl_family __ro_after_init = { static struct genl_family vdpa_nl_family __ro_after_init = {
......
...@@ -582,11 +582,20 @@ void vdpa_set_status(struct vdpa_device *vdev, u8 status); ...@@ -582,11 +582,20 @@ void vdpa_set_status(struct vdpa_device *vdev, u8 status);
* @dev: vdpa device to remove * @dev: vdpa device to remove
* Driver need to remove the specified device by calling * Driver need to remove the specified device by calling
* _vdpa_unregister_device(). * _vdpa_unregister_device().
* @dev_set_attr: change a vdpa device's attr after it was create
* @mdev: parent device to use for device
* @dev: vdpa device structure
* @config:Attributes to be set for the device.
* The driver needs to check the mask of the structure and then set
* the related information to the vdpa device. The driver must return 0
* if set successfully.
*/ */
struct vdpa_mgmtdev_ops { struct vdpa_mgmtdev_ops {
int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name, int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name,
const struct vdpa_dev_set_config *config); const struct vdpa_dev_set_config *config);
void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev); void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev);
int (*dev_set_attr)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev,
const struct vdpa_dev_set_config *config);
}; };
/** /**
......
...@@ -19,6 +19,7 @@ enum vdpa_command { ...@@ -19,6 +19,7 @@ enum vdpa_command {
VDPA_CMD_DEV_GET, /* can dump */ VDPA_CMD_DEV_GET, /* can dump */
VDPA_CMD_DEV_CONFIG_GET, /* can dump */ VDPA_CMD_DEV_CONFIG_GET, /* can dump */
VDPA_CMD_DEV_VSTATS_GET, VDPA_CMD_DEV_VSTATS_GET,
VDPA_CMD_DEV_ATTR_SET,
}; };
enum vdpa_attr { enum vdpa_attr {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment