|
Mark McLoughlin |
b65c30 |
From 2e7c7b6cb25603e2fa40990da86d03a57b2616bd Mon Sep 17 00:00:00 2001
|
|
Mark McLoughlin |
b29fd2 |
From: Mark McLoughlin <markmc@redhat.com>
|
|
Mark McLoughlin |
b29fd2 |
Date: Thu, 29 Oct 2009 11:34:17 +0000
|
|
Mark McLoughlin |
b29fd2 |
Subject: [PATCH] net: disable draining tap queue in one go
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
If qemu_send_packet_async() returns zero, it means the packet has been
|
|
Mark McLoughlin |
b29fd2 |
queued and the sent callback will be invoked once it has been flushed.
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
This is only possible where the NIC's receive() handler returns zero
|
|
Mark McLoughlin |
b29fd2 |
and promises to notify the networking core that room is available in its
|
|
Mark McLoughlin |
b29fd2 |
queue again.
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
In the case where the receive handler does not have this capability
|
|
Mark McLoughlin |
b29fd2 |
(and its queue fills up) it returns -1 and the networking core does not
|
|
Mark McLoughlin |
b29fd2 |
queue up the packet. This condition is indicated by a -1 return from
|
|
Mark McLoughlin |
b29fd2 |
qemu_send_packet_async().
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
Currently, tap handles this condition simply by dropping the packet. It
|
|
Mark McLoughlin |
b29fd2 |
should do its best to avoid getting into this situation by checking such
|
|
Mark McLoughlin |
b29fd2 |
NIC's have room for a packet before copying the packet from the tap
|
|
Mark McLoughlin |
b29fd2 |
interface.
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
tap_send() used to achieve this by only reading a single packet before
|
|
Mark McLoughlin |
b29fd2 |
returning to the mainloop. That way, tap_can_send() is called before
|
|
Mark McLoughlin |
b29fd2 |
reading each packet.
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
tap_send() was changed to completely drain the tap interface queue
|
|
Mark McLoughlin |
b29fd2 |
without taking into account the situation where the NIC returns an
|
|
Mark McLoughlin |
b29fd2 |
error and the packet is not queued. Let's start fixing this by
|
|
Mark McLoughlin |
b29fd2 |
reverting to the previous behaviour of reading one packet at a time.
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
Reported-by: Scott Tsai <scottt.tw@gmail.com>
|
|
Mark McLoughlin |
b29fd2 |
Tested-by: Sven Rudolph <Sven_Rudolph@drewag.de>
|
|
Mark McLoughlin |
b29fd2 |
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
Fedora-patch: qemu-fix-dropped-packets-with-non-virtio-nics.patch
|
|
Mark McLoughlin |
b29fd2 |
---
|
|
Mark McLoughlin |
b29fd2 |
net.c | 29 +++++++++++++----------------
|
|
Mark McLoughlin |
b29fd2 |
1 files changed, 13 insertions(+), 16 deletions(-)
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
diff --git a/net.c b/net.c
|
|
Mark McLoughlin |
b65c30 |
index 3572c48..522e33c 100644
|
|
Mark McLoughlin |
b29fd2 |
--- a/net.c
|
|
Mark McLoughlin |
b29fd2 |
+++ b/net.c
|
|
Mark McLoughlin |
b29fd2 |
@@ -1453,27 +1453,24 @@ static void tap_send(void *opaque)
|
|
Mark McLoughlin |
b29fd2 |
{
|
|
Mark McLoughlin |
b29fd2 |
TAPState *s = opaque;
|
|
Mark McLoughlin |
b29fd2 |
int size;
|
|
Mark McLoughlin |
b29fd2 |
+ uint8_t *buf = s->buf;
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
- do {
|
|
Mark McLoughlin |
b29fd2 |
- uint8_t *buf = s->buf;
|
|
Mark McLoughlin |
b29fd2 |
-
|
|
Mark McLoughlin |
b29fd2 |
- size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
|
|
Mark McLoughlin |
b29fd2 |
- if (size <= 0) {
|
|
Mark McLoughlin |
b29fd2 |
- break;
|
|
Mark McLoughlin |
b29fd2 |
- }
|
|
Mark McLoughlin |
b29fd2 |
+ size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
|
|
Mark McLoughlin |
b29fd2 |
+ if (size <= 0) {
|
|
Mark McLoughlin |
b65c30 |
+ return;
|
|
Mark McLoughlin |
b29fd2 |
+ }
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
#ifdef IFF_VNET_HDR
|
|
Mark McLoughlin |
b29fd2 |
- if (s->has_vnet_hdr && !s->using_vnet_hdr) {
|
|
Mark McLoughlin |
b29fd2 |
- buf += sizeof(struct virtio_net_hdr);
|
|
Mark McLoughlin |
b29fd2 |
- size -= sizeof(struct virtio_net_hdr);
|
|
Mark McLoughlin |
b29fd2 |
- }
|
|
Mark McLoughlin |
b29fd2 |
+ if (s->has_vnet_hdr && !s->using_vnet_hdr) {
|
|
Mark McLoughlin |
b29fd2 |
+ buf += sizeof(struct virtio_net_hdr);
|
|
Mark McLoughlin |
b29fd2 |
+ size -= sizeof(struct virtio_net_hdr);
|
|
Mark McLoughlin |
b29fd2 |
+ }
|
|
Mark McLoughlin |
b29fd2 |
#endif
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
- size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
|
|
Mark McLoughlin |
b29fd2 |
- if (size == 0) {
|
|
Mark McLoughlin |
b29fd2 |
- tap_read_poll(s, 0);
|
|
Mark McLoughlin |
b29fd2 |
- }
|
|
Mark McLoughlin |
b29fd2 |
- } while (size > 0);
|
|
Mark McLoughlin |
b29fd2 |
+ size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
|
|
Mark McLoughlin |
b29fd2 |
+ if (size == 0) {
|
|
Mark McLoughlin |
b29fd2 |
+ tap_read_poll(s, 0);
|
|
Mark McLoughlin |
b29fd2 |
+ }
|
|
Mark McLoughlin |
b29fd2 |
}
|
|
Mark McLoughlin |
b29fd2 |
|
|
Mark McLoughlin |
b29fd2 |
#ifdef TUNSETSNDBUF
|
|
Mark McLoughlin |
b29fd2 |
--
|
|
Mark McLoughlin |
b29fd2 |
1.6.2.5
|
|
Mark McLoughlin |
b29fd2 |
|