* [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented
@ 2013-09-10 12:19 Vincenzo Maffione
2013-09-11 8:39 ` Stefan Hajnoczi
0 siblings, 1 reply; 4+ messages in thread
From: Vincenzo Maffione @ 2013-09-10 12:19 UTC (permalink / raw)
To: qemu-devel
Cc: anthony, mst, jasowang, Vincenzo Maffione, stefanha, pbonzini,
g.lettieri, rizzo
This patch implements the NetClientInfo.receive_iov method for the
e1000 device emulation. In this way a network backend that uses
qemu_sendv_packet() can deliver the fragmented packet without
requiring an additional copy in the frontend/backend network code
(nc_sendv_compat() function).
The existing method NetClientInfo.receive has been reimplemented
using the new method.
Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
---
hw/net/e1000.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 59 insertions(+), 12 deletions(-)
I propose this patch also because our research group (University of Pisa,
Department of Computer Engineering) is working on the e1000 device
(optimizations and paravirtual extensions) and we have patches to
support the VALE switch as a network backend (see
http://info.iet.unipi.it/~luigi/vale/).
The VALE backend uses qemu_sendv_packet() to send fragmented packets: For
this reason we think it could be interesting to better support these packets
with e1000.
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index f5ebed4..6ff54b5 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -32,6 +32,7 @@
#include "hw/loader.h"
#include "sysemu/sysemu.h"
#include "sysemu/dma.h"
+#include "qemu/iov.h"
#include "e1000_regs.h"
@@ -64,6 +65,8 @@ static int debugflags = DBGBIT(TXERR) | DBGBIT(GENERAL);
/* this is the size past which hardware will drop packets when setting LPE=1 */
#define MAXIMUM_ETHERNET_LPE_SIZE 16384
+#define MAXIMUM_ETHERNET_HDR_LEN (14+4)
+
/*
* HW models:
* E1000_DEV_ID_82540EM works with Windows and Linux
@@ -825,7 +828,7 @@ static uint64_t rx_desc_base(E1000State *s)
}
static ssize_t
-e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
{
E1000State *s = qemu_get_nic_opaque(nc);
PCIDevice *d = PCI_DEVICE(s);
@@ -834,8 +837,12 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
unsigned int n, rdt;
uint32_t rdh_start;
uint16_t vlan_special = 0;
- uint8_t vlan_status = 0, vlan_offset = 0;
+ uint8_t vlan_status = 0;
uint8_t min_buf[MIN_BUF_SIZE];
+ struct iovec min_iov;
+ uint8_t *filter_buf = iov->iov_base;
+ size_t size = iov_size(iov, iovcnt);
+ size_t iov_ofs = 0;
size_t desc_offset;
size_t desc_size;
size_t total_size;
@@ -850,10 +857,16 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
/* Pad to minimum Ethernet frame length */
if (size < sizeof(min_buf)) {
- memcpy(min_buf, buf, size);
+ iov_to_buf(iov, iovcnt, 0, min_buf, size);
memset(&min_buf[size], 0, sizeof(min_buf) - size);
- buf = min_buf;
- size = sizeof(min_buf);
+ min_iov.iov_base = filter_buf = min_buf;
+ min_iov.iov_len = size = sizeof(min_buf);
+ iovcnt = 1;
+ iov = &min_iov;
+ } else if (iov->iov_len < MAXIMUM_ETHERNET_HDR_LEN) {
+ /* This is very unlikely, but may happen. */
+ iov_to_buf(iov, iovcnt, 0, min_buf, MAXIMUM_ETHERNET_HDR_LEN);
+ filter_buf = min_buf;
}
/* Discard oversized packets if !LPE and !SBP. */
@@ -864,14 +877,24 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
return size;
}
- if (!receive_filter(s, buf, size))
+ if (!receive_filter(s, filter_buf, size)) {
return size;
+ }
- if (vlan_enabled(s) && is_vlan_packet(s, buf)) {
- vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(buf + 14)));
- memmove((uint8_t *)buf + 4, buf, 12);
+ if (vlan_enabled(s) && is_vlan_packet(s, filter_buf)) {
+ vlan_special = cpu_to_le16(be16_to_cpup((uint16_t *)(filter_buf
+ + 14)));
+ iov_ofs = 4;
+ if (filter_buf == iov->iov_base) {
+ memmove(filter_buf + 4, filter_buf, 12);
+ } else {
+ iov_from_buf(iov, iovcnt, 4, filter_buf, 12);
+ while (iov->iov_len <= iov_ofs) {
+ iov_ofs -= iov->iov_len;
+ iov++;
+ }
+ }
vlan_status = E1000_RXD_STAT_VP;
- vlan_offset = 4;
size -= 4;
}
@@ -893,12 +916,24 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
desc.status |= (vlan_status | E1000_RXD_STAT_DD);
if (desc.buffer_addr) {
if (desc_offset < size) {
+ size_t iov_copy, copied = 0;
+ hwaddr ba = le64_to_cpu(desc.buffer_addr);
size_t copy_size = size - desc_offset;
if (copy_size > s->rxbuf_size) {
copy_size = s->rxbuf_size;
}
- pci_dma_write(d, le64_to_cpu(desc.buffer_addr),
- buf + desc_offset + vlan_offset, copy_size);
+ do {
+ iov_copy = MIN(copy_size, iov->iov_len - iov_ofs);
+ pci_dma_write(d, ba + copied,
+ iov->iov_base + iov_ofs, iov_copy);
+ copy_size -= iov_copy;
+ copied += iov_copy;
+ iov_ofs += iov_copy;
+ if (iov_ofs == iov->iov_len) {
+ iov++;
+ iov_ofs = 0;
+ }
+ } while (copy_size);
}
desc_offset += desc_size;
desc.length = cpu_to_le16(desc_size);
@@ -948,6 +983,17 @@ e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
return size;
}
+static ssize_t
+e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+ const struct iovec iov = {
+ .iov_base = (uint8_t *)buf,
+ .iov_len = size
+ };
+
+ return e1000_receive_iov(nc, &iov, 1);
+}
+
static uint32_t
mac_readreg(E1000State *s, int index)
{
@@ -1326,6 +1372,7 @@ static NetClientInfo net_e1000_info = {
.size = sizeof(NICState),
.can_receive = e1000_can_receive,
.receive = e1000_receive,
+ .receive_iov = e1000_receive_iov,
.cleanup = e1000_cleanup,
.link_status_changed = e1000_set_link_status,
};
--
1.8.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented
2013-09-10 12:19 [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented Vincenzo Maffione
@ 2013-09-11 8:39 ` Stefan Hajnoczi
2013-09-11 10:57 ` Vincenzo Maffione
0 siblings, 1 reply; 4+ messages in thread
From: Stefan Hajnoczi @ 2013-09-11 8:39 UTC (permalink / raw)
To: Vincenzo Maffione
Cc: mst, jasowang, qemu-devel, anthony, pbonzini, g.lettieri, rizzo
On Tue, Sep 10, 2013 at 02:19:47PM +0200, Vincenzo Maffione wrote:
> This patch implements the NetClientInfo.receive_iov method for the
> e1000 device emulation. In this way a network backend that uses
> qemu_sendv_packet() can deliver the fragmented packet without
> requiring an additional copy in the frontend/backend network code
> (nc_sendv_compat() function).
>
> The existing method NetClientInfo.receive has been reimplemented
> using the new method.
>
> Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
> ---
> hw/net/e1000.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 59 insertions(+), 12 deletions(-)
>
> I propose this patch also because our research group (University of Pisa,
> Department of Computer Engineering) is working on the e1000 device
> (optimizations and paravirtual extensions) and we have patches to
> support the VALE switch as a network backend (see
> http://info.iet.unipi.it/~luigi/vale/).
> The VALE backend uses qemu_sendv_packet() to send fragmented packets: For
> this reason we think it could be interesting to better support these packets
> with e1000.
Thanks, applied to my net tree:
https://github.com/stefanha/qemu/commits/net
Stefan
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented
2013-09-11 8:39 ` Stefan Hajnoczi
@ 2013-09-11 10:57 ` Vincenzo Maffione
2013-09-12 8:23 ` Stefan Hajnoczi
0 siblings, 1 reply; 4+ messages in thread
From: Vincenzo Maffione @ 2013-09-11 10:57 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, anthony,
Paolo Bonzini, Giuseppe Lettieri, Luigi Rizzo
[-- Attachment #1: Type: text/plain, Size: 1640 bytes --]
Thanks for the help!
Actually I've found out that the variable "copied" I use in this patch can
be removed, we can simply increment the variable "ba" instead (ba +=
iov_copy).
I have the patch v3 to do that ready. Do you think it is worth sending it?
Best regards,
Vincenzo
2013/9/11 Stefan Hajnoczi <stefanha@redhat.com>
> On Tue, Sep 10, 2013 at 02:19:47PM +0200, Vincenzo Maffione wrote:
> > This patch implements the NetClientInfo.receive_iov method for the
> > e1000 device emulation. In this way a network backend that uses
> > qemu_sendv_packet() can deliver the fragmented packet without
> > requiring an additional copy in the frontend/backend network code
> > (nc_sendv_compat() function).
> >
> > The existing method NetClientInfo.receive has been reimplemented
> > using the new method.
> >
> > Signed-off-by: Vincenzo Maffione <v.maffione@gmail.com>
> > ---
> > hw/net/e1000.c | 71
> ++++++++++++++++++++++++++++++++++++++++++++++++----------
> > 1 file changed, 59 insertions(+), 12 deletions(-)
> >
> > I propose this patch also because our research group (University of Pisa,
> > Department of Computer Engineering) is working on the e1000 device
> > (optimizations and paravirtual extensions) and we have patches to
> > support the VALE switch as a network backend (see
> > http://info.iet.unipi.it/~luigi/vale/).
> > The VALE backend uses qemu_sendv_packet() to send fragmented packets: For
> > this reason we think it could be interesting to better support these
> packets
> > with e1000.
>
> Thanks, applied to my net tree:
> https://github.com/stefanha/qemu/commits/net
>
> Stefan
>
--
Vincenzo Maffione
[-- Attachment #2: Type: text/html, Size: 2502 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented
2013-09-11 10:57 ` Vincenzo Maffione
@ 2013-09-12 8:23 ` Stefan Hajnoczi
0 siblings, 0 replies; 4+ messages in thread
From: Stefan Hajnoczi @ 2013-09-12 8:23 UTC (permalink / raw)
To: Vincenzo Maffione
Cc: Stefan Hajnoczi, Michael S. Tsirkin, Jason Wang, qemu-devel,
anthony, Paolo Bonzini, Giuseppe Lettieri, Luigi Rizzo
On Wed, Sep 11, 2013 at 12:57:58PM +0200, Vincenzo Maffione wrote:
> Thanks for the help!
>
> Actually I've found out that the variable "copied" I use in this patch can
> be removed, we can simply increment the variable "ba" instead (ba +=
> iov_copy).
>
> I have the patch v3 to do that ready. Do you think it is worth sending it?
Yep, that would be good. I'll replace the patch with v3.
Stefan
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-09-12 8:23 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-10 12:19 [Qemu-devel] [PATCH v2] e1000: NetClientInfo.receive_iov implemented Vincenzo Maffione
2013-09-11 8:39 ` Stefan Hajnoczi
2013-09-11 10:57 ` Vincenzo Maffione
2013-09-12 8:23 ` Stefan Hajnoczi
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).