[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] e1000: indicate dropped packets in HW counters

From: Jason Wang
Subject: Re: [Qemu-devel] [PATCH] e1000: indicate dropped packets in HW counters
Date: Wed, 26 Sep 2018 11:05:36 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1

On 2018年09月25日 16:56, Martin Wilck wrote:
The e1000 emulation silently discards RX packets if there's
insufficient space in the ring buffer. This leads to errors
on higher-level protocols in the guest, with no indication
about the error cause.

This patch increments the "Missed Packets Count" (MPC) and
"Receive No Buffers Count" (RNBC) HW counters in this case.
As the emulation has no FIFO for buffering packets that can't
immediately be pushed to the guest, these two registers are
practically equivalent (see, in

On a Linux guest, the register content  will be reflected in
the "rx_missed_errors" and "rx_no_buffer_count" stats from
"ethtool -S", and in the "missed" stat from "ip -s -s link show",
giving at least some hint about the error cause inside the guest.

If the cause is known, problems like this can often be avoided
easily, by increasing the number of RX descriptors in the guest
e1000 driver (e.g under Linux, "e1000.RxDescriptors=1024").

The patch also adds a qemu trace message for this condition.

Signed-off-by: Martin Wilck <address@hidden>
  hw/net/e1000.c      | 20 ++++++++++++++------
  hw/net/trace-events |  3 +++
  2 files changed, 17 insertions(+), 6 deletions(-)

Applied with a minor tweak: let e1000_receive_overrun() return void instead.


diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 13a9494..312d6b1 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -36,6 +36,7 @@
  #include "qemu/range.h"
#include "e1000x_common.h"
+#include "trace.h"
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -847,6 +848,16 @@ static uint64_t rx_desc_base(E1000State *s)
      return (bah << 32) + bal;
+static int
+e1000_receiver_overrun(E1000State *s, size_t size)
+    trace_e1000_receiver_overrun(size, s->mac_reg[RDH], s->mac_reg[RDT]);
+    e1000x_inc_reg_if_not_full(s->mac_reg, RNBC);
+    e1000x_inc_reg_if_not_full(s->mac_reg, MPC);
+    set_ics(s, 0, E1000_ICS_RXO);
+    return -1;
  static ssize_t
  e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
@@ -915,10 +926,8 @@ e1000_receive_iov(NetClientState *nc, const struct iovec 
*iov, int iovcnt)
      rdh_start = s->mac_reg[RDH];
      desc_offset = 0;
      total_size = size + e1000x_fcs_len(s->mac_reg);
-    if (!e1000_has_rxbufs(s, total_size)) {
-            set_ics(s, 0, E1000_ICS_RXO);
-            return -1;
-    }
+    if (!e1000_has_rxbufs(s, total_size))
+        return e1000_receiver_overrun(s, total_size);
      do {
          desc_size = total_size - desc_offset;
          if (desc_size > s->rxbuf_size) {
@@ -969,8 +978,7 @@ e1000_receive_iov(NetClientState *nc, const struct iovec 
*iov, int iovcnt)
              rdh_start >= s->mac_reg[RDLEN] / sizeof(desc)) {
              DBGOUT(RXERR, "RDH wraparound @%x, RDT %x, RDLEN %x\n",
                     rdh_start, s->mac_reg[RDT], s->mac_reg[RDLEN]);
-            set_ics(s, 0, E1000_ICS_RXO);
-            return -1;
+            return e1000_receiver_overrun(s, total_size);
      } while (desc_offset < total_size);
diff --git a/hw/net/trace-events b/hw/net/trace-events
index 663bea1..7e3da9d 100644
--- a/hw/net/trace-events
+++ b/hw/net/trace-events
@@ -104,6 +104,9 @@ net_rx_pkt_rss_ip6_ex(void) "Calculating IPv6/EX RSS  hash"
  net_rx_pkt_rss_hash(size_t rss_length, uint32_t rss_hash) "RSS hash for %zu bytes: 
  net_rx_pkt_rss_add_chunk(void* ptr, size_t size, size_t input_offset) "Add RSS 
chunk %p, %zu bytes, RSS input offset %zu bytes"
+# hw/net/e1000.c
+e1000_receiver_overrun(size_t s, uint32_t rdh, uint32_t rdt) "Receiver overrun: 
dropped packet of %lu bytes, RDH=%u, RDT=%u"
  # hw/net/e1000x_common.c
  e1000x_rx_can_recv_disabled(bool link_up, bool rx_enabled, bool pci_master) 
"link_up: %d, rx_enabled %d, pci_master %d"
  e1000x_vlan_is_vlan_pkt(bool is_vlan_pkt, uint16_t eth_proto, uint16_t vet) "Is 
VLAN packet: %d, ETH proto: 0x%X, VET: 0x%X"

reply via email to

[Prev in Thread] Current Thread [Next in Thread]