summary refs log tree commit diff stats
path: root/hw/virtio-net.c
diff options
context:
space:
mode:
authorAmos Kong <akong@redhat.com>2013-01-22 23:44:45 +0800
committerMichael S. Tsirkin <mst@redhat.com>2013-01-30 01:31:09 +0200
commitc1943a3f3774ee1aad51e8cc5b8cd24e66e198a5 (patch)
tree3d64b553c9369b022a078a22fef3af6dcaac7cb2 /hw/virtio-net.c
parent921ac5d0f3a0df869db5ce4edf752f51d8b1596a (diff)
downloadfocaccia-qemu-c1943a3f3774ee1aad51e8cc5b8cd24e66e198a5.tar.gz
focaccia-qemu-c1943a3f3774ee1aad51e8cc5b8cd24e66e198a5.zip
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: Amos Kong <akong@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/virtio-net.c')
-rw-r--r--hw/virtio-net.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 9ea987562f..04834e99a7 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -93,7 +93,8 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 
     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);
         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,
     struct virtio_net_ctrl_mac mac_data;
     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) {
         return VIRTIO_NET_ERR;
     }