diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2022-10-30 18:30:00 -0400 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2022-10-30 18:30:01 -0400 |
commit | 2281c822ee74072659d247a2eb3abf2b786f73b3 (patch) | |
tree | a0f2b5e8de223a27f8c29f174b23e1345b5dc5d0 /hw/net/virtio-net.c | |
parent | d5ab9490cdf3ebcd97793982d4664f951816f6db (diff) | |
parent | e506fee8b1e092f6ac6f9459bf6a35b807644ad2 (diff) |
Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging
# -----BEGIN PGP SIGNATURE-----
# Version: GnuPG v1
#
# iQEcBAABAgAGBQJjW2i1AAoJEO8Ells5jWIR5HMIAIvDEmWQ2eZ1R+CfsefXkD5H
# W3RSZbMrOHR6sb9cbYpqK/vWmH8E/jZkKY4n/q7vQ3QerFMeDPgxu0Qn43iElLXS
# iGHhC51fa5IwJNDomjUGI8oJzyk0sxAbgwOjXZ4qbAkk9KeQYWU+JqYghvOrBYbd
# VaIwEiBlECuBy0DKx2gBTfxgeuw3V3WvtjpKeZVRlR+4vLQtI9Goga78qIPfjpH2
# sN/lFhZGaX1FT8DSft0oCCBxCK8ZaNzmMpmr39a8+e4g/EJZC9xbgNkl3fN0yYa5
# P0nluv/Z6e1TZ4FBDaiVFysTS5WnS0KRjUrodzctiGECE3sQiAvkWbKZ+QdGrlw=
# =0/b/
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 28 Oct 2022 01:29:25 EDT
# gpg: using RSA key EF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [full]
# Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211
* tag 'net-pull-request' of https://github.com/jasowang/qemu: (26 commits)
net: stream: add QAPI events to report connection state
net: stream: move to QIO to enable additional parameters
qemu-sockets: update socket_uri() and socket_parse() to be consistent
qemu-sockets: move and rename SocketAddress_to_str()
net: dgram: add unix socket
net: dgram: move mcast specific code from net_socket_fd_init_dgram()
net: dgram: make dgram_dst generic
net: stream: add unix socket
net: stream: Don't ignore EINVAL on netdev socket connection
net: socket: Don't ignore EINVAL on netdev socket connection
qapi: net: add stream and dgram netdevs
net: introduce qemu_set_info_str() function
qapi: net: introduce a way to bypass qemu_opts_parse_noisily()
net: simplify net_client_parse() error management
net: remove the @errp argument of net_client_inits()
net: introduce convert_host_port()
vhost: Accept event idx flag
vhost: use avail event idx on vhost_svq_kick
vhost: toggle device callbacks using used event idx
vhost: allocate event_idx fields on vring
...
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/net/virtio-net.c')
-rw-r--r-- | hw/net/virtio-net.c | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index e9f696b4cf..b6903aea54 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2526,6 +2526,7 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len) VirtIONet *n = qemu_get_nic_opaque(nc); VirtIONetQueue *q = virtio_net_get_subqueue(nc); VirtIODevice *vdev = VIRTIO_DEVICE(n); + int ret; virtqueue_push(q->tx_vq, q->async_tx.elem, 0); virtio_notify(vdev, q->tx_vq); @@ -2534,7 +2535,22 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len) q->async_tx.elem = NULL; virtio_queue_set_notification(q->tx_vq, 1); - virtio_net_flush_tx(q); + ret = virtio_net_flush_tx(q); + if (ret >= n->tx_burst) { + /* + * the flush has been stopped by tx_burst + * we will not receive notification for the + * remainining part, so re-schedule + */ + virtio_queue_set_notification(q->tx_vq, 0); + if (q->tx_bh) { + qemu_bh_schedule(q->tx_bh); + } else { + timer_mod(q->tx_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); + } + q->tx_waiting = 1; + } } /* TX */ @@ -2633,6 +2649,8 @@ drop: return num_packets; } +static void virtio_net_tx_timer(void *opaque); + static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq) { VirtIONet *n = VIRTIO_NET(vdev); @@ -2650,15 +2668,13 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq) } if (q->tx_waiting) { - virtio_queue_set_notification(vq, 1); + /* We already have queued packets, immediately flush */ timer_del(q->tx_timer); - q->tx_waiting = 0; - if (virtio_net_flush_tx(q) == -EINVAL) { - return; - } + virtio_net_tx_timer(q); } else { + /* re-arm timer to flush it (and more) on next tick */ timer_mod(q->tx_timer, - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); q->tx_waiting = 1; virtio_queue_set_notification(vq, 0); } @@ -2691,6 +2707,8 @@ static void virtio_net_tx_timer(void *opaque) VirtIONetQueue *q = opaque; VirtIONet *n = q->n; VirtIODevice *vdev = VIRTIO_DEVICE(n); + int ret; + /* This happens when device was stopped but BH wasn't. */ if (!vdev->vm_running) { /* Make sure tx waiting is set, so we'll run when restarted. */ @@ -2705,8 +2723,33 @@ static void virtio_net_tx_timer(void *opaque) return; } + ret = virtio_net_flush_tx(q); + if (ret == -EBUSY || ret == -EINVAL) { + return; + } + /* + * If we flush a full burst of packets, assume there are + * more coming and immediately rearm + */ + if (ret >= n->tx_burst) { + q->tx_waiting = 1; + timer_mod(q->tx_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); + return; + } + /* + * If less than a full burst, re-enable notification and flush + * anything that may have come in while we weren't looking. If + * we find something, assume the guest is still active and rearm + */ virtio_queue_set_notification(q->tx_vq, 1); - virtio_net_flush_tx(q); + ret = virtio_net_flush_tx(q); + if (ret > 0) { + virtio_queue_set_notification(q->tx_vq, 0); + q->tx_waiting = 1; + timer_mod(q->tx_timer, + qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + n->tx_timeout); + } } static void virtio_net_tx_bh(void *opaque) |