From: Vladislav Yasevich <vyasevic@redhat.com>
To: qemu-devel@nongnu.org
Cc: Vladislav Yasevich <vyasevic@redhat.com>,
jasowang@redhat.com, stefanha@redhat.com
Subject: [Qemu-devel] [PATCH 2/2] rtl8139: correctly track full receive buffer in standard mode
Date: Fri, 21 Aug 2015 14:59:25 -0700 [thread overview]
Message-ID: <1440194365-27610-3-git-send-email-vyasevic@redhat.com> (raw)
In-Reply-To: <1440194365-27610-1-git-send-email-vyasevic@redhat.com>
In standard operation mode, when the receive ring buffer
is full, the buffer actually appears empty to the driver since
the RxBufAddr (the location we wirte new data to) and RxBufPtr
(the location guest would stat reading from) are the same.
As a result, the call to rtl8139_RxBufferEmpty ends up
returning true indicating that the receive buffer is empty.
This would result in the next packet overwriting the recevie buffer
again and stalling receive operations.
This patch catches the "receive buffer full" condition
using an unused C+ register. This is done to simplify
migration and not require a new machine type.
Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com>
---
hw/net/rtl8139.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index 359e001..3d572ab 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -816,6 +816,23 @@ static int rtl8139_can_receive(NetClientState *nc)
}
}
+static void rtl8139_set_rxbuf_full(RTL8139State *s, bool full)
+{
+ /* In standard mode, C+ RxDesc isn't used. Reuse it
+ * to store the rx_buf_full status.
+ */
+ s->currCPlusRxDesc = full;
+ DPRINTF("received: rx buffer full\n");
+}
+
+static bool rtl8139_rxbuf_full(RTL8139State *s)
+{
+ /* In standard mode, C+ RxDesc isn't used. Reuse it
+ * to store the rx_buf_full status.
+ */
+ return !!s->currCPlusRxDesc;
+}
+
static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t size_, int do_interrupt)
{
RTL8139State *s = qemu_get_nic_opaque(nc);
@@ -1178,6 +1195,14 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
/* correct buffer write pointer */
s->RxBufAddr = MOD2((s->RxBufAddr + 3) & ~0x3, s->RxBufferSize);
+ /* Catch buffer full condition. Without this, we end up
+ * assuming that buffer is empty.
+ */
+ if (s->RxBufAddr == s->RxBufPtr)
+ {
+ rtl8139_set_rxbuf_full(s, true);
+ }
+
/* now we can signal we have received something */
DPRINTF("received: rx buffer length %d head 0x%04x read 0x%04x\n",
@@ -1414,9 +1439,10 @@ static int rtl8139_RxBufferEmpty(RTL8139State *s)
{
int unread = MOD2(s->RxBufferSize + s->RxBufAddr - s->RxBufPtr, s->RxBufferSize);
- if (unread != 0)
+ if (unread != 0 || rtl8139_rxbuf_full(s))
{
- DPRINTF("receiver buffer data available 0x%04x\n", unread);
+ DPRINTF("receiver buffer data available 0x%04x\n",
+ unread ? : s->RxBufferSize);
return 0;
}
@@ -1430,7 +1456,10 @@ static uint32_t rtl8139_ChipCmd_read(RTL8139State *s)
uint32_t ret = s->bChipCmdState;
if (rtl8139_RxBufferEmpty(s))
+ {
ret |= RxBufEmpty;
+ rtl8139_set_rxbuf_full(s, false);
+ }
DPRINTF("ChipCmd read val=0x%04x\n", ret);
@@ -2601,6 +2630,9 @@ static void rtl8139_RxBufPtr_write(RTL8139State *s, uint32_t val)
/* this value is off by 16 */
s->RxBufPtr = MOD2(val + 0x10, s->RxBufferSize);
+ /* We just read data, clear full buffer state */
+ rtl8139_set_rxbuf_full(s, false);
+
/* more buffer space may be available so try to receive */
qemu_flush_queued_packets(qemu_get_queue(s->nic));
--
1.9.3
next prev parent reply other threads:[~2015-08-21 21:59 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-21 21:59 [Qemu-devel] [PATCH 0/2] rtl8139: Fix buffer overflow in standard mode Vladislav Yasevich
2015-08-21 21:59 ` [Qemu-devel] [PATCH 1/2] rtl8139: Do not consume the packet during " Vladislav Yasevich
2015-08-26 12:18 ` Stefan Hajnoczi
2015-08-26 13:02 ` Vlad Yasevich
2015-08-21 21:59 ` Vladislav Yasevich [this message]
2015-08-26 12:36 ` [Qemu-devel] [PATCH 2/2] rtl8139: correctly track full receive buffer " Stefan Hajnoczi
2015-08-26 13:07 ` Vlad Yasevich
-- strict thread matches above, loose matches on Subject: below --
2015-08-26 19:51 [Qemu-devel] [PATCH v2 0/2] rtl8139: Fix buffer overflow " Vladislav Yasevich
2015-08-26 19:51 ` [Qemu-devel] [PATCH 2/2] rtl8139: correctly track full receive buffer " Vladislav Yasevich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1440194365-27610-3-git-send-email-vyasevic@redhat.com \
--to=vyasevic@redhat.com \
--cc=jasowang@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).