From 6e50d18847a76704c8a49e406084a2321117b954 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Mon, 3 Feb 2014 08:20:02 +0400 Subject: [PATCH 01/11] opencores_eth: flush queue whenever can_receive can go from false to true The following registers control whether MAC can receive frames: - MODER.RXEN bit that enables/disables receiver; - TX_BD_NUM register that specifies number of RX descriptors. Notify QEMU networking core when the MAC is ready to receive frames. Discard frame and raise BUSY interrupt when the frame arrives but the current RX descriptor is not empty. Signed-off-by: Max Filippov Reviewed-by: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- hw/net/opencores_eth.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index 4118d54ac8..4a443049dd 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -169,6 +169,7 @@ enum { }; enum { + INT_SOURCE_BUSY = 0x10, INT_SOURCE_RXB = 0x4, INT_SOURCE_TXB = 0x1, }; @@ -351,8 +352,7 @@ static int open_eth_can_receive(NetClientState *nc) OpenEthState *s = qemu_get_nic_opaque(nc); return GET_REGBIT(s, MODER, RXEN) && - (s->regs[TX_BD_NUM] < 0x80) && - (rx_desc(s)->len_flags & RXD_E); + (s->regs[TX_BD_NUM] < 0x80); } static ssize_t open_eth_receive(NetClientState *nc, @@ -402,6 +402,12 @@ static ssize_t open_eth_receive(NetClientState *nc, desc *desc = rx_desc(s); size_t copy_size = GET_REGBIT(s, MODER, HUGEN) ? 65536 : maxfl; + if (!(desc->len_flags & RXD_E)) { + open_eth_int_source_write(s, + s->regs[INT_SOURCE] | INT_SOURCE_BUSY); + return size; + } + desc->len_flags &= ~(RXD_CF | RXD_M | RXD_OR | RXD_IS | RXD_DN | RXD_TL | RXD_SF | RXD_CRC | RXD_LC); @@ -551,6 +557,15 @@ static uint64_t open_eth_reg_read(void *opaque, return v; } +static void open_eth_notify_can_receive(OpenEthState *s) +{ + NetClientState *nc = qemu_get_queue(s->nic); + + if (open_eth_can_receive(nc)) { + qemu_flush_queued_packets(nc); + } +} + static void open_eth_ro(OpenEthState *s, uint32_t val) { } @@ -567,6 +582,7 @@ static void open_eth_moder_host_write(OpenEthState *s, uint32_t val) if (set & MODER_RXEN) { s->rx_desc = s->regs[TX_BD_NUM]; + open_eth_notify_can_receive(s); } if (set & MODER_TXEN) { s->tx_desc = 0; @@ -592,6 +608,18 @@ static void open_eth_int_mask_host_write(OpenEthState *s, uint32_t val) s->regs[INT_SOURCE] & s->regs[INT_MASK]); } +static void open_eth_tx_bd_num_host_write(OpenEthState *s, uint32_t val) +{ + if (val < 0x80) { + bool enable = s->regs[TX_BD_NUM] == 0x80; + + s->regs[TX_BD_NUM] = val; + if (enable) { + open_eth_notify_can_receive(s); + } + } +} + static void open_eth_mii_command_host_write(OpenEthState *s, uint32_t val) { unsigned fiad = GET_REGFIELD(s, MIIADDRESS, FIAD); @@ -630,6 +658,7 @@ static void open_eth_reg_write(void *opaque, [MODER] = open_eth_moder_host_write, [INT_SOURCE] = open_eth_int_source_host_write, [INT_MASK] = open_eth_int_mask_host_write, + [TX_BD_NUM] = open_eth_tx_bd_num_host_write, [MIICOMMAND] = open_eth_mii_command_host_write, [MIITX_DATA] = open_eth_mii_tx_host_write, [MIISTATUS] = open_eth_ro, From e96dfd110ee1ad70e7ddbfae01ca95c66f70dac0 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:15 +0100 Subject: [PATCH 02/11] net: change vnet-hdr TAP prototypes The tap_has_vnet_hdr() and tap_has_vnet_hdr_len() functions used to return int, even though they only return true/false values. This patch changes the prototypes to return bool. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- include/net/tap.h | 4 ++-- net/tap-win32.c | 8 ++++---- net/tap.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/net/tap.h b/include/net/tap.h index a994f20447..a3490a96ab 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -30,8 +30,8 @@ #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); +bool tap_has_vnet_hdr(NetClientState *nc); +bool 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); diff --git a/net/tap-win32.c b/net/tap-win32.c index 91e9e844a0..edf26c4720 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -727,9 +727,9 @@ bool tap_has_ufo(NetClientState *nc) return false; } -int tap_has_vnet_hdr(NetClientState *nc) +bool tap_has_vnet_hdr(NetClientState *nc) { - return 0; + return false; } int tap_probe_vnet_hdr_len(int fd, int len) @@ -755,9 +755,9 @@ struct vhost_net *tap_get_vhost_net(NetClientState *nc) return NULL; } -int tap_has_vnet_hdr_len(NetClientState *nc, int len) +bool tap_has_vnet_hdr_len(NetClientState *nc, int len) { - return 0; + return false; } void tap_set_vnet_hdr_len(NetClientState *nc, int len) diff --git a/net/tap.c b/net/tap.c index 39c1cda3e4..c805f3cdc9 100644 --- a/net/tap.c +++ b/net/tap.c @@ -219,7 +219,7 @@ bool tap_has_ufo(NetClientState *nc) return s->has_ufo; } -int tap_has_vnet_hdr(NetClientState *nc) +bool tap_has_vnet_hdr(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -228,13 +228,13 @@ int tap_has_vnet_hdr(NetClientState *nc) return !!s->host_vnet_hdr_len; } -int tap_has_vnet_hdr_len(NetClientState *nc, int len) +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) From 1f55ac4586bfae81b1e805fb2f0713cb21501ae2 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:16 +0100 Subject: [PATCH 03/11] net: extend NetClientInfo for offloading Some new callbacks have been added to generalize the operations done by virtio-net and vmxnet3 frontends to manipulate TAP offloadings. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- include/net/net.h | 19 ++++++++++++++++ net/net.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/include/net/net.h b/include/net/net.h index 11e146888b..7b2539433b 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -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_peer_has_ufo(NetClientState *nc); +bool qemu_peer_has_vnet_hdr(NetClientState *nc); +bool qemu_peer_has_vnet_hdr_len(NetClientState *nc, int len); +void qemu_peer_using_vnet_hdr(NetClientState *nc, bool enable); +void qemu_peer_set_offload(NetClientState *nc, int csum, int tso4, int tso6, + int ecn, int ufo); +void qemu_peer_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); diff --git a/net/net.c b/net/net.c index 41b38830ea..06d690aa4a 100644 --- a/net/net.c +++ b/net/net.c @@ -378,6 +378,61 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) } } +bool qemu_peer_has_ufo(NetClientState *nc) +{ + if (!nc->peer || !nc->peer->info->has_ufo) { + return false; + } + + return nc->peer->info->has_ufo(nc->peer); +} + +bool qemu_peer_has_vnet_hdr(NetClientState *nc) +{ + if (!nc->peer || !nc->peer->info->has_vnet_hdr) { + return false; + } + + return nc->peer->info->has_vnet_hdr(nc->peer); +} + +bool qemu_peer_has_vnet_hdr_len(NetClientState *nc, int len) +{ + if (!nc->peer || !nc->peer->info->has_vnet_hdr_len) { + return false; + } + + return nc->peer->info->has_vnet_hdr_len(nc->peer, len); +} + +void qemu_peer_using_vnet_hdr(NetClientState *nc, bool enable) +{ + if (!nc->peer || !nc->peer->info->using_vnet_hdr) { + return; + } + + nc->peer->info->using_vnet_hdr(nc->peer, enable); +} + +void qemu_peer_set_offload(NetClientState *nc, int csum, int tso4, int tso6, + int ecn, int ufo) +{ + if (!nc->peer || !nc->peer->info->set_offload) { + return; + } + + nc->peer->info->set_offload(nc->peer, csum, tso4, tso6, ecn, ufo); +} + +void qemu_peer_set_vnet_hdr_len(NetClientState *nc, int len) +{ + if (!nc->peer || !nc->peer->info->set_vnet_hdr_len) { + return; + } + + nc->peer->info->set_vnet_hdr_len(nc->peer, len); +} + int qemu_can_send_packet(NetClientState *sender) { if (!sender->peer) { From 2e753bcc7db1a7d2af0d47c0ae7e82a04ce69d63 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:17 +0100 Subject: [PATCH 04/11] net: TAP uses NetClientInfo offloading callbacks The TAP NetClientInfo structure is inizialized with the TAP-specific functions that manipulates offloading features. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- net/tap-win32.c | 92 ++++++++++++++++++++++++++----------------------- net/tap.c | 6 ++++ 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/net/tap-win32.c b/net/tap-win32.c index edf26c4720..924ca55bd4 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -669,11 +669,60 @@ static void tap_win32_send(void *opaque) } } +bool tap_has_ufo(NetClientState *nc) +{ + return false; +} + +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) +{ +} + +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; +} + +bool tap_has_vnet_hdr_len(NetClientState *nc, int len) +{ + return false; +} + +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; -} - -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) -{ -} - -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; -} - -bool tap_has_vnet_hdr_len(NetClientState *nc, int len) -{ - return false; -} - -void tap_set_vnet_hdr_len(NetClientState *nc, int len) -{ - abort(); -} - int tap_enable(NetClientState *nc) { abort(); diff --git a/net/tap.c b/net/tap.c index c805f3cdc9..d34ec8802a 100644 --- a/net/tap.c +++ b/net/tap.c @@ -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, From cf528b89580797050b8cf60fee6247f35531a675 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:18 +0100 Subject: [PATCH 05/11] net: virtio-net and vmxnet3 use offloading API With this patch, virtio-net and vmxnet3 frontends make use of the qemu_peer_* API for backend offloadings manipulations, instead of calling TAP-specific functions directly. We also remove the existing checks which prevent those frontends from using offloadings with backends different from TAP (e.g. netmap). Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- hw/net/vhost_net.c | 4 ++-- hw/net/virtio-net.c | 16 ++++++---------- hw/net/vmxnet3.c | 12 +++++------- 3 files changed, 13 insertions(+), 19 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 854997d9ba..c90b9ec9ab 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -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 = backend->info->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 (!backend->info->has_vnet_hdr_len(backend, sizeof(struct virtio_net_hdr_mrg_rxbuf))) { net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 36266083b2..cda8c7549e 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -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_peer_has_vnet_hdr(nc); } 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_peer_has_ufo(qemu_get_queue(n->nic)); 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_peer_has_vnet_hdr_len(nc, n->guest_hdr_len)) { + qemu_peer_set_vnet_hdr_len(nc, 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_peer_set_offload(qemu_get_subqueue(n->nic, 0), !!(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_peer_using_vnet_hdr(qemu_get_subqueue(n->nic, i), true); } n->host_hdr_len = sizeof(struct virtio_net_hdr); } else { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 19687aa03c..0524684923 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -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_peer_set_offload(qemu_get_queue(s->nic), 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_peer_has_vnet_hdr(nc)) { 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_peer_set_vnet_hdr_len(qemu_get_queue(s->nic), sizeof(struct virtio_net_hdr)); - tap_using_vnet_hdr(qemu_get_queue(s->nic)->peer, 1); + qemu_peer_using_vnet_hdr(qemu_get_queue(s->nic), 1); } qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); From 3bac80d31af9d38d02e80d1541a1ea8e70067bad Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:19 +0100 Subject: [PATCH 06/11] net: make tap offloading callbacks static Since TAP offloadings are manipulated through a new API, it's not necessary to export them in include/net/tap.h anymore. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- include/net/tap.h | 6 ------ net/tap-win32.c | 12 ++++++------ net/tap.c | 12 ++++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/include/net/tap.h b/include/net/tap.h index a3490a96ab..6daeb42b0f 100644 --- a/include/net/tap.h +++ b/include/net/tap.h @@ -29,12 +29,6 @@ #include "qemu-common.h" #include "qapi-types.h" -bool tap_has_ufo(NetClientState *nc); -bool tap_has_vnet_hdr(NetClientState *nc); -bool 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); diff --git a/net/tap-win32.c b/net/tap-win32.c index 924ca55bd4..8aee611f7d 100644 --- a/net/tap-win32.c +++ b/net/tap-win32.c @@ -669,12 +669,12 @@ static void tap_win32_send(void *opaque) } } -bool tap_has_ufo(NetClientState *nc) +static bool tap_has_ufo(NetClientState *nc) { return false; } -bool tap_has_vnet_hdr(NetClientState *nc) +static bool tap_has_vnet_hdr(NetClientState *nc) { return false; } @@ -688,11 +688,11 @@ void tap_fd_set_vnet_hdr_len(int fd, int len) { } -void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr) +static void tap_using_vnet_hdr(NetClientState *nc, bool 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) { } @@ -702,12 +702,12 @@ struct vhost_net *tap_get_vhost_net(NetClientState *nc) return NULL; } -bool tap_has_vnet_hdr_len(NetClientState *nc, int len) +static bool tap_has_vnet_hdr_len(NetClientState *nc, int len) { return false; } -void tap_set_vnet_hdr_len(NetClientState *nc, int len) +static void tap_set_vnet_hdr_len(NetClientState *nc, int len) { abort(); } diff --git a/net/tap.c b/net/tap.c index d34ec8802a..2d5099b9be 100644 --- a/net/tap.c +++ b/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; } -bool tap_has_vnet_hdr(NetClientState *nc) +static bool tap_has_vnet_hdr(NetClientState *nc) { TAPState *s = DO_UPCAST(TAPState, nc, nc); @@ -228,7 +228,7 @@ bool tap_has_vnet_hdr(NetClientState *nc) return !!s->host_vnet_hdr_len; } -bool 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); @@ -237,7 +237,7 @@ bool tap_has_vnet_hdr_len(NetClientState *nc, int 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); From f6c65bfb93fd90f69a11fd1db1e7b2cebb056b01 Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 6 Feb 2014 17:02:20 +0100 Subject: [PATCH 07/11] net: add offloading support to netmap backend Whit this patch, the netmap backend supports TSO/UFO/CSUM offloadings, and accepts the virtio-net header, similarly to what happens with TAP. The offloading callbacks in the NetClientInfo interface have been implemented. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- net/netmap.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/net/netmap.c b/net/netmap.c index 0ccc4976b5..73f6d7acf3 100644 --- a/net/netmap.c +++ b/net/netmap.c @@ -31,6 +31,7 @@ #include #include "net/net.h" +#include "net/tap.h" #include "clients.h" #include "sysemu/sysemu.h" #include "qemu/error-report.h" @@ -54,6 +55,7 @@ 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, ...) \ @@ -274,7 +276,7 @@ static ssize_t netmap_receive_iov(NetClientState *nc, return iov_size(iov, iovcnt); } - i = ring->cur; + last = i = ring->cur; avail = ring->avail; if (avail < iovcnt) { @@ -394,6 +396,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 +462,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 +493,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; From 0a985b37272b563b1f8414431c6064eb1aa0c97b Mon Sep 17 00:00:00 2001 From: Vincenzo Maffione Date: Thu, 20 Feb 2014 15:40:43 +0100 Subject: [PATCH 08/11] net: Disable netmap backend when not supported This patch fixes configure so that the netmap backend is not compiled in if the host doesn't support an API version >= 11. A version upper bound (15) has been added so that the netmap API can be extended with some minor features without requiring QEMU code modifications. Moreover, some changes have been done to net/netmap.c in order to reflect the current netmap API/ABI (11). The NETMAP_WITH_LIBS macro makes possible to include some utilities (e.g. netmap ring macros, D(), RD() and other high level functions) through the netmap headers. In this way we get rid of the D and RD macro definitions in the QEMU code, and we open the way for further code simplifications that will be introduced by future patches. Signed-off-by: Vincenzo Maffione Signed-off-by: Stefan Hajnoczi --- configure | 10 +++++++++- net/netmap.c | 55 +++++++++++++--------------------------------------- 2 files changed, 22 insertions(+), 43 deletions(-) diff --git a/configure b/configure index 00f90702bc..9ad3ff3aeb 100755 --- a/configure +++ b/configure @@ -2215,13 +2215,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 #include #include #include +#if (NETMAP_API < 11) || (NETMAP_API > 15) +#error +#endif int main(void) { return 0; } EOF if compile_prog "" "" ; then diff --git a/net/netmap.c b/net/netmap.c index 73f6d7acf3..8213304a5b 100644 --- a/net/netmap.c +++ b/net/netmap.c @@ -27,6 +27,8 @@ #include #include #include +#include +#define NETMAP_WITH_LIBS #include #include @@ -58,31 +60,6 @@ typedef struct NetmapState { 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 @@ -239,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; @@ -252,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; @@ -269,7 +245,6 @@ 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. */ @@ -277,9 +252,8 @@ static ssize_t netmap_receive_iov(NetClientState *nc, } last = i = ring->cur; - avail = ring->avail; - if (avail < iovcnt) { + if (nm_ring_space(ring) < iovcnt) { /* Not enough netmap slots. */ netmap_write_poll(s, true); return 0; @@ -295,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); @@ -310,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; @@ -320,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); @@ -345,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; @@ -360,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"); } From d6085e3ace20bc9b0fa625d8d79b22668710e217 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 20 Feb 2014 12:14:07 +0100 Subject: [PATCH 09/11] net: remove implicit peer from offload API The virtio_net offload APIs are used on the NIC's peer (i.e. the tap device). The API was defined to implicitly use nc->peer, saving the caller the trouble. This wasn't ideal because: 1. There are callers who have the peer but not the NIC. Currently they are forced to bypass the API and access peer->info->... directly. 2. The rest of the net.h API uses nc, not nc->peer, so it is inconsistent. This patch pushes nc->peer back up to callers. Signed-off-by: Stefan Hajnoczi --- hw/net/virtio-net.c | 12 ++++++------ hw/net/vmxnet3.c | 18 +++++++++--------- include/net/net.h | 14 +++++++------- net/net.c | 36 ++++++++++++++++++------------------ 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index cda8c7549e..9218a09ffc 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -325,7 +325,7 @@ static void peer_test_vnet_hdr(VirtIONet *n) return; } - n->has_vnet_hdr = qemu_peer_has_vnet_hdr(nc); + n->has_vnet_hdr = qemu_has_vnet_hdr(nc->peer); } static int peer_has_vnet_hdr(VirtIONet *n) @@ -338,7 +338,7 @@ static int peer_has_ufo(VirtIONet *n) if (!peer_has_vnet_hdr(n)) return 0; - n->has_ufo = qemu_peer_has_ufo(qemu_get_queue(n->nic)); + n->has_ufo = qemu_has_ufo(qemu_get_queue(n->nic)->peer); return n->has_ufo; } @@ -357,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) && - qemu_peer_has_vnet_hdr_len(nc, n->guest_hdr_len)) { - qemu_peer_set_vnet_hdr_len(nc, 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; } } @@ -459,7 +459,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) static void virtio_net_apply_guest_offloads(VirtIONet *n) { - qemu_peer_set_offload(qemu_get_subqueue(n->nic, 0), + qemu_set_offload(qemu_get_subqueue(n->nic, 0)->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)), @@ -1540,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++) { - qemu_peer_using_vnet_hdr(qemu_get_subqueue(n->nic, i), true); + qemu_using_vnet_hdr(qemu_get_subqueue(n->nic, i)->peer, true); } n->host_hdr_len = sizeof(struct virtio_net_hdr); } else { diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 0524684923..5be807ce82 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -1290,12 +1290,12 @@ static void vmxnet3_update_features(VMXNET3State *s) s->lro_supported, rxcso_supported, s->rx_vlan_stripping); if (s->peer_has_vhdr) { - qemu_peer_set_offload(qemu_get_queue(s->nic), - rxcso_supported, - s->lro_supported, - s->lro_supported, - 0, - 0); + qemu_set_offload(qemu_get_queue(s->nic)->peer, + rxcso_supported, + s->lro_supported, + s->lro_supported, + 0, + 0); } } @@ -1885,7 +1885,7 @@ static bool vmxnet3_peer_has_vnet_hdr(VMXNET3State *s) { NetClientState *nc = qemu_get_queue(s->nic); - if (qemu_peer_has_vnet_hdr(nc)) { + if (qemu_has_vnet_hdr(nc->peer)) { return true; } @@ -1933,10 +1933,10 @@ static void vmxnet3_net_init(VMXNET3State *s) s->lro_supported = false; if (s->peer_has_vhdr) { - qemu_peer_set_vnet_hdr_len(qemu_get_queue(s->nic), + qemu_set_vnet_hdr_len(qemu_get_queue(s->nic)->peer, sizeof(struct virtio_net_hdr)); - qemu_peer_using_vnet_hdr(qemu_get_queue(s->nic), 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); diff --git a/include/net/net.h b/include/net/net.h index 7b2539433b..8166345a13 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -132,13 +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_peer_has_ufo(NetClientState *nc); -bool qemu_peer_has_vnet_hdr(NetClientState *nc); -bool qemu_peer_has_vnet_hdr_len(NetClientState *nc, int len); -void qemu_peer_using_vnet_hdr(NetClientState *nc, bool enable); -void qemu_peer_set_offload(NetClientState *nc, int csum, int tso4, int tso6, - int ecn, int ufo); -void qemu_peer_set_vnet_hdr_len(NetClientState *nc, int len); +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); diff --git a/net/net.c b/net/net.c index 06d690aa4a..e3ef1e4f1d 100644 --- a/net/net.c +++ b/net/net.c @@ -378,59 +378,59 @@ void qemu_foreach_nic(qemu_nic_foreach func, void *opaque) } } -bool qemu_peer_has_ufo(NetClientState *nc) +bool qemu_has_ufo(NetClientState *nc) { - if (!nc->peer || !nc->peer->info->has_ufo) { + if (!nc || !nc->info->has_ufo) { return false; } - return nc->peer->info->has_ufo(nc->peer); + return nc->info->has_ufo(nc); } -bool qemu_peer_has_vnet_hdr(NetClientState *nc) +bool qemu_has_vnet_hdr(NetClientState *nc) { - if (!nc->peer || !nc->peer->info->has_vnet_hdr) { + if (!nc || !nc->info->has_vnet_hdr) { return false; } - return nc->peer->info->has_vnet_hdr(nc->peer); + return nc->info->has_vnet_hdr(nc); } -bool qemu_peer_has_vnet_hdr_len(NetClientState *nc, int len) +bool qemu_has_vnet_hdr_len(NetClientState *nc, int len) { - if (!nc->peer || !nc->peer->info->has_vnet_hdr_len) { + if (!nc || !nc->info->has_vnet_hdr_len) { return false; } - return nc->peer->info->has_vnet_hdr_len(nc->peer, len); + return nc->info->has_vnet_hdr_len(nc, len); } -void qemu_peer_using_vnet_hdr(NetClientState *nc, bool enable) +void qemu_using_vnet_hdr(NetClientState *nc, bool enable) { - if (!nc->peer || !nc->peer->info->using_vnet_hdr) { + if (!nc || !nc->info->using_vnet_hdr) { return; } - nc->peer->info->using_vnet_hdr(nc->peer, enable); + nc->info->using_vnet_hdr(nc, enable); } -void qemu_peer_set_offload(NetClientState *nc, int csum, int tso4, int tso6, +void qemu_set_offload(NetClientState *nc, int csum, int tso4, int tso6, int ecn, int ufo) { - if (!nc->peer || !nc->peer->info->set_offload) { + if (!nc || !nc->info->set_offload) { return; } - nc->peer->info->set_offload(nc->peer, csum, tso4, tso6, ecn, ufo); + nc->info->set_offload(nc, csum, tso4, tso6, ecn, ufo); } -void qemu_peer_set_vnet_hdr_len(NetClientState *nc, int len) +void qemu_set_vnet_hdr_len(NetClientState *nc, int len) { - if (!nc->peer || !nc->peer->info->set_vnet_hdr_len) { + if (!nc || !nc->info->set_vnet_hdr_len) { return; } - nc->peer->info->set_vnet_hdr_len(nc->peer, len); + nc->info->set_vnet_hdr_len(nc, len); } int qemu_can_send_packet(NetClientState *sender) From e3e48565c1553f9ab4c34c2388287a013ef30deb Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 20 Feb 2014 12:14:08 +0100 Subject: [PATCH 10/11] vhost_net: use offload API instead of bypassing it There is no need to access backend->info->has_vnet_hdr() and friends anymore. Use the qemu_has_vnet_hdr() API instead. Signed-off-by: Stefan Hajnoczi --- hw/net/vhost_net.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index c90b9ec9ab..a1de2f43a0 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -106,7 +106,7 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd, goto fail; } net->nc = backend; - net->dev.backend_features = backend->info->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,8 +117,8 @@ struct vhost_net *vhost_net_init(NetClientState *backend, int devfd, if (r < 0) { goto fail; } - if (!backend->info->has_vnet_hdr_len(backend, - sizeof(struct virtio_net_hdr_mrg_rxbuf))) { + if (!qemu_has_vnet_hdr_len(backend, + sizeof(struct virtio_net_hdr_mrg_rxbuf))) { net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); } if (~net->dev.features & net->dev.backend_features) { From ad37bb3b000963b36b5c30f5a4239cfbc4fe8725 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 20 Feb 2014 12:14:09 +0100 Subject: [PATCH 11/11] virtio-net: use qemu_get_queue() where possible qemu_get_queue() is a shorthand for qemu_get_subqueue(n->nic, 0). Use the shorthand where possible. Signed-off-by: Stefan Hajnoczi --- hw/net/virtio-net.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9218a09ffc..3c0342e17a 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -459,7 +459,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev) static void virtio_net_apply_guest_offloads(VirtIONet *n) { - qemu_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)),