提交 c1943a3f 编写于 作者: A Amos Kong 提交者: Michael S. Tsirkin

virtio-net: introduce a new macaddr control

In virtio-net guest driver, currently we write MAC address to
pci config space byte by byte, this means that we have an
intermediate step where mac is wrong. This patch introduced
a new control command to set MAC address, it's atomic.

VIRTIO_NET_F_CTRL_MAC_ADDR is a new feature bit for compatibility.

"mac" field will be set to read-only when VIRTIO_NET_F_CTRL_MAC_ADDR
is acked.
Signed-off-by: NAmos Kong <akong@redhat.com>
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
上级 921ac5d0
...@@ -309,6 +309,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = { ...@@ -309,6 +309,10 @@ static QEMUMachine pc_i440fx_machine_v1_4 = {
.driver = "usb-tablet",\ .driver = "usb-tablet",\
.property = "usb_version",\ .property = "usb_version",\
.value = stringify(1),\ .value = stringify(1),\
},{\
.driver = "virtio-net-pci",\
.property = "ctrl_mac_addr",\
.value = "off", \
} }
static QEMUMachine pc_machine_v1_3 = { static QEMUMachine pc_machine_v1_3 = {
......
...@@ -93,7 +93,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config) ...@@ -93,7 +93,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
memcpy(&netcfg, config, sizeof(netcfg)); memcpy(&netcfg, config, sizeof(netcfg));
if (memcmp(netcfg.mac, n->mac, ETH_ALEN)) { if (!(n->vdev.guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
memcpy(n->mac, netcfg.mac, ETH_ALEN); memcpy(n->mac, netcfg.mac, ETH_ALEN);
qemu_format_nic_info_str(&n->nic->nc, n->mac); qemu_format_nic_info_str(&n->nic->nc, n->mac);
} }
...@@ -351,6 +352,16 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd, ...@@ -351,6 +352,16 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
struct virtio_net_ctrl_mac mac_data; struct virtio_net_ctrl_mac mac_data;
size_t s; size_t s;
if (cmd == VIRTIO_NET_CTRL_MAC_ADDR_SET) {
if (iov_size(iov, iov_cnt) != sizeof(n->mac)) {
return VIRTIO_NET_ERR;
}
s = iov_to_buf(iov, iov_cnt, 0, &n->mac, sizeof(n->mac));
assert(s == sizeof(n->mac));
qemu_format_nic_info_str(&n->nic->nc, n->mac);
return VIRTIO_NET_OK;
}
if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) { if (cmd != VIRTIO_NET_CTRL_MAC_TABLE_SET) {
return VIRTIO_NET_ERR; return VIRTIO_NET_ERR;
} }
......
...@@ -44,6 +44,8 @@ ...@@ -44,6 +44,8 @@
#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ #define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */
#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ #define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
#define TX_TIMER_INTERVAL 150000 /* 150 us */ #define TX_TIMER_INTERVAL 150000 /* 150 us */
...@@ -106,7 +108,7 @@ typedef uint8_t virtio_net_ctrl_ack; ...@@ -106,7 +108,7 @@ typedef uint8_t virtio_net_ctrl_ack;
#define VIRTIO_NET_CTRL_RX_MODE_NOBCAST 5 #define VIRTIO_NET_CTRL_RX_MODE_NOBCAST 5
/* /*
* Control the MAC filter table. * Control the MAC
* *
* The MAC filter table is managed by the hypervisor, the guest should * The MAC filter table is managed by the hypervisor, the guest should
* assume the size is infinite. Filtering should be considered * assume the size is infinite. Filtering should be considered
...@@ -119,6 +121,10 @@ typedef uint8_t virtio_net_ctrl_ack; ...@@ -119,6 +121,10 @@ typedef uint8_t virtio_net_ctrl_ack;
* first sg list contains unicast addresses, the second is for multicast. * first sg list contains unicast addresses, the second is for multicast.
* This functionality is present if the VIRTIO_NET_F_CTRL_RX feature * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature
* is available. * is available.
*
* The ADDR_SET command requests one out scatterlist, it contains a
* 6 bytes MAC address. This functionality is present if the
* VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.
*/ */
struct virtio_net_ctrl_mac { struct virtio_net_ctrl_mac {
uint32_t entries; uint32_t entries;
...@@ -126,6 +132,7 @@ struct virtio_net_ctrl_mac { ...@@ -126,6 +132,7 @@ struct virtio_net_ctrl_mac {
}; };
#define VIRTIO_NET_CTRL_MAC 1 #define VIRTIO_NET_CTRL_MAC 1
#define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0
#define VIRTIO_NET_CTRL_MAC_ADDR_SET 1
/* /*
* Control VLAN filtering * Control VLAN filtering
...@@ -158,5 +165,6 @@ struct virtio_net_ctrl_mac { ...@@ -158,5 +165,6 @@ struct virtio_net_ctrl_mac {
DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \ DEFINE_PROP_BIT("ctrl_vq", _state, _field, VIRTIO_NET_F_CTRL_VQ, true), \
DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \ DEFINE_PROP_BIT("ctrl_rx", _state, _field, VIRTIO_NET_F_CTRL_RX, true), \
DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \ DEFINE_PROP_BIT("ctrl_vlan", _state, _field, VIRTIO_NET_F_CTRL_VLAN, true), \
DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true) DEFINE_PROP_BIT("ctrl_rx_extra", _state, _field, VIRTIO_NET_F_CTRL_RX_EXTRA, true), \
DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true)
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册