Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Cindy Lu <lulu@redhat.com>
Message-Id: <20240731031653.1047692-2-lulu@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>

authored by

Cindy Lu and committed by
Michael S. Tsirkin
2f87e9cf a8927f69

+89
+79
drivers/vdpa/vdpa.c
··· 1361 1361 return err; 1362 1362 } 1363 1363 1364 + static int vdpa_dev_net_device_attr_set(struct vdpa_device *vdev, 1365 + struct genl_info *info) 1366 + { 1367 + struct vdpa_dev_set_config set_config = {}; 1368 + struct vdpa_mgmt_dev *mdev = vdev->mdev; 1369 + struct nlattr **nl_attrs = info->attrs; 1370 + const u8 *macaddr; 1371 + int err = -EOPNOTSUPP; 1372 + 1373 + down_write(&vdev->cf_lock); 1374 + if (nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]) { 1375 + set_config.mask |= BIT_ULL(VDPA_ATTR_DEV_NET_CFG_MACADDR); 1376 + macaddr = nla_data(nl_attrs[VDPA_ATTR_DEV_NET_CFG_MACADDR]); 1377 + 1378 + if (is_valid_ether_addr(macaddr)) { 1379 + ether_addr_copy(set_config.net.mac, macaddr); 1380 + if (mdev->ops->dev_set_attr) { 1381 + err = mdev->ops->dev_set_attr(mdev, vdev, 1382 + &set_config); 1383 + } else { 1384 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 1385 + "Operation not supported by the device."); 1386 + } 1387 + } else { 1388 + NL_SET_ERR_MSG_FMT_MOD(info->extack, 1389 + "Invalid MAC address"); 1390 + } 1391 + } 1392 + up_write(&vdev->cf_lock); 1393 + return err; 1394 + } 1395 + 1396 + static int vdpa_nl_cmd_dev_attr_set_doit(struct sk_buff *skb, 1397 + struct genl_info *info) 1398 + { 1399 + struct vdpa_device *vdev; 1400 + struct device *dev; 1401 + const char *name; 1402 + u64 classes; 1403 + int err = 0; 1404 + 1405 + if (!info->attrs[VDPA_ATTR_DEV_NAME]) 1406 + return -EINVAL; 1407 + 1408 + name = nla_data(info->attrs[VDPA_ATTR_DEV_NAME]); 1409 + 1410 + down_write(&vdpa_dev_lock); 1411 + dev = bus_find_device(&vdpa_bus, NULL, name, vdpa_name_match); 1412 + if (!dev) { 1413 + NL_SET_ERR_MSG_MOD(info->extack, "device not found"); 1414 + err = -ENODEV; 1415 + goto dev_err; 1416 + } 1417 + vdev = container_of(dev, struct vdpa_device, dev); 1418 + if (!vdev->mdev) { 1419 + NL_SET_ERR_MSG_MOD(info->extack, "unmanaged vdpa device"); 1420 + err = -EINVAL; 1421 + goto mdev_err; 1422 + } 1423 + classes = vdpa_mgmtdev_get_classes(vdev->mdev, NULL); 1424 + if (classes & BIT_ULL(VIRTIO_ID_NET)) { 1425 + err = vdpa_dev_net_device_attr_set(vdev, info); 1426 + } else { 1427 + NL_SET_ERR_MSG_FMT_MOD(info->extack, "%s device not supported", 1428 + name); 1429 + } 1430 + 1431 + mdev_err: 1432 + put_device(dev); 1433 + dev_err: 1434 + up_write(&vdpa_dev_lock); 1435 + return err; 1436 + } 1437 + 1364 1438 static int vdpa_dev_config_dump(struct device *dev, void *data) 1365 1439 { 1366 1440 struct vdpa_device *vdev = container_of(dev, struct vdpa_device, dev); ··· 1569 1495 { 1570 1496 .cmd = VDPA_CMD_DEV_VSTATS_GET, 1571 1497 .doit = vdpa_nl_cmd_dev_stats_get_doit, 1498 + .flags = GENL_ADMIN_PERM, 1499 + }, 1500 + { 1501 + .cmd = VDPA_CMD_DEV_ATTR_SET, 1502 + .doit = vdpa_nl_cmd_dev_attr_set_doit, 1572 1503 .flags = GENL_ADMIN_PERM, 1573 1504 }, 1574 1505 };
+9
include/linux/vdpa.h
··· 582 582 * @dev: vdpa device to remove 583 583 * Driver need to remove the specified device by calling 584 584 * _vdpa_unregister_device(). 585 + * @dev_set_attr: change a vdpa device's attr after it was create 586 + * @mdev: parent device to use for device 587 + * @dev: vdpa device structure 588 + * @config:Attributes to be set for the device. 589 + * The driver needs to check the mask of the structure and then set 590 + * the related information to the vdpa device. The driver must return 0 591 + * if set successfully. 585 592 */ 586 593 struct vdpa_mgmtdev_ops { 587 594 int (*dev_add)(struct vdpa_mgmt_dev *mdev, const char *name, 588 595 const struct vdpa_dev_set_config *config); 589 596 void (*dev_del)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev); 597 + int (*dev_set_attr)(struct vdpa_mgmt_dev *mdev, struct vdpa_device *dev, 598 + const struct vdpa_dev_set_config *config); 590 599 }; 591 600 592 601 /**
+1
include/uapi/linux/vdpa.h
··· 19 19 VDPA_CMD_DEV_GET, /* can dump */ 20 20 VDPA_CMD_DEV_CONFIG_GET, /* can dump */ 21 21 VDPA_CMD_DEV_VSTATS_GET, 22 + VDPA_CMD_DEV_ATTR_SET, 22 23 }; 23 24 24 25 enum vdpa_attr {