[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [RFC Patch v2 03/10] virtio-net rsc: Chain Lookup, Pack
From: |
Michael S. Tsirkin |
Subject: |
Re: [Qemu-devel] [RFC Patch v2 03/10] virtio-net rsc: Chain Lookup, Packet Caching and Framework of IPv4 |
Date: |
Sun, 31 Jan 2016 20:50:31 +0200 |
On Mon, Feb 01, 2016 at 02:13:22AM +0800, address@hidden wrote:
> From: Wei Xu <address@hidden>
>
> Upon a packet is arriving, a corresponding chain will be selected or created,
> or be bypassed if it's not an IPv4 packets.
>
> The callback in the chain will be invoked to call the real coalescing.
>
> Since the coalescing is based on the TCP connection, so the packets will be
> cached if there is no previous data within the same connection.
>
> The framework of IPv4 is also introduced.
>
> This patch depends on patch 2918cf2 (Detailed IPv4 and General TCP data
> coalescing)
>
> Signed-off-by: Wei Xu <address@hidden>
> ---
> hw/net/virtio-net.c | 173
> +++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 172 insertions(+), 1 deletion(-)
>
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 4e9458e..cfbac6d 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -14,10 +14,12 @@
> #include "qemu/iov.h"
> #include "hw/virtio/virtio.h"
> #include "net/net.h"
> +#include "net/eth.h"
> #include "net/checksum.h"
> #include "net/tap.h"
> #include "qemu/error-report.h"
> #include "qemu/timer.h"
> +#include "qemu/sockets.h"
> #include "hw/virtio/virtio-net.h"
> #include "net/vhost_net.h"
> #include "hw/virtio/virtio-bus.h"
> @@ -37,6 +39,21 @@
> #define endof(container, field) \
> (offsetof(container, field) + sizeof(((container *)0)->field))
>
> +#define VIRTIO_HEADER 12 /* Virtio net header size */
> +#define IP_OFFSET (VIRTIO_HEADER + sizeof(struct eth_header))
> +
> +#define MAX_VIRTIO_IP_PAYLOAD (65535 + IP_OFFSET)
> +
> +/* Global statistics */
> +static uint32_t rsc_chain_no_mem;
> +
> +/* Switcher to enable/disable rsc */
> +static bool virtio_net_rsc_bypass;
> +
> +/* Coalesce callback for ipv4/6 */
> +typedef int32_t (VirtioNetCoalesce) (NetRscChain *chain, NetRscSeg *seg,
> + const uint8_t *buf, size_t size);
> +
Since there are only 2 cases, it's probably better to just
open-code if (v4) -> coalesce4 else if v6 -> coalesce6
> typedef struct VirtIOFeature {
> uint32_t flags;
> size_t end;
> @@ -1019,7 +1036,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_do_receive(NetClientState *nc,
> + const uint8_t *buf, size_t size)
> {
> VirtIONet *n = qemu_get_nic_opaque(nc);
> VirtIONetQueue *q = virtio_net_get_subqueue(nc);
> @@ -1623,6 +1641,159 @@ static void virtio_net_rsc_cleanup(VirtIONet *n)
> }
> }
>
> +static int virtio_net_rsc_cache_buf(NetRscChain *chain, NetClientState *nc,
> + const uint8_t *buf, size_t size)
> +{
> + NetRscSeg *seg;
> +
> + seg = g_malloc(sizeof(NetRscSeg));
> + if (!seg) {
> + return 0;
> + }
> +
> + seg->buf = g_malloc(MAX_VIRTIO_IP_PAYLOAD);
> + if (!seg->buf) {
> + goto out;
> + }
> +
> + memmove(seg->buf, buf, size);
> + seg->size = size;
> + seg->dup_ack_count = 0;
> + seg->is_coalesced = 0;
> + seg->nc = nc;
> +
> + QTAILQ_INSERT_TAIL(&chain->buffers, seg, next);
> + return size;
> +
> +out:
> + g_free(seg);
> + return 0;
> +}
> +
> +
> +static int32_t virtio_net_rsc_try_coalesce4(NetRscChain *chain,
> + NetRscSeg *seg, const uint8_t *buf, size_t size)
> +{
> + /* This real part of this function will be introduced in next patch, just
> + * return a 'final' to feed the compilation. */
> + return RSC_FINAL;
> +}
> +
> +static size_t virtio_net_rsc_callback(NetRscChain *chain, NetClientState *nc,
> + const uint8_t *buf, size_t size, VirtioNetCoalesce *coalesce)
> +{
> + int ret;
> + NetRscSeg *seg, *nseg;
> +
> + if (QTAILQ_EMPTY(&chain->buffers)) {
> + if (!virtio_net_rsc_cache_buf(chain, nc, buf, size)) {
> + return 0;
> + } else {
> + return size;
> + }
> + }
> +
> + QTAILQ_FOREACH_SAFE(seg, &chain->buffers, next, nseg) {
> + ret = coalesce(chain, seg, buf, size);
> + if (RSC_FINAL == ret) {
> + ret = virtio_net_do_receive(seg->nc, seg->buf, seg->size);
> + QTAILQ_REMOVE(&chain->buffers, seg, next);
> + g_free(seg->buf);
> + g_free(seg);
> + if (ret == 0) {
> + /* Send failed */
> + return 0;
> + }
> +
> + /* Send current packet */
> + return virtio_net_do_receive(nc, buf, size);
> + } else if (RSC_NO_MATCH == ret) {
> + continue;
> + } else {
> + /* Coalesced, mark coalesced flag to tell calc cksum for ipv4 */
> + seg->is_coalesced = 1;
> + return size;
> + }
> + }
> +
> + return virtio_net_rsc_cache_buf(chain, nc, buf, size);
> +}
> +
> +static size_t virtio_net_rsc_receive4(void *opq, NetClientState* nc,
> + const uint8_t *buf, size_t size)
> +{
> + NetRscChain *chain;
> +
> + chain = (NetRscChain *)opq;
> + return virtio_net_rsc_callback(chain, nc, buf, size,
> + virtio_net_rsc_try_coalesce4);
> +}
> +
> +static NetRscChain *virtio_net_rsc_lookup_chain(NetClientState *nc,
> + uint16_t proto)
> +{
> + VirtIONet *n;
> + NetRscChain *chain;
> + NICState *nic;
> +
> + /* Only handle IPv4/6 */
> + if (proto != (uint16_t)ETH_P_IP) {
> + return NULL;
> + }
> +
> + nic = (NICState *)nc;
> + n = container_of(&nic, VirtIONet, nic);
> + QTAILQ_FOREACH(chain, &n->rsc_chains, next) {
> + if (chain->proto == proto) {
> + return chain;
> + }
> + }
> +
> + chain = g_malloc(sizeof(*chain));
> + if (!chain) {
> + rsc_chain_no_mem++;
> + return NULL;
> + }
> +
> + chain->proto = proto;
> + chain->do_receive = virtio_net_rsc_receive4;
> +
> + QTAILQ_INIT(&chain->buffers);
> + QTAILQ_INSERT_TAIL(&n->rsc_chains, chain, next);
> + return chain;
> +}
> +
> +static ssize_t virtio_net_rsc_receive(NetClientState *nc,
> + const uint8_t *buf, size_t size)
> +{
> + uint16_t proto;
> + NetRscChain *chain;
> + struct eth_header *eth;
> +
> + if (size < IP_OFFSET) {
> + return virtio_net_do_receive(nc, buf, size);
> + }
> +
> + eth = (struct eth_header *)(buf + VIRTIO_HEADER);
> + proto = htons(eth->h_proto);
> + chain = virtio_net_rsc_lookup_chain(nc, proto);
> + if (!chain) {
> + return virtio_net_do_receive(nc, buf, size);
> + } else {
> + return chain->do_receive(chain, nc, buf, size);
> + }
> +}
> +
> +static ssize_t virtio_net_receive(NetClientState *nc,
> + const uint8_t *buf, size_t size)
> +{
> + if (virtio_net_rsc_bypass) {
> + return virtio_net_do_receive(nc, buf, size);
> + } else {
> + return virtio_net_rsc_receive(nc, buf, size);
> + }
> +}
> +
> static NetClientInfo net_virtio_info = {
> .type = NET_CLIENT_OPTIONS_KIND_NIC,
> .size = sizeof(NICState),
> --
> 2.4.0
- [Qemu-devel] [RFC v2 0/10] Support Receive-Segment-Offload(RSC) for WHQL test of Window guest, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 01/10] virtio-net rsc: Data structure, 'Segment', 'Chain' and 'Status', wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 02/10] virtio-net rsc: Initilize & Cleanup, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 04/10] virtio-net rsc: Detailed IPv4 and General TCP data coalescing, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 03/10] virtio-net rsc: Chain Lookup, Packet Caching and Framework of IPv4, wexu, 2016/01/31
- Re: [Qemu-devel] [RFC Patch v2 03/10] virtio-net rsc: Chain Lookup, Packet Caching and Framework of IPv4,
Michael S. Tsirkin <=
- [Qemu-devel] [RFC Patch v2 05/10] virtio-net rsc: Create timer to drain the packets from the cache pool, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 06/10] virtio-net rsc: IPv4 checksum, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 07/10] virtio-net rsc: Checking TCP flag and drain specific connection packets, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 08/10] virtio-net rsc: Sanity check & More bypass cases check, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 09/10] virtio-net rsc: Add IPv6 support, wexu, 2016/01/31
- [Qemu-devel] [RFC Patch v2 10/10] virtio-net rsc: Add Receive Segment Coalesce statistics, wexu, 2016/01/31
- Re: [Qemu-devel] [RFC v2 0/10] Support Receive-Segment-Offload(RSC) for WHQL test of Window guest, Michael S. Tsirkin, 2016/01/31
- Re: [Qemu-devel] [RFC v2 0/10] Support Receive-Segment-Offload(RSC) for WHQL test of Window guest, Jason Wang, 2016/01/31