Net patches
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTDJtxAAoJEJykq7OBq3PIEBAH/0Fh1TUsHpLGwtVC+HObl4HF 19KJpaXfG3L1x5pV4qbRvsmgXDNjnm8sSAbAvINn5uKJqk371qshvgssaIyLOA/o VD+9lR1mwE9mwiktCfFniddoZmTsMyGxsbE4i1dZAxsGuuiJ3x2zRotpQCLjmWMJ OSIdy1v657tR0EnhjI19g4fNvCpfOwX3tvMt20vgL6/x9AuNjMfFeP6S/KNuxBBC 6vflVNmN0AIc/tIbR5bql5/wcDixJcxobFXHxAmIbaaJTNtFXq0PNpo0kfLi5Zzx s6iVoYVXNMx1xqpegBEVLyIvtcX7SCggO8FT+bhzaOfPVL8NaSXRJMRjH22V+D0= =UA+s -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stefanha/tags/net-pull-request' into staging Net patches # gpg: Signature made Tue 25 Feb 2014 13:32:33 GMT using RSA key ID 81AB73C8 # gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" # gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8 * remotes/stefanha/tags/net-pull-request: virtio-net: use qemu_get_queue() where possible vhost_net: use offload API instead of bypassing it net: remove implicit peer from offload API net: Disable netmap backend when not supported net: add offloading support to netmap backend net: make tap offloading callbacks static net: virtio-net and vmxnet3 use offloading API net: TAP uses NetClientInfo offloading callbacks net: extend NetClientInfo for offloading net: change vnet-hdr TAP prototypes opencores_eth: flush queue whenever can_receive can go from false to true Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						bc3fbad816
					
				
							
								
								
									
										10
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@ -2249,13 +2249,21 @@ EOF
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# netmap headers probe
 | 
			
		||||
# netmap support probe
 | 
			
		||||
# Apart from looking for netmap headers, we make sure that the host API version
 | 
			
		||||
# supports the netmap backend (>=11). The upper bound (15) is meant to simulate
 | 
			
		||||
# a minor/major version number. Minor new features will be marked with values up
 | 
			
		||||
# to 15, and if something happens that requires a change to the backend we will
 | 
			
		||||
# move above 15, submit the backend fixes and modify this two bounds.
 | 
			
		||||
if test "$netmap" != "no" ; then
 | 
			
		||||
  cat > $TMPC << EOF
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <net/netmap.h>
 | 
			
		||||
#include <net/netmap_user.h>
 | 
			
		||||
#if (NETMAP_API < 11) || (NETMAP_API > 15)
 | 
			
		||||
#error
 | 
			
		||||
#endif
 | 
			
		||||
