|
From: | Vincenzo Maffione |
Subject: | Re: [Qemu-devel] [PATCH] net: QEMU_NET_PACKET_FLAG_MORE introduced |
Date: | Mon, 9 Dec 2013 11:20:29 +0100 |
On Fri, Dec 06, 2013 at 03:44:33PM +0100, Vincenzo Maffione wrote:So we are batching some more and this helps throughput. However I wonder
> This patch extends the frontend-backend interface so that it is possible
> to pass a new flag (QEMU_NET_PACKET_FLAG_MORE) when sending a packet to the
> other peer. The new flag acts as a hint for the receiving peer, which can
> accumulate a batch of packets before forwarding those packets (to the host
> if the receiving peer is the backend or to the guest if the receiving peer
> is the frontend).
>
> The patch also implements a batching mechanism for the netmap backend (on the
> backend receive side) and for the e1000 and virtio frontends (on the frontend
> transmit side).
>
> Measured improvement of a guest-to-guest UDP_STREAM netperf test (64 bytes
> packets) with virtio-net frontends:
> 820 Kpps ==> 1000 Kpps (+22%).
>
> Measured improvement of a guest-to-guest UDP test (64 bytes packets) with
> e1000 frontends and netmap clients on the guests:
> 1.8 Mpps ==> 3.1 Mpps (+72%).
>
> Signed-off-by: Vincenzo Maffione <address@hidden>
what this does to a more bursty traffic, such as
several TCP streams running in parallel.
> ---
> Experiment details:
> - Processor: Intel i7-3770K CPU @ 3.50GHz (8 cores)
> - Memory @ 1333 MHz
> - Host O.S.: Archlinux with Linux 3.11
> - Guest O.S.: Archlinux with Linux 3.11
>
> QEMU command line for the virtio experiment:
> qemu-system-x86_64 archdisk.qcow -snapshot -enable-kvm -device virtio-net-pci,ioeventfd=on,mac=00:AA:BB:CC:DD:01,netdev=mynet -netdev netmap,ifname=vale0:01,id=mynet -smp 2 -vga std -m 3G
>
> QEMU command line for the e1000 experiment:
> qemu-system-x86_64 archdisk.qcow -snapshot -enable-kvm -device e1000,mitigation=off,mac=00:AA:BB:CC:DD:01,netdev=mynet -netdev netmap,ifname=vale0:01,id=mynet -smp 2 -vga std -m 3G
>
> With the e1000 experiments, we don't use netperf on the guests, but netmap clients (pkt-gen)
> that run directly on the e1000 adapter, bypassing the O.S. stack.
>
> Other things:
> - This patch is against the net-next tree (https://github.com/stefanha/qemu.git)
> because the first netmap patch is not in the qemu master (AFAIK).
> - The batching can also be implemented on the backend transmit side and frontend
> receive side. We could do it in the future.
>
> hw/net/cadence_gem.c | 3 ++-
> hw/net/dp8393x.c | 5 +++--
> hw/net/e1000.c | 21 ++++++++++++++++-----
> hw/net/eepro100.c | 5 +++--
> hw/net/etraxfs_eth.c | 5 +++--
> hw/net/lan9118.c | 2 +-
> hw/net/mcf_fec.c | 5 +++--
> hw/net/mipsnet.c | 6 ++++--
> hw/net/ne2000.c | 5 +++--
> hw/net/ne2000.h | 3 ++-
> hw/net/opencores_eth.c | 2 +-
> hw/net/pcnet.c | 8 +++++---
> hw/net/pcnet.h | 3 ++-
> hw/net/rtl8139.c | 7 ++++---
> hw/net/smc91c111.c | 5 +++--
> hw/net/spapr_llan.c | 2 +-
> hw/net/stellaris_enet.c | 3 ++-
> hw/net/virtio-net.c | 10 ++++++++--
> hw/net/vmxnet3.c | 3 ++-
> hw/net/vmxnet_tx_pkt.c | 4 ++--
> hw/net/xgmac.c | 2 +-
> hw/net/xilinx_axienet.c | 2 +-
> hw/usb/dev-network.c | 8 +++++---
> include/net/net.h | 20 +++++++++++++-------
> include/net/queue.h | 1 +
> net/dump.c | 3 ++-
> net/hub.c | 10 ++++++----
> net/net.c | 39 +++++++++++++++++++++++----------------
> net/netmap.c | 17 ++++++++++++-----
> net/slirp.c | 5 +++--
> net/socket.c | 10 ++++++----
> net/tap-win32.c | 2 +-
> net/tap.c | 12 +++++++-----
> net/vde.c | 5 +++--
> savevm.c | 2 +-
> 35 files changed, 155 insertions(+), 90 deletions(-)
>
> diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c
> index 4a355bb..432687a 100644
> --- a/hw/net/cadence_gem.c
> +++ b/hw/net/cadence_gem.c
> @@ -583,7 +583,8 @@ static int gem_mac_address_filter(GemState *s, const uint8_t *packet)
> * gem_receive:
> * Fit a packet handed to us by QEMU into the receive descriptor ring.
> */
> -static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> unsigned desc[2];
> hwaddr packet_desc_addr, last_desc_addr;
> diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
> index 789d385..d8c7da8 100644
> --- a/hw/net/dp8393x.c
> +++ b/hw/net/dp8393x.c
> @@ -415,7 +415,7 @@ static void do_transmit_packets(dp8393xState *s)
> }
> } else {
> /* Transmit packet */
> - qemu_send_packet(nc, s->tx_buffer, tx_len);
> + qemu_send_packet(nc, s->tx_buffer, tx_len, 0);
> }
> s->regs[SONIC_TCR] |= SONIC_TCR_PTX;
>
> @@ -723,7 +723,8 @@ static int receive_filter(dp8393xState *s, const uint8_t * buf, int size)
> return -1;
> }
>
> -static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
> +static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf,
> + size_t size, unsigned flags)
> {
> dp8393xState *s = qemu_get_nic_opaque(nc);
> uint16_t data[10];
> diff --git a/hw/net/e1000.c b/hw/net/e1000.c
> index ae63591..5294ec5 100644
> --- a/hw/net/e1000.c
> +++ b/hw/net/e1000.c
> @@ -570,10 +570,19 @@ static void
> e1000_send_packet(E1000State *s, const uint8_t *buf, int size)
> {
> NetClientState *nc = qemu_get_queue(s->nic);
> + uint32_t tdh = s->mac_reg[TDH];
> + unsigned flags = QEMU_NET_PACKET_FLAG_MORE;
> +
> if (s->phy_reg[PHY_CTRL] & MII_CR_LOOPBACK) {
> - nc->info->receive(nc, buf, size);
> + nc->info->receive(nc, buf, size, 0);
> } else {
> - qemu_send_packet(nc, buf, size);
> + if (++tdh * sizeof(struct e1000_tx_desc) >= s->mac_reg[TDLEN]) {
> + tdh = 0;
> + }
> + if (tdh == s->mac_reg[TDT]) {
> + flags = 0;
> + }
> + qemu_send_packet(nc, buf, size, flags);
> }
> }
>
> @@ -899,7 +908,8 @@ static uint64_t rx_desc_base(E1000State *s)
> }
>
> static ssize_t
> -e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
> +e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt,
> + unsigned flags)
> {
> E1000State *s = qemu_get_nic_opaque(nc);
> PCIDevice *d = PCI_DEVICE(s);
> @@ -1054,14 +1064,15 @@ e1000_receive_iov(NetClientState *nc, const struct iovec *iov, int iovcnt)
> }
>
> static ssize_t
> -e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +e1000_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> const struct iovec iov = {
> .iov_base = (uint8_t *)buf,
> .iov_len = size
> };
>
> - return e1000_receive_iov(nc, &iov, 1);
> + return e1000_receive_iov(nc, &iov, 1, flags);
> }
>
> static uint32_t
> diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c
> index 3b891ca..9763904 100644
> --- a/hw/net/eepro100.c
> +++ b/hw/net/eepro100.c
> @@ -828,7 +828,7 @@ static void tx_command(EEPRO100State *s)
> }
> }
> TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
> - qemu_send_packet(qemu_get_queue(s->nic), buf, size);
> + qemu_send_packet(qemu_get_queue(s->nic), buf, size, 0);
> s->statistics.tx_good_frames++;
> /* Transmit with bad status would raise an CX/TNO interrupt.
> * (82557 only). Emulation never has bad status. */
> @@ -1627,7 +1627,8 @@ static int nic_can_receive(NetClientState *nc)
> #endif
> }
>
> -static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
> +static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf,
> + size_t size, unsigned flags)
> {
> /* TODO:
> * - Magic packets should set bit 30 in power management driver register.
> diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c
> index 78ebbbc..6cba74e 100644
> --- a/hw/net/etraxfs_eth.c
> +++ b/hw/net/etraxfs_eth.c
> @@ -525,7 +525,8 @@ static int eth_can_receive(NetClientState *nc)
> return 1;
> }
>
> -static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
> ETRAXFSEthState *eth = qemu_get_nic_opaque(nc);
> @@ -560,7 +561,7 @@ static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
> ETRAXFSEthState *eth = opaque;
>
> D(printf("%s buf=%p len=%d\n", __func__, buf, len));
> - qemu_send_packet(qemu_get_queue(eth->nic), buf, len);
> + qemu_send_packet(qemu_get_queue(eth->nic), buf, len, 0);
> return len;
> }
>
> diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
> index 2315f99..55e06a9 100644
> --- a/hw/net/lan9118.c
> +++ b/hw/net/lan9118.c
> @@ -664,7 +664,7 @@ static void do_tx_packet(lan9118_state *s)
> /* This assumes the receive routine doesn't touch the VLANClient. */
> lan9118_receive(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
> } else {
> - qemu_send_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len);
> + qemu_send_packet(qemu_get_queue(s->nic), s->txp->data, s->txp->len, 0);
> }
> s->txp->fifo_used = 0;
>
> diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
> index 4bff3de..14ed0dd 100644
> --- a/hw/net/mcf_fec.c
> +++ b/hw/net/mcf_fec.c
> @@ -174,7 +174,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s)
> if (bd.flags & FEC_BD_L) {
> /* Last buffer in frame. */
> DPRINTF("Sending packet\n");
> - qemu_send_packet(qemu_get_queue(s->nic), frame, len);
> + qemu_send_packet(qemu_get_queue(s->nic), frame, len, 0);
> ptr = frame;
> frame_size = 0;
> s->eir |= FEC_INT_TXF;
> @@ -357,7 +357,8 @@ static int mcf_fec_can_receive(NetClientState *nc)
> return s->rx_enabled;
> }
>
> -static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t mcf_fec_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> mcf_fec_state *s = qemu_get_nic_opaque(nc);
> mcf_fec_bd bd;
> diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c
> index e421b86..7f5d4c4 100644
> --- a/hw/net/mipsnet.c
> +++ b/hw/net/mipsnet.c
> @@ -74,7 +74,8 @@ static int mipsnet_can_receive(NetClientState *nc)
> return !mipsnet_buffer_full(s);
> }
>
> -static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> MIPSnetState *s = qemu_get_nic_opaque(nc);
>
> @@ -176,7 +177,8 @@ static void mipsnet_ioport_write(void *opaque, hwaddr addr,
> if (s->tx_written == s->tx_count) {
> /* Send buffer. */
> trace_mipsnet_send(s->tx_count);
> - qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, s->tx_count);
> + qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer,
> + s->tx_count, 0);
> s->tx_count = s->tx_written = 0;
> s->intctl |= MIPSNET_INTCTL_TXDONE;
> s->busy = 1;
> diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c
> index 4c32e9e..52af46a 100644
> --- a/hw/net/ne2000.c
> +++ b/hw/net/ne2000.c
> @@ -176,7 +176,8 @@ int ne2000_can_receive(NetClientState *nc)
>
> #define MIN_BUF_SIZE 60
>
> -ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
> +ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_,
> + unsigned flags)
> {
> NE2000State *s = qemu_get_nic_opaque(nc);
> int size = size_;
> @@ -301,7 +302,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
> /* fail safe: check range on the transmitted length */
> if (index + s->tcnt <= NE2000_PMEM_END) {
> qemu_send_packet(qemu_get_queue(s->nic), s->mem + index,
> - s->tcnt);
> + s->tcnt, 0);
> }
> /* signal end of transfer */
> s->tsr = ENTSR_PTX;
> diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h
> index e500306..b62a8f3 100644
> --- a/hw/net/ne2000.h
> +++ b/hw/net/ne2000.h
> @@ -35,6 +35,7 @@ void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size);
> extern const VMStateDescription vmstate_ne2000;
> void ne2000_reset(NE2000State *s);
> int ne2000_can_receive(NetClientState *nc);
> -ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
> +ssize_t ne2000_receive(NetClientState *nc, const uint8_t *buf, size_t size_,
> + unsigned flags);
>
> #endif
> diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c
> index 4118d54..b4328ea 100644
> --- a/hw/net/opencores_eth.c
> +++ b/hw/net/opencores_eth.c
> @@ -503,7 +503,7 @@ static void open_eth_start_xmit(OpenEthState *s, desc *tx)
> if (tx_len > len) {
> memset(buf + len, 0, tx_len - len);
> }
> - qemu_send_packet(qemu_get_queue(s->nic), buf, tx_len);
> + qemu_send_packet(qemu_get_queue(s->nic), buf, tx_len, 0);
>
> if (tx->len_flags & TXD_WR) {
> s->tx_desc = 0;
> diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
> index 7cb47b3..707ac92 100644
> --- a/hw/net/pcnet.c
> +++ b/hw/net/pcnet.c
> @@ -1019,7 +1019,8 @@ int pcnet_can_receive(NetClientState *nc)
>
> #define MIN_BUF_SIZE 60
>
> -ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
> +ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_,
> + unsigned flags)
> {
> PCNetState *s = qemu_get_nic_opaque(nc);
> int is_padr = 0, is_bcast = 0, is_ladr = 0;
> @@ -1265,12 +1266,13 @@ static void pcnet_transmit(PCNetState *s)
> if (BCR_SWSTYLE(s) == 1)
> add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
> s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
> - pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
> + pcnet_receive(qemu_get_queue(s->nic), s->buffer,
> + s->xmit_pos, 0);
> s->looptest = 0;
> } else
> if (s->nic)
> qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
> - s->xmit_pos);
> + s->xmit_pos, 0);
>
> s->csr[0] &= ~0x0008; /* clear TDMD */
> s->csr[4] |= 0x0004; /* set TXSTRT */
> diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h
> index 9dee6f3..a26aacd 100644
> --- a/hw/net/pcnet.h
> +++ b/hw/net/pcnet.h
> @@ -61,7 +61,8 @@ void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val);
> uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr);
> uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
> int pcnet_can_receive(NetClientState *nc);
> -ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_);
> +ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_,
> + unsigned flags);
> void pcnet_set_link_status(NetClientState *nc);
> void pcnet_common_cleanup(PCNetState *d);
> int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info);
> diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
> index 7f2b4db..340331f 100644
> --- a/hw/net/rtl8139.c
> +++ b/hw/net/rtl8139.c
> @@ -1195,7 +1195,8 @@ static ssize_t rtl8139_do_receive(NetClientState *nc, const uint8_t *buf, size_t
> return size_;
> }
>
> -static ssize_t rtl8139_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t rtl8139_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> return rtl8139_do_receive(nc, buf, size, 1);
> }
> @@ -1814,9 +1815,9 @@ static void rtl8139_transfer_frame(RTL8139State *s, uint8_t *buf, int size,
> else
> {
> if (iov) {
> - qemu_sendv_packet(qemu_get_queue(s->nic), iov, 3);
> + qemu_sendv_packet(qemu_get_queue(s->nic), iov, 3, 0);
> } else {
> - qemu_send_packet(qemu_get_queue(s->nic), buf, size);
> + qemu_send_packet(qemu_get_queue(s->nic), buf, size, 0);
> }
> }
> }
> diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
> index a8e29b3..82289aa 100644
> --- a/hw/net/smc91c111.c
> +++ b/hw/net/smc91c111.c
> @@ -242,7 +242,7 @@ static void smc91c111_do_tx(smc91c111_state *s)
> smc91c111_release_packet(s, packetnum);
> else if (s->tx_fifo_done_len < NUM_PACKETS)
> s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
> - qemu_send_packet(qemu_get_queue(s->nic), p, len);
> + qemu_send_packet(qemu_get_queue(s->nic), p, len, 0);
> }
> s->tx_fifo_len = 0;
> smc91c111_update(s);
> @@ -647,7 +647,8 @@ static int smc91c111_can_receive(NetClientState *nc)
> return 1;
> }
>
> -static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> smc91c111_state *s = qemu_get_nic_opaque(nc);
> int status;
> diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c
> index 1bd6f50..1a50bc1 100644
> --- a/hw/net/spapr_llan.c
> +++ b/hw/net/spapr_llan.c
> @@ -476,7 +476,7 @@ static target_ulong h_send_logical_lan(PowerPCCPU *cpu, sPAPREnvironment *spapr,
> p += VLAN_BD_LEN(bufs[i]);
> }
>
> - qemu_send_packet(qemu_get_queue(dev->nic), lbuf, total_len);
> + qemu_send_packet(qemu_get_queue(dev->nic), lbuf, total_len, 0);
>
> return H_SUCCESS;
> }
> diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c
> index 9dd77f7..950b455 100644
> --- a/hw/net/stellaris_enet.c
> +++ b/hw/net/stellaris_enet.c
> @@ -83,7 +83,8 @@ static void stellaris_enet_update(stellaris_enet_state *s)
> }
>
> /* TODO: Implement MAC address filtering. */
> -static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> stellaris_enet_state *s = qemu_get_nic_opaque(nc);
> int n;
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 513c168..b25bc4e 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -938,7 +938,8 @@ static int receive_filter(VirtIONet *n, const uint8_t *buf, int size)
> return 0;
> }
>
> -static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> VirtIONet *n = qemu_get_nic_opaque(nc);
> VirtIONetQueue *q = virtio_net_get_subqueue(nc);
> @@ -1079,6 +1080,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
> unsigned int out_num = elem.out_num;
> struct iovec *out_sg = &elem.out_sg[0];
> struct iovec sg[VIRTQUEUE_MAX_SIZE];
> + unsigned flags = QEMU_NET_PACKET_FLAG_MORE;
>
> if (out_num < 1) {
> error_report("virtio-net header not in first element");
> @@ -1104,8 +1106,12 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
>
> len = n->guest_hdr_len;
>
> + if (num_packets + 1 >= n->tx_burst || virtio_queue_empty(q->tx_vq)) {
> + flags = 0;
> + }
> ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
> - out_sg, out_num, virtio_net_tx_complete);
> + out_sg, out_num, virtio_net_tx_complete,
> + flags);
> if (ret == 0) {
> virtio_queue_set_notification(q->tx_vq, 0);
> q->async_tx.elem = elem;
> diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
> index 19687aa..6bd59d0 100644
> --- a/hw/net/vmxnet3.c
> +++ b/hw/net/vmxnet3.c
> @@ -1817,7 +1817,8 @@ vmxnet3_rx_filter_may_indicate(VMXNET3State *s, const void *data,
> }
>
> static ssize_t
> -vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +vmxnet3_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> VMXNET3State *s = qemu_get_nic_opaque(nc);
> size_t bytes_indicated;
> diff --git a/hw/net/vmxnet_tx_pkt.c b/hw/net/vmxnet_tx_pkt.c
> index f7344c4..12d842e 100644
> --- a/hw/net/vmxnet_tx_pkt.c
> +++ b/hw/net/vmxnet_tx_pkt.c
> @@ -526,7 +526,7 @@ static bool vmxnet_tx_pkt_do_sw_fragmentation(struct VmxnetTxPkt *pkt,
>
> eth_fix_ip4_checksum(l3_iov_base, l3_iov_len);
>
> - qemu_sendv_packet(nc, fragment, dst_idx);
> + qemu_sendv_packet(nc, fragment, dst_idx, 0);
>
> fragment_offset += fragment_len;
>
> @@ -559,7 +559,7 @@ bool vmxnet_tx_pkt_send(struct VmxnetTxPkt *pkt, NetClientState *nc)
> if (pkt->has_virt_hdr ||
> pkt->virt_hdr.gso_type == VIRTIO_NET_HDR_GSO_NONE) {
> qemu_sendv_packet(nc, pkt->vec,
> - pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG);
> + pkt->payload_frags + VMXNET_TX_PKT_PL_START_FRAG, 0);
> return true;
> }
>
> diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c
> index 9384fa0..683a5ad 100644
> --- a/hw/net/xgmac.c
> +++ b/hw/net/xgmac.c
> @@ -239,7 +239,7 @@ static void xgmac_enet_send(XgmacState *s)
> frame_size += len;
> if (bd.ctl_stat & 0x20000000) {
> /* Last buffer in frame. */
> - qemu_send_packet(qemu_get_queue(s->nic), frame, len);
> + qemu_send_packet(qemu_get_queue(s->nic), frame, len, 0);
> ptr = frame;
> frame_size = 0;
> s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
> diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c
> index 3eb7715..9dd44bf 100644
> --- a/hw/net/xilinx_axienet.c
> +++ b/hw/net/xilinx_axienet.c
> @@ -919,7 +919,7 @@ xilinx_axienet_data_stream_push(StreamSlave *obj, uint8_t *buf, size_t size)
> buf[write_off + 1] = csum & 0xff;
> }
>
> - qemu_send_packet(qemu_get_queue(s->nic), buf, size);
> + qemu_send_packet(qemu_get_queue(s->nic), buf, size, 0);
>
> s->stats.tx_bytes += size;
> s->regs[R_IS] |= IS_TX_COMPLETE;
> diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
> index 4c532b7..253878c 100644
> --- a/hw/usb/dev-network.c
> +++ b/hw/usb/dev-network.c
> @@ -1196,7 +1196,7 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
>
> if (!is_rndis(s)) {
> if (p->iov.size < 64) {
> - qemu_send_packet(qemu_get_queue(s->nic), s->out_buf, s->out_ptr);
> + qemu_send_packet(qemu_get_queue(s->nic), s->out_buf, s->out_ptr, 0);
> s->out_ptr = 0;
> }
> return;
> @@ -1209,7 +1209,8 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p)
> uint32_t offs = 8 + le32_to_cpu(msg->DataOffset);
> uint32_t size = le32_to_cpu(msg->DataLength);
> if (offs + size <= len)
> - qemu_send_packet(qemu_get_queue(s->nic), s->out_buf + offs, size);
> + qemu_send_packet(qemu_get_queue(s->nic), s->out_buf + offs,
> + size, 0);
> }
> s->out_ptr -= len;
> memmove(s->out_buf, &s->out_buf[len], s->out_ptr);
> @@ -1259,7 +1260,8 @@ static void usb_net_handle_data(USBDevice *dev, USBPacket *p)
> }
> }
>
> -static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> USBNetState *s = qemu_get_nic_opaque(nc);
> uint8_t *in_buf = s->in_buf;
> diff --git a/include/net/net.h b/include/net/net.h
> index 11e1468..d3f0ad6 100644
> --- a/include/net/net.h
> +++ b/include/net/net.h
> @@ -44,8 +44,10 @@ typedef struct NICConf {
>
> typedef void (NetPoll)(NetClientState *, bool enable);
> typedef int (NetCanReceive)(NetClientState *);
> -typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t);
> -typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int);
> +typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t,
> + unsigned);
> +typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int,
> + unsigned);
> typedef void (NetCleanup) (NetClientState *);
> typedef void (LinkStatusChanged)(NetClientState *);
> typedef void (NetClientDestructor)(NetClientState *);
> @@ -110,13 +112,17 @@ typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque);
> void qemu_foreach_nic(qemu_nic_foreach func, void *opaque);
> int qemu_can_send_packet(NetClientState *nc);
> ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
> - int iovcnt);
> + int iovcnt, unsigned flags);
> ssize_t qemu_sendv_packet_async(NetClientState *nc, const struct iovec *iov,
> - int iovcnt, NetPacketSent *sent_cb);
> -void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size);
> -ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size);
> + int iovcnt, NetPacketSent *sent_cb,
> + unsigned flags);
> +void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size,
> + unsigned flags);
> +ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size,
> + unsigned flags);
> ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
> - int size, NetPacketSent *sent_cb);
> + int size, NetPacketSent *sent_cb,
> + unsigned flags);
> void qemu_purge_queued_packets(NetClientState *nc);
> void qemu_flush_queued_packets(NetClientState *nc);
> void qemu_format_nic_info_str(NetClientState *nc, uint8_t macaddr[6]);
> diff --git a/include/net/queue.h b/include/net/queue.h
> index fc02b33..1d136a6 100644
> --- a/include/net/queue.h
> +++ b/include/net/queue.h
> @@ -33,6 +33,7 @@ typedef void (NetPacketSent) (NetClientState *sender, ssize_t ret);
>
> #define QEMU_NET_PACKET_FLAG_NONE 0
> #define QEMU_NET_PACKET_FLAG_RAW (1<<0)
> +#define QEMU_NET_PACKET_FLAG_MORE (2<<0)
>
> NetQueue *qemu_new_net_queue(void *opaque);
>
> diff --git a/net/dump.c b/net/dump.c
> index 9d3a09e..f718d5c 100644
> --- a/net/dump.c
> +++ b/net/dump.c
> @@ -57,7 +57,8 @@ struct pcap_sf_pkthdr {
> uint32_t len;
> };
>
> -static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t dump_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> DumpState *s = DO_UPCAST(DumpState, nc, nc);
> struct pcap_sf_pkthdr hdr;
> diff --git a/net/hub.c b/net/hub.c
> index 33a99c9..7adca5d 100644
> --- a/net/hub.c
> +++ b/net/hub.c
> @@ -52,7 +52,7 @@ static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port,
> continue;
> }
>
> - qemu_send_packet(&port->nc, buf, len);
> + qemu_send_packet(&port->nc, buf, len, 0);
> }
> return len;
> }
> @@ -68,7 +68,7 @@ static ssize_t net_hub_receive_iov(NetHub *hub, NetHubPort *source_port,
> continue;
> }
>
> - qemu_sendv_packet(&port->nc, iov, iovcnt);
> + qemu_sendv_packet(&port->nc, iov, iovcnt, 0);
> }
> return len;
> }
> @@ -107,7 +107,8 @@ static int net_hub_port_can_receive(NetClientState *nc)
> }
>
> static ssize_t net_hub_port_receive(NetClientState *nc,
> - const uint8_t *buf, size_t len)
> + const uint8_t *buf, size_t len,
> + unsigned flags)
> {
> NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
>
> @@ -115,7 +116,8 @@ static ssize_t net_hub_port_receive(NetClientState *nc,
> }
>
> static ssize_t net_hub_port_receive_iov(NetClientState *nc,
> - const struct iovec *iov, int iovcnt)
> + const struct iovec *iov, int iovcnt,
> + unsigned flags)
> {
> NetHubPort *port = DO_UPCAST(NetHubPort, nc, nc);
>
> diff --git a/net/net.c b/net/net.c
> index 9db88cc..65cf5f1 100644
> --- a/net/net.c
> +++ b/net/net.c
> @@ -414,9 +414,10 @@ ssize_t qemu_deliver_packet(NetClientState *sender,
> }
>
> if (flags & QEMU_NET_PACKET_FLAG_RAW && nc->info->receive_raw) {
> - ret = nc->info->receive_raw(nc, data, size);
> + ret = nc->info->receive_raw(nc, data, size,
> + flags & ~QEMU_NET_PACKET_FLAG_RAW);
> } else {
> - ret = nc->info->receive(nc, data, size);
> + ret = nc->info->receive(nc, data, size, flags);
> }
>
> if (ret == 0) {
> @@ -475,32 +476,36 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
>
> ssize_t qemu_send_packet_async(NetClientState *sender,
> const uint8_t *buf, int size,
> - NetPacketSent *sent_cb)
> + NetPacketSent *sent_cb, unsigned flags)
> {
> - return qemu_send_packet_async_with_flags(sender, QEMU_NET_PACKET_FLAG_NONE,
> + return qemu_send_packet_async_with_flags(sender,
> + flags | QEMU_NET_PACKET_FLAG_NONE,
> buf, size, sent_cb);
> }
>
> -void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size)
> +void qemu_send_packet(NetClientState *nc, const uint8_t *buf, int size,
> + unsigned flags)
> {
> - qemu_send_packet_async(nc, buf, size, NULL);
> + qemu_send_packet_async(nc, buf, size, NULL, flags);
> }
>
> -ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size)
> +ssize_t qemu_send_packet_raw(NetClientState *nc, const uint8_t *buf, int size,
> + unsigned flags)
> {
> - return qemu_send_packet_async_with_flags(nc, QEMU_NET_PACKET_FLAG_RAW,
> + return qemu_send_packet_async_with_flags(nc,
> + QEMU_NET_PACKET_FLAG_RAW | flags,
> buf, size, NULL);
> }
>
> static ssize_t nc_sendv_compat(NetClientState *nc, const struct iovec *iov,
> - int iovcnt)
> + int iovcnt, unsigned flags)
> {
> uint8_t buffer[NET_BUFSIZE];
> size_t offset;
>
> offset = iov_to_buf(iov, iovcnt, 0, buffer, sizeof(buffer));
>
> - return nc->info->receive(nc, buffer, offset);
> + return nc->info->receive(nc, buffer, offset, flags);
> }
>
> ssize_t qemu_deliver_packet_iov(NetClientState *sender,
> @@ -521,9 +526,9 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
> }
>
> if (nc->info->receive_iov) {
> - ret = nc->info->receive_iov(nc, iov, iovcnt);
> + ret = nc->info->receive_iov(nc, iov, iovcnt, flags);
> } else {
> - ret = nc_sendv_compat(nc, iov, iovcnt);
> + ret = nc_sendv_compat(nc, iov, iovcnt, flags);
> }
>
> if (ret == 0) {
> @@ -535,7 +540,8 @@ ssize_t qemu_deliver_packet_iov(NetClientState *sender,
>
> ssize_t qemu_sendv_packet_async(NetClientState *sender,
> const struct iovec *iov, int iovcnt,
> - NetPacketSent *sent_cb)
> + NetPacketSent *sent_cb,
> + unsigned flags)
> {
> NetQueue *queue;
>
> @@ -546,14 +552,15 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
> queue = sender->peer->incoming_queue;
>
> return qemu_net_queue_send_iov(queue, sender,
> - QEMU_NET_PACKET_FLAG_NONE,
> + flags | QEMU_NET_PACKET_FLAG_NONE,
> iov, iovcnt, sent_cb);
> }
>
> ssize_t
> -qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt)
> +qemu_sendv_packet(NetClientState *nc, const struct iovec *iov, int iovcnt,
> + unsigned flags)
> {
> - return qemu_sendv_packet_async(nc, iov, iovcnt, NULL);
> + return qemu_sendv_packet_async(nc, iov, iovcnt, NULL, flags);
> }
>
> NetClientState *qemu_find_netdev(const char *id)
> diff --git a/net/netmap.c b/net/netmap.c
> index 0ccc497..0b982a0 100644
> --- a/net/netmap.c
> +++ b/net/netmap.c
> @@ -218,7 +218,8 @@ static void netmap_writable(void *opaque)
> }
>
> static ssize_t netmap_receive(NetClientState *nc,
> - const uint8_t *buf, size_t size)
> + const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
> struct netmap_ring *ring = s->me.tx;
> @@ -252,13 +253,17 @@ static ssize_t netmap_receive(NetClientState *nc,
> pkt_copy(buf, dst, size);
> ring->cur = NETMAP_RING_NEXT(ring, i);
> ring->avail--;
> - ioctl(s->me.fd, NIOCTXSYNC, NULL);
> +
> + if (!(flags & QEMU_NET_PACKET_FLAG_MORE)) {
> + ioctl(s->me.fd, NIOCTXSYNC, NULL);
> + }
>
> return size;
> }
>
> static ssize_t netmap_receive_iov(NetClientState *nc,
> - const struct iovec *iov, int iovcnt)
> + const struct iovec *iov, int iovcnt,
> + unsigned flags)
> {
> NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
> struct netmap_ring *ring = s->me.tx;
> @@ -322,7 +327,9 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
> ring->cur = i;
> ring->avail = avail;
>
> - ioctl(s->me.fd, NIOCTXSYNC, NULL);
> + if (!(flags & QEMU_NET_PACKET_FLAG_MORE)) {
> + ioctl(s->me.fd, NIOCTXSYNC, NULL);
> + }
>
> return iov_size(iov, iovcnt);
> }
> @@ -368,7 +375,7 @@ static void netmap_send(void *opaque)
> }
>
> iovsize = qemu_sendv_packet_async(&s->nc, s->iov, iovcnt,
> - netmap_send_completed);
> + netmap_send_completed, 0);
>
> if (iovsize == 0) {
> /* The peer does not receive anymore. Packet is queued, stop
> diff --git a/net/slirp.c b/net/slirp.c
> index 124e953..a801638 100644
> --- a/net/slirp.c
> +++ b/net/slirp.c
> @@ -103,10 +103,11 @@ void slirp_output(void *opaque, const uint8_t *pkt, int pkt_len)
> {
> SlirpState *s = opaque;
>
> - qemu_send_packet(&s->nc, pkt, pkt_len);
> + qemu_send_packet(&s->nc, pkt, pkt_len, 0);
> }
>
> -static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t net_slirp_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> SlirpState *s = DO_UPCAST(SlirpState, nc, nc);
>
> diff --git a/net/socket.c b/net/socket.c
> index fb21e20..acc715a 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -89,7 +89,8 @@ static void net_socket_writable(void *opaque)
> qemu_flush_queued_packets(&s->nc);
> }
>
> -static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
> uint32_t len = htonl(size);
> @@ -124,7 +125,8 @@ static ssize_t net_socket_receive(NetClientState *nc, const uint8_t *buf, size_t
> return size;
> }
>
> -static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t net_socket_receive_dgram(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> NetSocketState *s = DO_UPCAST(NetSocketState, nc, nc);
> ssize_t ret;
> @@ -211,7 +213,7 @@ static void net_socket_send(void *opaque)
> buf += l;
> size -= l;
> if (s->index >= s->packet_len) {
> - qemu_send_packet(&s->nc, s->buf, s->packet_len);
> + qemu_send_packet(&s->nc, s->buf, s->packet_len, 0);
> s->index = 0;
> s->state = 0;
> }
> @@ -234,7 +236,7 @@ static void net_socket_send_dgram(void *opaque)
> net_socket_write_poll(s, false);
> return;
> }
> - qemu_send_packet(&s->nc, s->buf, size);
> + qemu_send_packet(&s->nc, s->buf, size, 0);
> }
>
> static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr *localaddr)
> diff --git a/net/tap-win32.c b/net/tap-win32.c
> index 91e9e84..2d86122 100644
> --- a/net/tap-win32.c
> +++ b/net/tap-win32.c
> @@ -664,7 +664,7 @@ static void tap_win32_send(void *opaque)
>
> size = tap_win32_read(s->handle, &buf, max_size);
> if (size > 0) {
> - qemu_send_packet(&s->nc, buf, size);
> + qemu_send_packet(&s->nc, buf, size, 0);
> tap_win32_free_buffer(s->handle, buf);
> }
> }
> diff --git a/net/tap.c b/net/tap.c
> index 39c1cda..6d7a02e 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -112,7 +112,7 @@ static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt
> }
>
> static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
> - int iovcnt)
> + int iovcnt, unsigned flags)
> {
> TAPState *s = DO_UPCAST(TAPState, nc, nc);
> const struct iovec *iovp = iov;
> @@ -130,7 +130,8 @@ static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
> return tap_write_packet(s, iovp, iovcnt);
> }
>
> -static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf,
> + size_t size, unsigned flags)
> {
> TAPState *s = DO_UPCAST(TAPState, nc, nc);
> struct iovec iov[2];
> @@ -150,13 +151,14 @@ static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t si
> return tap_write_packet(s, iov, iovcnt);
> }
>
> -static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> TAPState *s = DO_UPCAST(TAPState, nc, nc);
> struct iovec iov[1];
>
> if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
> - return tap_receive_raw(nc, buf, size);
> + return tap_receive_raw(nc, buf, size, flags);
> }
>
> iov[0].iov_base = (char *)buf;
> @@ -203,7 +205,7 @@ static void tap_send(void *opaque)
> size -= s->host_vnet_hdr_len;
> }
>
> - size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
> + size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed, 0);
> if (size == 0) {
> tap_read_poll(s, false);
> }
> diff --git a/net/vde.c b/net/vde.c
> index 2a619fb..5629f58 100644
> --- a/net/vde.c
> +++ b/net/vde.c
> @@ -44,11 +44,12 @@ static void vde_to_qemu(void *opaque)
>
> size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0);
> if (size > 0) {
> - qemu_send_packet(&s->nc, buf, size);
> + qemu_send_packet(&s->nc, buf, size, 0);
> }
> }
>
> -static ssize_t vde_receive(NetClientState *nc, const uint8_t *buf, size_t size)
> +static ssize_t vde_receive(NetClientState *nc, const uint8_t *buf, size_t size,
> + unsigned flags)
> {
> VDEState *s = DO_UPCAST(VDEState, nc, nc);
> ssize_t ret;
> diff --git a/savevm.c b/savevm.c
> index 3f912dd..a8d5373 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -84,7 +84,7 @@ static void qemu_announce_self_iter(NICState *nic, void *opaque)
>
> len = announce_self_create(buf, nic->conf->macaddr.a);
>
> - qemu_send_packet_raw(qemu_get_queue(nic), buf, len);
> + qemu_send_packet_raw(qemu_get_queue(nic), buf, len, 0);
> }
>
>
> --
> 1.8.4.2
[Prev in Thread] | Current Thread | [Next in Thread] |