mirror of
https://github.com/qemu/qemu.git
synced 2024-12-04 09:13:39 +08:00
1bfa316ce7
When running a fully emulated device in cross-endian conditions, including a virtio 1.0 device offered to a big endian guest, we need to fix the vnet headers. This is currently handled by the virtio_net_hdr_swap() function in the core virtio-net code but it should actually be handled by the net backend. With this patch, virtio-net now tries to configure the backend to do the endian fixing when the device starts (i.e. drivers sets the CONFIG_OK bit). If the backend cannot support the requested endiannes, we have to fallback onto virtio_net_hdr_swap(): this is recorded in the needs_vnet_hdr_swap flag, to be used in the TX and RX paths. Note that we reset the backend to the default behaviour (guest native endianness) when the device stops (i.e. device status had CONFIG_OK bit and driver unsets it). This is needed, with the linux tap backend at least, otherwise the guest may lose network connectivity if rebooted into a different endianness. The current vhost-net code also tries to configure net backends. This will be no more needed and will be reverted in a subsequent patch. Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com> Reviewed-by: Laurent Vivier <lvivier@redhat.com> Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Laurent Vivier <lvivier@redhat.com>
104 lines
2.5 KiB
C
104 lines
2.5 KiB
C
/*
|
|
* Virtio Network Device
|
|
*
|
|
* Copyright IBM, Corp. 2007
|
|
*
|
|
* Authors:
|
|
* Anthony Liguori <aliguori@us.ibm.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
* the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#ifndef _QEMU_VIRTIO_NET_H
|
|
#define _QEMU_VIRTIO_NET_H
|
|
|
|
#include "standard-headers/linux/virtio_net.h"
|
|
#include "hw/virtio/virtio.h"
|
|
|
|
#define TYPE_VIRTIO_NET "virtio-net-device"
|
|
#define VIRTIO_NET(obj) \
|
|
OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
|
|
|
|
#define TX_TIMER_INTERVAL 150000 /* 150 us */
|
|
|
|
/* Limit the number of packets that can be sent via a single flush
|
|
* of the TX queue. This gives us a guaranteed exit condition and
|
|
* ensures fairness in the io path. 256 conveniently matches the
|
|
* length of the TX queue and shows a good balance of performance
|
|
* and latency. */
|
|
#define TX_BURST 256
|
|
|
|
typedef struct virtio_net_conf
|
|
{
|
|
uint32_t txtimer;
|
|
int32_t txburst;
|
|
char *tx;
|
|
} virtio_net_conf;
|
|
|
|
/* Maximum packet size we can receive from tap device: header + 64k */
|
|
#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
|
|
|
|
typedef struct VirtIONetQueue {
|
|
VirtQueue *rx_vq;
|
|
VirtQueue *tx_vq;
|
|
QEMUTimer *tx_timer;
|
|
QEMUBH *tx_bh;
|
|
int tx_waiting;
|
|
struct {
|
|
VirtQueueElement *elem;
|
|
} async_tx;
|
|
struct VirtIONet *n;
|
|
} VirtIONetQueue;
|
|
|
|
typedef struct VirtIONet {
|
|
VirtIODevice parent_obj;
|
|
uint8_t mac[ETH_ALEN];
|
|
uint16_t status;
|
|
VirtIONetQueue *vqs;
|
|
VirtQueue *ctrl_vq;
|
|
NICState *nic;
|
|
uint32_t tx_timeout;
|
|
int32_t tx_burst;
|
|
uint32_t has_vnet_hdr;
|
|
size_t host_hdr_len;
|
|
size_t guest_hdr_len;
|
|
uint32_t host_features;
|
|
uint8_t has_ufo;
|
|
int mergeable_rx_bufs;
|
|
uint8_t promisc;
|
|
uint8_t allmulti;
|
|
uint8_t alluni;
|
|
uint8_t nomulti;
|
|
uint8_t nouni;
|
|
uint8_t nobcast;
|
|
uint8_t vhost_started;
|
|
struct {
|
|
uint32_t in_use;
|
|
uint32_t first_multi;
|
|
uint8_t multi_overflow;
|
|
uint8_t uni_overflow;
|
|
uint8_t *macs;
|
|
} mac_table;
|
|
uint32_t *vlans;
|
|
virtio_net_conf net_conf;
|
|
NICConf nic_conf;
|
|
DeviceState *qdev;
|
|
int multiqueue;
|
|
uint16_t max_queues;
|
|
uint16_t curr_queues;
|
|
size_t config_size;
|
|
char *netclient_name;
|
|
char *netclient_type;
|
|
uint64_t curr_guest_offloads;
|
|
QEMUTimer *announce_timer;
|
|
int announce_counter;
|
|
bool needs_vnet_hdr_swap;
|
|
} VirtIONet;
|
|
|
|
void virtio_net_set_netclient_name(VirtIONet *n, const char *name,
|
|
const char *type);
|
|
|
|
#endif
|