int main(void) { return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
  if compile_prog "" "" ; then
 | 
			
		||||
 | 
			
		||||
@ -106,7 +106,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    net->nc = backend;
 | 
			
		||||
    net->dev.backend_features = tap_has_vnet_hdr(backend) ? 0 :
 | 
			
		||||
    net->dev.backend_features = qemu_has_vnet_hdr(backend) ? 0 :
 | 
			
		||||
        (1 << VHOST_NET_F_VIRTIO_NET_HDR);
 | 
			
		||||
    net->backend = r;
 | 
			
		||||
 | 
			
		||||
@ -117,7 +117,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd,
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        goto fail;
 | 
			
		||||
    }
 | 
			
		||||
    if (!tap_has_vnet_hdr_len(backend,
 | 
			
		||||
    if (!qemu_has_vnet_hdr_len(backend,
 | 
			
		||||
                               sizeof(struct virtio_net_hdr_mrg_rxbuf))) {
 | 
			
		||||
        net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -325,11 +325,7 @@ static void peer_test_vnet_hdr(VirtIONet *n)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    n->has_vnet_hdr = tap_has_vnet_hdr(nc->peer);
 | 
			
		||||
    n->has_vnet_hdr = qemu_has_vnet_hdr(nc->peer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int peer_has_vnet_hdr(VirtIONet *n)
 | 
			
		||||
@ -342,7 +338,7 @@ static int peer_has_ufo(VirtIONet *n)
 | 
			
		||||
    if (!peer_has_vnet_hdr(n))
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    n->has_ufo = tap_has_ufo(qemu_get_queue(n->nic)->peer);
 | 
			
		||||
    n->has_ufo = qemu_has_ufo(qemu_get_queue(n->nic)->peer);
 | 
			
		||||
 | 
			
		||||
    return n->has_ufo;
 | 
			
		||||
}
 | 
			
		||||
@ -361,8 +357,8 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs)
 | 
			
		||||
        nc = qemu_get_subqueue(n->nic, i);
 | 
			
		||||
 | 
			
		||||
        if (peer_has_vnet_hdr(n) &&
 | 
			
		||||
            tap_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
 | 
			
		||||
            tap_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
 | 
			
		||||
            qemu_has_vnet_hdr_len(nc->peer, n->guest_hdr_len)) {
 | 
			
		||||
            qemu_set_vnet_hdr_len(nc->peer, n->guest_hdr_len);
 | 
			
		||||
            n->host_hdr_len = n->guest_hdr_len;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -463,7 +459,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
 | 
			
		||||
 | 
			
		||||
static void virtio_net_apply_guest_offloads(VirtIONet *n)
 | 
			
		||||
{
 | 
			
		||||
    tap_set_offload(qemu_get_subqueue(n->nic, 0)->peer,
 | 
			
		||||
    qemu_set_offload(qemu_get_queue(n->nic)->peer,
 | 
			
		||||
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_CSUM)),
 | 
			
		||||
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO4)),
 | 
			
		||||
            !!(n->curr_guest_offloads & (1ULL << VIRTIO_NET_F_GUEST_TSO6)),
 | 
			
		||||
@ -1544,7 +1540,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
 | 
			
		||||
    peer_test_vnet_hdr(n);
 | 
			
		||||
    if (peer_has_vnet_hdr(n)) {
 | 
			
		||||
        for (i = 0; i < n->max_queues; i++) {
 | 
			
		||||
            tap_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
 | 
			
		||||
            qemu_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true);
 | 
			
		||||
        }
 | 
			
		||||
        n->host_hdr_len = sizeof(struct virtio_net_hdr);
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
@ -1290,7 +1290,7 @@ static void vmxnet3_update_features(VMXNET3State *s)
 | 
			
		||||
              s->lro_supported, rxcso_supported,
 | 
			
		||||
              s->rx_vlan_stripping);
 | 
			
		||||
    if (s->peer_has_vhdr) {
 | 
			
		||||
        tap_set_offload(qemu_get_queue(s->nic)->peer,
 | 
			
		||||
        qemu_set_offload(qemu_get_queue(s->nic)->peer,
 | 
			
		||||
                         rxcso_supported,
 | 
			
		||||
                         s->lro_supported,
 | 
			
		||||
                         s->lro_supported,
 | 
			
		||||
@ -1883,11 +1883,9 @@ static NetClientInfo net_vmxnet3_info = {
 | 
			
		||||
 | 
			
		||||
static bool vmxnet3_peer_has_vnet_hdr(VMXNET3State *s)
 | 
			
		||||
{
 | 
			
		||||
    NetClientState *peer = qemu_get_queue(s->nic)->peer;
 | 
			
		||||
    NetClientState *nc = qemu_get_queue(s->nic);
 | 
			
		||||
 | 
			
		||||
    if ((NULL != peer)                              &&
 | 
			
		||||
        (peer->info->type == NET_CLIENT_OPTIONS_KIND_TAP)   &&
 | 
			
		||||
        tap_has_vnet_hdr(peer)) {
 | 
			
		||||
    if (qemu_has_vnet_hdr(nc->peer)) {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1935,10 +1933,10 @@ static void vmxnet3_net_init(VMXNET3State *s)
 | 
			
		||||
    s->lro_supported = false;
 | 
			
		||||
 | 
			
		||||
    if (s->peer_has_vhdr) {
 | 
			
		||||
        tap_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
 | 
			
		||||
        qemu_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer,
 | 
			
		||||
            sizeof(struct virtio_net_hdr));
 | 
			
		||||
 | 
			
		||||
        tap_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
 | 
			
		||||
        qemu_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 | 
			
		||||
 | 
			
		||||
@ -50,6 +50,12 @@ typedef void (NetCleanup) (NetClientState *);
 | 
			
		||||
typedef void (LinkStatusChanged)(NetClientState *);
 | 
			
		||||
typedef void (NetClientDestructor)(NetClientState *);
 | 
			
		||||
typedef RxFilterInfo *(QueryRxFilter)(NetClientState *);
 | 
			
		||||
typedef bool (HasUfo)(NetClientState *);
 | 
			
		||||
typedef bool (HasVnetHdr)(NetClientState *);
 | 
			
		||||
typedef bool (HasVnetHdrLen)(NetClientState *, int);
 | 
			
		||||
typedef void (UsingVnetHdr)(NetClientState *, bool);
 | 
			
		||||
typedef void (SetOffload)(NetClientState *, int, int, int, int, int);
 | 
			
		||||
typedef void (SetVnetHdrLen)(NetClientState *, int);
 | 
			
		||||
 | 
			
		||||
typedef struct NetClientInfo {
 | 
			
		||||
    NetClientOptionsKind type;
 | 
			
		||||
@ -62,6 +68,12 @@ typedef struct NetClientInfo {
 | 
			
		||||
    LinkStatusChanged *link_status_changed;
 | 
			
		||||
    QueryRxFilter *query_rx_filter;
 | 
			
		||||
    NetPoll *poll;
 | 
			
		||||
    HasUfo *has_ufo;
 | 
			
		||||
    HasVnetHdr *has_vnet_hdr;
 | 
			
		||||
    HasVnetHdrLen *has_vnet_hdr_len;
 | 
			
		||||
    UsingVnetHdr *using_vnet_hdr;
 | 
			
		||||
    SetOffload *set_offload;
 | 
			
		||||
    SetVnetHdrLen *set_vnet_hdr_len;
 | 
			
		||||
} NetClientInfo;
 | 
			
		||||
 | 
			
		||||
struct NetClientState {
 | 
			
		||||
@ -120,6 +132,13 @@ ssize_t qemu_send_packet_async(NetClientState *nc, const uint8_t *buf,
 | 
			
		||||
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]);
 | 
			
		||||
bool qemu_has_ufo(NetClientState *nc);
 | 
			
		||||
bool qemu_has_vnet_hdr(NetClientState *nc);
 | 
			
		||||
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len);
 | 
			
		||||
void qemu_using_vnet_hdr(NetClientState *nc, bool enable);
 | 
			
		||||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
 | 
			
		||||
                      int ecn, int ufo);
 | 
			
		||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len);
 | 
			
		||||
void qemu_macaddr_default_if_unset(MACAddr *macaddr);
 | 
			
		||||
int qemu_show_nic_models(const char *arg, const char *const *models);
 | 
			
		||||
void qemu_check_nic_model(NICInfo *nd, const char *model);
 | 
			
		||||
 | 
			
		||||
@ -29,12 +29,6 @@
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qapi-types.h"
 | 
			
		||||
 | 
			
		||||
bool tap_has_ufo(NetClientState *nc);
 | 
			
		||||
int tap_has_vnet_hdr(NetClientState *nc);
 | 
			
		||||
int tap_has_vnet_hdr_len(NetClientState *nc, int len);
 | 
			
		||||
void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr);
 | 
			
		||||
void tap_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo);
 | 
			
		||||
void tap_set_vnet_hdr_len(NetClientState *nc, int len);
 | 
			
		||||
int tap_enable(NetClientState *nc);
 | 
			
		||||
int tap_disable(NetClientState *nc);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										55
									
								
								net/net.c
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								net/net.c
									
									
									
									
									
								
							@ -378,6 +378,61 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool qemu_has_ufo(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->has_ufo) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nc->info->has_ufo(nc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool qemu_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->has_vnet_hdr) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nc->info->has_vnet_hdr(nc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool qemu_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->has_vnet_hdr_len) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return nc->info->has_vnet_hdr_len(nc, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qemu_using_vnet_hdr(NetClientState *nc, bool enable)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->using_vnet_hdr) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nc->info->using_vnet_hdr(nc, enable);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
 | 
			
		||||
                          int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->set_offload) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qemu_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    if (!nc || !nc->info->set_vnet_hdr_len) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    nc->info->set_vnet_hdr_len(nc, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_can_send_packet(NetClientState *sender)
 | 
			
		||||
{
 | 
			
		||||
    if (!sender->peer) {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								net/netmap.c
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								net/netmap.c
									
									
									
									
									
								
							@ -27,10 +27,13 @@
 | 
			
		||||
#include <net/if.h>
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#define NETMAP_WITH_LIBS
 | 
			
		||||
#include <net/netmap.h>
 | 
			
		||||
#include <net/netmap_user.h>
 | 
			
		||||
 | 
			
		||||
#include "net/net.h"
 | 
			
		||||
#include "net/tap.h"
 | 
			
		||||
#include "clients.h"
 | 
			
		||||
#include "sysemu/sysemu.h"
 | 
			
		||||
#include "qemu/error-report.h"
 | 
			
		||||
@ -54,33 +57,9 @@ typedef struct NetmapState {
 | 
			
		||||
    bool                read_poll;
 | 
			
		||||
    bool                write_poll;
 | 
			
		||||
    struct iovec        iov[IOV_MAX];
 | 
			
		||||
    int                 vnet_hdr_len;  /* Current virtio-net header length. */
 | 
			
		||||
} NetmapState;
 | 
			
		||||
 | 
			
		||||
#define D(format, ...)                                          \
 | 
			
		||||
    do {                                                        \
 | 
			
		||||
        struct timeval __xxts;                                  \
 | 
			
		||||
        gettimeofday(&__xxts, NULL);                            \
 | 
			
		||||
        printf("%03d.%06d %s [%d] " format "\n",                \
 | 
			
		||||
                (int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
 | 
			
		||||
                __func__, __LINE__, ##__VA_ARGS__);         \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
/* Rate limited version of "D", lps indicates how many per second */
 | 
			
		||||
#define RD(lps, format, ...)                                    \
 | 
			
		||||
    do {                                                        \
 | 
			
		||||
        static int t0, __cnt;                                   \
 | 
			
		||||
        struct timeval __xxts;                                  \
 | 
			
		||||
        gettimeofday(&__xxts, NULL);                            \
 | 
			
		||||
        if (t0 != __xxts.tv_sec) {                              \
 | 
			
		||||
            t0 = __xxts.tv_sec;                                 \
 | 
			
		||||
            __cnt = 0;                                          \
 | 
			
		||||
        }                                                       \
 | 
			
		||||
        if (__cnt++ < lps) {                                    \
 | 
			
		||||
            D(format, ##__VA_ARGS__);                           \
 | 
			
		||||
        }                                                       \
 | 
			
		||||
    } while (0)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef __FreeBSD__
 | 
			
		||||
#define pkt_copy bcopy
 | 
			
		||||
#else
 | 
			
		||||
@ -237,7 +216,7 @@ static ssize_t netmap_receive(NetClientState *nc,
 | 
			
		||||
        return size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (ring->avail == 0) {
 | 
			
		||||
    if (nm_ring_empty(ring)) {
 | 
			
		||||
        /* No available slots in the netmap TX ring. */
 | 
			
		||||
        netmap_write_poll(s, true);
 | 
			
		||||
        return 0;
 | 
			
		||||
@ -250,8 +229,7 @@ static ssize_t netmap_receive(NetClientState *nc,
 | 
			
		||||
    ring->slot[i].len = size;
 | 
			
		||||
    ring->slot[i].flags = 0;
 | 
			
		||||
    pkt_copy(buf, dst, size);
 | 
			
		||||
    ring->cur = NETMAP_RING_NEXT(ring, i);
 | 
			
		||||
    ring->avail--;
 | 
			
		||||
    ring->cur = ring->head = nm_ring_next(ring, i);
 | 
			
		||||
    ioctl(s->me.fd, NIOCTXSYNC, NULL);
 | 
			
		||||
 | 
			
		||||
    return size;
 | 
			
		||||
@ -267,17 +245,15 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
 | 
			
		||||
    uint8_t *dst;
 | 
			
		||||
    int j;
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    uint32_t avail;
 | 
			
		||||
 | 
			
		||||
    if (unlikely(!ring)) {
 | 
			
		||||
        /* Drop the packet. */
 | 
			
		||||
        return iov_size(iov, iovcnt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    i = ring->cur;
 | 
			
		||||
    avail = ring->avail;
 | 
			
		||||
    last = i = ring->cur;
 | 
			
		||||
 | 
			
		||||
    if (avail < iovcnt) {
 | 
			
		||||
    if (nm_ring_space(ring) < iovcnt) {
 | 
			
		||||
        /* Not enough netmap slots. */
 | 
			
		||||
        netmap_write_poll(s, true);
 | 
			
		||||
        return 0;
 | 
			
		||||
@ -293,7 +269,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
 | 
			
		||||
        while (iov_frag_size) {
 | 
			
		||||
            nm_frag_size = MIN(iov_frag_size, ring->nr_buf_size);
 | 
			
		||||
 | 
			
		||||
            if (unlikely(avail == 0)) {
 | 
			
		||||
            if (unlikely(nm_ring_empty(ring))) {
 | 
			
		||||
                /* We run out of netmap slots while splitting the
 | 
			
		||||
                   iovec fragments. */
 | 
			
		||||
                netmap_write_poll(s, true);
 | 
			
		||||
@ -308,8 +284,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
 | 
			
		||||
            pkt_copy(iov[j].iov_base + offset, dst, nm_frag_size);
 | 
			
		||||
 | 
			
		||||
            last = i;
 | 
			
		||||
            i = NETMAP_RING_NEXT(ring, i);
 | 
			
		||||
            avail--;
 | 
			
		||||
            i = nm_ring_next(ring, i);
 | 
			
		||||
 | 
			
		||||
            offset += nm_frag_size;
 | 
			
		||||
            iov_frag_size -= nm_frag_size;
 | 
			
		||||
@ -318,9 +293,8 @@ static ssize_t netmap_receive_iov(NetClientState *nc,
 | 
			
		||||
    /* The last slot must not have NS_MOREFRAG set. */
 | 
			
		||||
    ring->slot[last].flags &= ~NS_MOREFRAG;
 | 
			
		||||
 | 
			
		||||
    /* Now update ring->cur and ring->avail. */
 | 
			
		||||
    ring->cur = i;
 | 
			
		||||
    ring->avail = avail;
 | 
			
		||||
    /* Now update ring->cur and ring->head. */
 | 
			
		||||
    ring->cur = ring->head = i;
 | 
			
		||||
 | 
			
		||||
    ioctl(s->me.fd, NIOCTXSYNC, NULL);
 | 
			
		||||
 | 
			
		||||
@ -343,7 +317,7 @@ static void netmap_send(void *opaque)
 | 
			
		||||
 | 
			
		||||
    /* Keep sending while there are available packets into the netmap
 | 
			
		||||
       RX ring and the forwarding path towards the peer is open. */
 | 
			
		||||
    while (ring->avail > 0 && qemu_can_send_packet(&s->nc)) {
 | 
			
		||||
    while (!nm_ring_empty(ring) && qemu_can_send_packet(&s->nc)) {
 | 
			
		||||
        uint32_t i;
 | 
			
		||||
        uint32_t idx;
 | 
			
		||||
        bool morefrag;
 | 
			
		||||
@ -358,11 +332,10 @@ static void netmap_send(void *opaque)
 | 
			
		||||
            s->iov[iovcnt].iov_len = ring->slot[i].len;
 | 
			
		||||
            iovcnt++;
 | 
			
		||||
 | 
			
		||||
            ring->cur = NETMAP_RING_NEXT(ring, i);
 | 
			
		||||
            ring->avail--;
 | 
			
		||||
        } while (ring->avail && morefrag);
 | 
			
		||||
            ring->cur = ring->head = nm_ring_next(ring, i);
 | 
			
		||||
        } while (!nm_ring_empty(ring) && morefrag);
 | 
			
		||||
 | 
			
		||||
        if (unlikely(!ring->avail && morefrag)) {
 | 
			
		||||
        if (unlikely(nm_ring_empty(ring) && morefrag)) {
 | 
			
		||||
            RD(5, "[netmap_send] ran out of slots, with a pending"
 | 
			
		||||
                   "incomplete packet\n");
 | 
			
		||||
        }
 | 
			
		||||
@ -394,6 +367,63 @@ static void netmap_cleanup(NetClientState *nc)
 | 
			
		||||
    s->me.fd = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Offloading manipulation support callbacks. */
 | 
			
		||||
static bool netmap_has_ufo(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool netmap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool netmap_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    return len == 0 || len == sizeof(struct virtio_net_hdr) ||
 | 
			
		||||
                len == sizeof(struct virtio_net_hdr_mrg_rxbuf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void netmap_using_vnet_hdr(NetClientState *nc, bool enable)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void netmap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
 | 
			
		||||
    int err;
 | 
			
		||||
    struct nmreq req;
 | 
			
		||||
 | 
			
		||||
    /* Issue a NETMAP_BDG_VNET_HDR command to change the virtio-net header
 | 
			
		||||
     * length for the netmap adapter associated to 'me->ifname'.
 | 
			
		||||
     */
 | 
			
		||||
    memset(&req, 0, sizeof(req));
 | 
			
		||||
    pstrcpy(req.nr_name, sizeof(req.nr_name), s->me.ifname);
 | 
			
		||||
    req.nr_version = NETMAP_API;
 | 
			
		||||
    req.nr_cmd = NETMAP_BDG_VNET_HDR;
 | 
			
		||||
    req.nr_arg1 = len;
 | 
			
		||||
    err = ioctl(s->me.fd, NIOCREGIF, &req);
 | 
			
		||||
    if (err) {
 | 
			
		||||
        error_report("Unable to execute NETMAP_BDG_VNET_HDR on %s: %s",
 | 
			
		||||
                     s->me.ifname, strerror(errno));
 | 
			
		||||
    } else {
 | 
			
		||||
        /* Keep track of the current length. */
 | 
			
		||||
        s->vnet_hdr_len = len;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void netmap_set_offload(NetClientState *nc, int csum, int tso4, int tso6,
 | 
			
		||||
                               int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
    NetmapState *s = DO_UPCAST(NetmapState, nc, nc);
 | 
			
		||||
 | 
			
		||||
    /* Setting a virtio-net header length greater than zero automatically
 | 
			
		||||
     * enables the offloadings.
 | 
			
		||||
     */
 | 
			
		||||
    if (!s->vnet_hdr_len) {
 | 
			
		||||
        netmap_set_vnet_hdr_len(nc, sizeof(struct virtio_net_hdr));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* NetClientInfo methods */
 | 
			
		||||
static NetClientInfo net_netmap_info = {
 | 
			
		||||
@ -403,6 +433,12 @@ static NetClientInfo net_netmap_info = {
 | 
			
		||||
    .receive_iov = netmap_receive_iov,
 | 
			
		||||
    .poll = netmap_poll,
 | 
			
		||||
    .cleanup = netmap_cleanup,
 | 
			
		||||
    .has_ufo = netmap_has_ufo,
 | 
			
		||||
    .has_vnet_hdr = netmap_has_vnet_hdr,
 | 
			
		||||
    .has_vnet_hdr_len = netmap_has_vnet_hdr_len,
 | 
			
		||||
    .using_vnet_hdr = netmap_using_vnet_hdr,
 | 
			
		||||
    .set_offload = netmap_set_offload,
 | 
			
		||||
    .set_vnet_hdr_len = netmap_set_vnet_hdr_len,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* The exported init function
 | 
			
		||||
@ -428,6 +464,7 @@ int net_init_netmap(const NetClientOptions *opts,
 | 
			
		||||
    nc = qemu_new_net_client(&net_netmap_info, peer, "netmap", name);
 | 
			
		||||
    s = DO_UPCAST(NetmapState, nc, nc);
 | 
			
		||||
    s->me = me;
 | 
			
		||||
    s->vnet_hdr_len = 0;
 | 
			
		||||
    netmap_read_poll(s, true); /* Initially only poll for reads. */
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
@ -669,11 +669,60 @@ static void tap_win32_send(void *opaque)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool tap_has_ufo(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool tap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_probe_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tap_set_offload(NetClientState *nc, int csum, int tso4,
 | 
			
		||||
                     int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct vhost_net *tap_get_vhost_net(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static NetClientInfo net_tap_win32_info = {
 | 
			
		||||
    .type = NET_CLIENT_OPTIONS_KIND_TAP,
 | 
			
		||||
    .size = sizeof(TAPState),
 | 
			
		||||
    .receive = tap_receive,
 | 
			
		||||
    .cleanup = tap_cleanup,
 | 
			
		||||
    .has_ufo = tap_has_ufo,
 | 
			
		||||
    .has_vnet_hdr = tap_has_vnet_hdr,
 | 
			
		||||
    .has_vnet_hdr_len = tap_has_vnet_hdr_len,
 | 
			
		||||
    .using_vnet_hdr = tap_using_vnet_hdr,
 | 
			
		||||
    .set_offload = tap_set_offload,
 | 
			
		||||
    .set_vnet_hdr_len = tap_set_vnet_hdr_len,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int tap_win32_init(NetClientState *peer, const char *model,
 | 
			
		||||
@ -722,49 +771,6 @@ int net_init_tap(const NetClientOptions *opts, const char *name,
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool tap_has_ufo(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_probe_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_fd_set_vnet_hdr_len(int fd, int len)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_set_offload(NetClientState *nc, int csum, int tso4,
 | 
			
		||||
                     int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct vhost_net *tap_get_vhost_net(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    abort();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_enable(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    abort();
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								net/tap.c
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								net/tap.c
									
									
									
									
									
								
							@ -210,7 +210,7 @@ static void tap_send(void *opaque)
 | 
			
		||||
    } while (size > 0 && qemu_can_send_packet(&s->nc));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool tap_has_ufo(NetClientState *nc)
 | 
			
		||||
static bool tap_has_ufo(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
@ -219,7 +219,7 @@ bool tap_has_ufo(NetClientState *nc)
 | 
			
		||||
    return s->has_ufo;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
static bool tap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
@ -228,16 +228,16 @@ int tap_has_vnet_hdr(NetClientState *nc)
 | 
			
		||||
    return !!s->host_vnet_hdr_len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int tap_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
    assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
 | 
			
		||||
 | 
			
		||||
    return tap_probe_vnet_hdr_len(s->fd, len);
 | 
			
		||||
    return !!tap_probe_vnet_hdr_len(s->fd, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
@ -249,7 +249,7 @@ void tap_set_vnet_hdr_len(NetClientState *nc, int len)
 | 
			
		||||
    s->host_vnet_hdr_len = len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
 | 
			
		||||
@ -259,7 +259,7 @@ void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
 | 
			
		||||
    s->using_vnet_hdr = using_vnet_hdr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tap_set_offload(NetClientState *nc, int csum, int tso4,
 | 
			
		||||
static void tap_set_offload(NetClientState *nc, int csum, int tso4,
 | 
			
		||||
                     int tso6, int ecn, int ufo)
 | 
			
		||||
{
 | 
			
		||||
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
 | 
			
		||||
@ -314,6 +314,12 @@ static NetClientInfo net_tap_info = {
 | 
			
		||||
    .receive_iov = tap_receive_iov,
 | 
			
		||||
    .poll = tap_poll,
 | 
			
		||||
    .cleanup = tap_cleanup,
 | 
			
		||||
    .has_ufo = tap_has_ufo,
 | 
			
		||||
    .has_vnet_hdr = tap_has_vnet_hdr,
 | 
			
		||||
    .has_vnet_hdr_len = tap_has_vnet_hdr_len,
 | 
			
		||||
    .using_vnet_hdr = tap_using_vnet_hdr,
 | 
			
		||||
    .set_offload = tap_set_offload,
 | 
			
		||||
    .set_vnet_hdr_len = tap_set_vnet_hdr_len,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static TAPState *net_tap_fd_init(NetClientState *peer,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user