From 9d8c6a258c70d8ff494489140a4fcb3a965909b2 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 27 Feb 2019 13:24:07 +0000 Subject: virtio-net: Switch to using announce timer Switch virtio's self announcement to use the AnnounceTimer. It keeps it's own AnnounceTimer (per device), and starts running it using a migration post-load and a virtual clock; that way the announce happens once the guest is actually running. The timer uses the migration parameters to set the timing of the repeats. Based on earlier patches by myself and Vladislav Yasevich Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Michael S. Tsirkin Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'hw/net/virtio-net.c') diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 6e6b146..38b8974 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -21,12 +21,14 @@ #include "qemu/timer.h" #include "hw/virtio/virtio-net.h" #include "net/vhost_net.h" +#include "net/announce.h" #include "hw/virtio/virtio-bus.h" #include "qapi/error.h" #include "qapi/qapi-events-net.h" #include "hw/virtio/virtio-access.h" #include "migration/misc.h" #include "standard-headers/linux/ethtool.h" +#include "trace.h" #define VIRTIO_NET_VM_VERSION 11 @@ -152,8 +154,9 @@ static void virtio_net_announce_timer(void *opaque) { VirtIONet *n = opaque; VirtIODevice *vdev = VIRTIO_DEVICE(n); + trace_virtio_net_announce_timer(n->announce_timer.round); - n->announce_counter--; + n->announce_timer.round--; n->status |= VIRTIO_NET_S_ANNOUNCE; virtio_notify_config(vdev); } @@ -467,8 +470,8 @@ static void virtio_net_reset(VirtIODevice *vdev) n->nobcast = 0; /* multiqueue is disabled by default */ n->curr_queues = 1; - timer_del(n->announce_timer); - n->announce_counter = 0; + timer_del(n->announce_timer.tm); + n->announce_timer.round = 0; n->status &= ~VIRTIO_NET_S_ANNOUNCE; /* Flush any MAC and VLAN filter table state */ @@ -964,13 +967,12 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd, static int virtio_net_handle_announce(VirtIONet *n, uint8_t cmd, struct iovec *iov, unsigned int iov_cnt) { + trace_virtio_net_handle_announce(n->announce_timer.round); if (cmd == VIRTIO_NET_CTRL_ANNOUNCE_ACK && n->status & VIRTIO_NET_S_ANNOUNCE) { n->status &= ~VIRTIO_NET_S_ANNOUNCE; - if (n->announce_counter) { - timer_mod(n->announce_timer, - qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + - self_announce_delay(n->announce_counter)); + if (n->announce_timer.round) { + qemu_announce_timer_step(&n->announce_timer); } return VIRTIO_NET_OK; } else { @@ -2286,6 +2288,7 @@ static int virtio_net_post_load_device(void *opaque, int version_id) VirtIODevice *vdev = VIRTIO_DEVICE(n); int i, link_down; + trace_virtio_net_post_load_device(); virtio_net_set_mrg_rx_bufs(n, n->mergeable_rx_bufs, virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)); @@ -2322,8 +2325,15 @@ static int virtio_net_post_load_device(void *opaque, int version_id) if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { - n->announce_counter = SELF_ANNOUNCE_ROUNDS; - timer_mod(n->announce_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL)); + qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(), + QEMU_CLOCK_VIRTUAL, + virtio_net_announce_timer, n); + if (n->announce_timer.round) { + timer_mod(n->announce_timer.tm, + qemu_clock_get_ms(n->announce_timer.type)); + } else { + qemu_announce_timer_del(&n->announce_timer); + } } return 0; @@ -2679,8 +2689,9 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) qemu_macaddr_default_if_unset(&n->nic_conf.macaddr); memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac)); n->status = VIRTIO_NET_S_LINK_UP; - n->announce_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, - virtio_net_announce_timer, n); + qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(), + QEMU_CLOCK_VIRTUAL, + virtio_net_announce_timer, n); if (n->netclient_type) { /* @@ -2743,8 +2754,7 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) virtio_net_del_queue(n, i); } - timer_del(n->announce_timer); - timer_free(n->announce_timer); + qemu_announce_timer_del(&n->announce_timer); g_free(n->vqs); qemu_del_nic(n->nic); virtio_net_rsc_cleanup(n); -- cgit v1.1 From b2c929f02ba37b206144735313af10fb9cc5d1a4 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Wed, 27 Feb 2019 13:24:10 +0000 Subject: virtio-net: Allow qemu_announce_self to trigger virtio announcements Expose the virtio-net self announcement capability and allow qemu_announce_self() to call it. These announces are caused by something external (i.e. the announce-self command); they won't trigger if the migration counter is triggering announces at the same time. Signed-off-by: Vladislav Yasevich Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Michael S. Tsirkin Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'hw/net/virtio-net.c') diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 38b8974..7e2c2a6 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -150,15 +150,42 @@ static bool virtio_net_started(VirtIONet *n, uint8_t status) (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running; } +static void virtio_net_announce_notify(VirtIONet *net) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(net); + trace_virtio_net_announce_notify(); + + net->status |= VIRTIO_NET_S_ANNOUNCE; + virtio_notify_config(vdev); +} + static void virtio_net_announce_timer(void *opaque) { VirtIONet *n = opaque; - VirtIODevice *vdev = VIRTIO_DEVICE(n); trace_virtio_net_announce_timer(n->announce_timer.round); n->announce_timer.round--; - n->status |= VIRTIO_NET_S_ANNOUNCE; - virtio_notify_config(vdev); + virtio_net_announce_notify(n); +} + +static void virtio_net_announce(NetClientState *nc) +{ + VirtIONet *n = qemu_get_nic_opaque(nc); + VirtIODevice *vdev = VIRTIO_DEVICE(n); + + /* + * Make sure the virtio migration announcement timer isn't running + * If it is, let it trigger announcement so that we do not cause + * confusion. + */ + if (n->announce_timer.round) { + return; + } + + if (virtio_vdev_has_feature(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE) && + virtio_vdev_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) { + virtio_net_announce_notify(n); + } } static void virtio_net_vhost_status(VirtIONet *n, uint8_t status) @@ -2556,6 +2583,7 @@ static NetClientInfo net_virtio_info = { .receive = virtio_net_receive, .link_status_changed = virtio_net_set_link_status, .query_rx_filter = virtio_net_query_rxfilter, + .announce = virtio_net_announce, }; static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx) @@ -2692,6 +2720,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) qemu_announce_timer_reset(&n->announce_timer, migrate_announce_params(), QEMU_CLOCK_VIRTUAL, virtio_net_announce_timer, n); + n->announce_timer.round = 0; if (n->netclient_type) { /* -- cgit v1.1