mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'net-pull-request' of https://github.com/jasowang/qemu into staging
# -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEEIV1G9IJGaJ7HfzVi7wSWWzmNYhEFAmh0lXsACgkQ7wSWWzmN # YhGvVwf+OxTtnr84VdsEckqNVuzVkMHk3PAuSlxpvfjHXnwwo5Efto9lA4h4BUSX # As9sYpF3qXZdh95QYB/49CvVdizsI/KW1wPEx4ryVqCi7kcdOrzNB/MMMXBrrJE+ # 86xtc2a53CHHcctUIvkBr/GVzhay/gm6VHjnPEB/B0Tv+rTKpIBr/nJzVlG+8uX9 # O/XRI0aqnCPlsWDQFR2TbyE4TSSmTw5oXru0I12tPfxt2ed6b+izKubHmqgeLCyH # ne+qEy2ds40eBZ4YMDDIsxYKY8RlWIdUY0Dnz6wSjC00BNo5yLu7cirL0Ozd6AsI # pK5eqQGZGGQIGV/KD+M7WwKWVltBJg== # =rS9w # -----END PGP SIGNATURE----- # gpg: Signature made Mon 14 Jul 2025 01:28:27 EDT # gpg: using RSA key 215D46F48246689EC77F3562EF04965B398D6211 # gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>" [full] # Primary key fingerprint: 215D 46F4 8246 689E C77F 3562 EF04 965B 398D 6211 * tag 'net-pull-request' of https://github.com/jasowang/qemu: net/passt: Implement vhost-user backend support net: Add passt network backend net: Add is_vhost_user flag to vhost_net struct net: Allow network backends to advertise max TX queue size net: Add save_acked_features callback to vhost_net net: Add get_acked_features callback to VhostNetOptions net: Consolidate vhost feature bits into vhost_net structure net: Add get_vhost_net callback to NetClientInfo vhost_net: Rename vhost_set_vring_enable() for clarity net: Define net_client_set_link() net: Refactor stream logic for reuse in '-net passt' virtio-net: Add queues for RSS during migration net: fix buffer overflow in af_xdp_umem_create() Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
@@ -85,13 +85,59 @@ passt doesn't require any capability or privilege. passt has
|
||||
better performance than ``-net user``, full IPv6 support and better security
|
||||
as it's a daemon that is not executed in QEMU context.
|
||||
|
||||
passt can be connected to QEMU either by using a socket
|
||||
(``-netdev stream``) or using the vhost-user interface (``-netdev vhost-user``).
|
||||
passt_ can be used in the same way as the user backend (using ``-net passt``,
|
||||
``-netdev passt`` or ``-nic passt``) or it can be launched manually and
|
||||
connected to QEMU either by using a socket (``-netdev stream``) or by using
|
||||
the vhost-user interface (``-netdev vhost-user``).
|
||||
|
||||
Using ``-netdev stream`` or ``-netdev vhost-user`` will allow the user to
|
||||
enable functionalities not available through the passt backend interface
|
||||
(like migration).
|
||||
|
||||
See `passt(1)`_ for more details on passt.
|
||||
|
||||
.. _passt: https://passt.top/
|
||||
.. _passt(1): https://passt.top/builds/latest/web/passt.1.html
|
||||
|
||||
To use the passt backend interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There is no need to start the daemon as QEMU will do it for you.
|
||||
|
||||
By default, passt will be started in the socket-based mode.
|
||||
|
||||
.. parsed-literal::
|
||||
|qemu_system| [...OPTIONS...] -nic passt
|
||||
|
||||
(qemu) info network
|
||||
e1000e.0: index=0,type=nic,model=e1000e,macaddr=52:54:00:12:34:56
|
||||
\ #net071: index=0,type=passt,stream,connected to pid 24846
|
||||
|
||||
.. parsed-literal::
|
||||
|qemu_system| [...OPTIONS...] -net nic -net passt,tcp-ports=10001,udp-ports=10001
|
||||
|
||||
(qemu) info network
|
||||
hub 0
|
||||
\ hub0port1: #net136: index=0,type=passt,stream,connected to pid 25204
|
||||
\ hub0port0: e1000e.0: index=0,type=nic,model=e1000e,macaddr=52:54:00:12:34:56
|
||||
|
||||
.. parsed-literal::
|
||||
|qemu_system| [...OPTIONS...] -netdev passt,id=netdev0 -device virtio-net,mac=9a:2b:2c:2d:2e:2f,id=virtio0,netdev=netdev0
|
||||
|
||||
(qemu) info network
|
||||
virtio0: index=0,type=nic,model=virtio-net-pci,macaddr=9a:2b:2c:2d:2e:2f
|
||||
\ netdev0: index=0,type=passt,stream,connected to pid 25428
|
||||
|
||||
To use the vhost-based interface, add the ``vhost-user=on`` parameter and
|
||||
select the virtio-net device:
|
||||
|
||||
.. parsed-literal::
|
||||
|qemu_system| [...OPTIONS...] -nic passt,model=virtio,vhost-user=on
|
||||
|
||||
(qemu) info network
|
||||
virtio-net-pci.0: index=0,type=nic,model=virtio-net-pci,macaddr=52:54:00:12:34:56
|
||||
\ #net006: index=0,type=passt,vhost-user,connected to pid 25731
|
||||
|
||||
To use socket based passt interface:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -1287,6 +1287,9 @@ ERST
|
||||
.name = "netdev_add",
|
||||
.args_type = "netdev:O",
|
||||
.params = "[user|tap|socket|stream|dgram|vde|bridge|hubport|netmap|vhost-user"
|
||||
#ifdef CONFIG_PASST
|
||||
"|passt"
|
||||
#endif
|
||||
#ifdef CONFIG_AF_XDP
|
||||
"|af-xdp"
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "net/net.h"
|
||||
#include "net/tap.h"
|
||||
#include "net/vhost-user.h"
|
||||
|
||||
#include "hw/virtio/virtio-net.h"
|
||||
#include "net/vhost_net.h"
|
||||
@@ -101,7 +100,7 @@ VHostNetState *get_vhost_net(NetClientState *nc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vhost_set_vring_enable(NetClientState *nc, int enable)
|
||||
int vhost_net_set_vring_enable(NetClientState *nc, int enable)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
+19
-126
@@ -16,7 +16,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "net/net.h"
|
||||
#include "net/tap.h"
|
||||
#include "net/vhost-user.h"
|
||||
#include "net/vhost-vdpa.h"
|
||||
|
||||
#include "standard-headers/linux/vhost_types.h"
|
||||
@@ -36,94 +35,9 @@
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "linux-headers/linux/vhost.h"
|
||||
|
||||
|
||||
/* Features supported by host kernel. */
|
||||
static const int kernel_feature_bits[] = {
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY,
|
||||
VIRTIO_RING_F_INDIRECT_DESC,
|
||||
VIRTIO_RING_F_EVENT_IDX,
|
||||
VIRTIO_NET_F_MRG_RXBUF,
|
||||
VIRTIO_F_VERSION_1,
|
||||
VIRTIO_NET_F_MTU,
|
||||
VIRTIO_F_IOMMU_PLATFORM,
|
||||
VIRTIO_F_RING_PACKED,
|
||||
VIRTIO_F_RING_RESET,
|
||||
VIRTIO_F_IN_ORDER,
|
||||
VIRTIO_F_NOTIFICATION_DATA,
|
||||
VIRTIO_NET_F_RSC_EXT,
|
||||
VIRTIO_NET_F_HASH_REPORT,
|
||||
VHOST_INVALID_FEATURE_BIT
|
||||
};
|
||||
|
||||
/* Features supported by others. */
|
||||
static const int user_feature_bits[] = {
|
||||
VIRTIO_F_NOTIFY_ON_EMPTY,
|
||||
VIRTIO_F_NOTIFICATION_DATA,
|
||||
VIRTIO_RING_F_INDIRECT_DESC,
|
||||
VIRTIO_RING_F_EVENT_IDX,
|
||||
|
||||
VIRTIO_F_ANY_LAYOUT,
|
||||
VIRTIO_F_VERSION_1,
|
||||
VIRTIO_NET_F_CSUM,
|
||||
VIRTIO_NET_F_GUEST_CSUM,
|
||||
VIRTIO_NET_F_GSO,
|
||||
VIRTIO_NET_F_GUEST_TSO4,
|
||||
VIRTIO_NET_F_GUEST_TSO6,
|
||||
VIRTIO_NET_F_GUEST_ECN,
|
||||
VIRTIO_NET_F_GUEST_UFO,
|
||||
VIRTIO_NET_F_HOST_TSO4,
|
||||
VIRTIO_NET_F_HOST_TSO6,
|
||||
VIRTIO_NET_F_HOST_ECN,
|
||||
VIRTIO_NET_F_HOST_UFO,
|
||||
VIRTIO_NET_F_MRG_RXBUF,
|
||||
VIRTIO_NET_F_MTU,
|
||||
VIRTIO_F_IOMMU_PLATFORM,
|
||||
VIRTIO_F_RING_PACKED,
|
||||
VIRTIO_F_RING_RESET,
|
||||
VIRTIO_F_IN_ORDER,
|
||||
VIRTIO_NET_F_RSS,
|
||||
VIRTIO_NET_F_RSC_EXT,
|
||||
VIRTIO_NET_F_HASH_REPORT,
|
||||
VIRTIO_NET_F_GUEST_USO4,
|
||||
VIRTIO_NET_F_GUEST_USO6,
|
||||
VIRTIO_NET_F_HOST_USO,
|
||||
|
||||
/* This bit implies RARP isn't sent by QEMU out of band */
|
||||
VIRTIO_NET_F_GUEST_ANNOUNCE,
|
||||
|
||||
VIRTIO_NET_F_MQ,
|
||||
|
||||
VHOST_INVALID_FEATURE_BIT
|
||||
};
|
||||
|
||||
static const int *vhost_net_get_feature_bits(struct vhost_net *net)
|
||||
{
|
||||
const int *feature_bits = 0;
|
||||
|
||||
switch (net->nc->info->type) {
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
feature_bits = kernel_feature_bits;
|
||||
break;
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
feature_bits = user_feature_bits;
|
||||
break;
|
||||
#ifdef CONFIG_VHOST_NET_VDPA
|
||||
case NET_CLIENT_DRIVER_VHOST_VDPA:
|
||||
feature_bits = vdpa_feature_bits;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error_report("Feature bits not defined for this type: %d",
|
||||
net->nc->info->type);
|
||||
break;
|
||||
}
|
||||
|
||||
return feature_bits;
|
||||
}
|
||||
|
||||
uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
|
||||
{
|
||||
return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net),
|
||||
return vhost_get_features(&net->dev, net->feature_bits,
|
||||
features);
|
||||
}
|
||||
int vhost_net_get_config(struct vhost_net *net, uint8_t *config,
|
||||
@@ -140,7 +54,7 @@ int vhost_net_set_config(struct vhost_net *net, const uint8_t *data,
|
||||
void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
|
||||
{
|
||||
net->dev.acked_features = net->dev.backend_features;
|
||||
vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features);
|
||||
vhost_ack_features(&net->dev, net->feature_bits, features);
|
||||
}
|
||||
|
||||
uint64_t vhost_net_get_max_queues(VHostNetState *net)
|
||||
@@ -155,11 +69,11 @@ uint64_t vhost_net_get_acked_features(VHostNetState *net)
|
||||
|
||||
void vhost_net_save_acked_features(NetClientState *nc)
|
||||
{
|
||||
#ifdef CONFIG_VHOST_NET_USER
|
||||
if (nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
vhost_user_save_acked_features(nc);
|
||||
struct vhost_net *net = get_vhost_net(nc);
|
||||
|
||||
if (net && net->save_acked_features) {
|
||||
net->save_acked_features(nc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vhost_net_disable_notifiers_nvhosts(VirtIODevice *dev,
|
||||
@@ -329,6 +243,10 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
||||
}
|
||||
net->nc = options->net_backend;
|
||||
net->dev.nvqs = options->nvqs;
|
||||
net->feature_bits = options->feature_bits;
|
||||
net->save_acked_features = options->save_acked_features;
|
||||
net->max_tx_queue_size = options->max_tx_queue_size;
|
||||
net->is_vhost_user = options->is_vhost_user;
|
||||
|
||||
net->dev.max_queues = 1;
|
||||
net->dev.vqs = net->vqs;
|
||||
@@ -372,9 +290,8 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
||||
}
|
||||
|
||||
/* Set sane init value. Override when guest acks. */
|
||||
#ifdef CONFIG_VHOST_NET_USER
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
features = vhost_user_get_acked_features(net->nc);
|
||||
if (options->get_acked_features) {
|
||||
features = options->get_acked_features(net->nc);
|
||||
if (~net->dev.features & features) {
|
||||
fprintf(stderr, "vhost lacks feature mask 0x%" PRIx64
|
||||
" for backend\n",
|
||||
@@ -382,7 +299,6 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vhost_net_ack_features(net, features);
|
||||
|
||||
@@ -525,7 +441,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
||||
* because vhost user doesn't interrupt masking/unmasking
|
||||
* properly.
|
||||
*/
|
||||
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
if (net->is_vhost_user) {
|
||||
dev->use_guest_notifier_mask = false;
|
||||
}
|
||||
}
|
||||
@@ -551,7 +467,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
|
||||
|
||||
if (peer->vring_enable) {
|
||||
/* restore vring enable state */
|
||||
r = vhost_set_vring_enable(peer, peer->vring_enable);
|
||||
r = vhost_net_set_vring_enable(peer, peer->vring_enable);
|
||||
|
||||
if (r < 0) {
|
||||
goto err_guest_notifiers;
|
||||
@@ -649,44 +565,21 @@ void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask)
|
||||
{
|
||||
vhost_config_mask(&net->dev, dev, mask);
|
||||
}
|
||||
|
||||
VHostNetState *get_vhost_net(NetClientState *nc)
|
||||
{
|
||||
VHostNetState *vhost_net = 0;
|
||||
|
||||
if (!nc) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (nc->info->type) {
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
vhost_net = tap_get_vhost_net(nc);
|
||||
/*
|
||||
* tap_get_vhost_net() can return NULL if a tap net-device backend is
|
||||
* created with 'vhost=off' option, 'vhostforce=off' or no vhost or
|
||||
* vhostforce or vhostfd options at all. Please see net_init_tap_one().
|
||||
* Hence, we omit the assertion here.
|
||||
*/
|
||||
break;
|
||||
#ifdef CONFIG_VHOST_NET_USER
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
vhost_net = vhost_user_get_vhost_net(nc);
|
||||
assert(vhost_net);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_VHOST_NET_VDPA
|
||||
case NET_CLIENT_DRIVER_VHOST_VDPA:
|
||||
vhost_net = vhost_vdpa_get_vhost_net(nc);
|
||||
assert(vhost_net);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
if (nc->info->get_vhost_net) {
|
||||
return nc->info->get_vhost_net(nc);
|
||||
}
|
||||
|
||||
return vhost_net;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int vhost_set_vring_enable(NetClientState *nc, int enable)
|
||||
int vhost_net_set_vring_enable(NetClientState *nc, int enable)
|
||||
{
|
||||
VHostNetState *net = get_vhost_net(nc);
|
||||
const VhostOps *vhost_ops = net->dev.vhost_ops;
|
||||
|
||||
+24
-23
@@ -670,34 +670,36 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
|
||||
static int virtio_net_max_tx_queue_size(VirtIONet *n)
|
||||
{
|
||||
NetClientState *peer = n->nic_conf.peers.ncs[0];
|
||||
struct vhost_net *net;
|
||||
|
||||
/*
|
||||
* Backends other than vhost-user or vhost-vdpa don't support max queue
|
||||
* size.
|
||||
*/
|
||||
if (!peer) {
|
||||
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
|
||||
goto default_value;
|
||||
}
|
||||
|
||||
switch(peer->info->type) {
|
||||
case NET_CLIENT_DRIVER_VHOST_USER:
|
||||
case NET_CLIENT_DRIVER_VHOST_VDPA:
|
||||
return VIRTQUEUE_MAX_SIZE;
|
||||
default:
|
||||
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
|
||||
};
|
||||
net = get_vhost_net(peer);
|
||||
|
||||
if (!net || !net->max_tx_queue_size) {
|
||||
goto default_value;
|
||||
}
|
||||
|
||||
return net->max_tx_queue_size;
|
||||
|
||||
default_value:
|
||||
return VIRTIO_NET_TX_QUEUE_DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
static int peer_attach(VirtIONet *n, int index)
|
||||
{
|
||||
NetClientState *nc = qemu_get_subqueue(n->nic, index);
|
||||
struct vhost_net *net;
|
||||
|
||||
if (!nc->peer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
vhost_set_vring_enable(nc->peer, 1);
|
||||
net = get_vhost_net(nc->peer);
|
||||
if (net && net->is_vhost_user) {
|
||||
vhost_net_set_vring_enable(nc->peer, 1);
|
||||
}
|
||||
|
||||
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
|
||||
@@ -714,13 +716,15 @@ static int peer_attach(VirtIONet *n, int index)
|
||||
static int peer_detach(VirtIONet *n, int index)
|
||||
{
|
||||
NetClientState *nc = qemu_get_subqueue(n->nic, index);
|
||||
struct vhost_net *net;
|
||||
|
||||
if (!nc->peer) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
|
||||
vhost_set_vring_enable(nc->peer, 0);
|
||||
net = get_vhost_net(nc->peer);
|
||||
if (net && net->is_vhost_user) {
|
||||
vhost_net_set_vring_enable(nc->peer, 0);
|
||||
}
|
||||
|
||||
if (nc->peer->info->type != NET_CLIENT_DRIVER_TAP) {
|
||||
@@ -3022,11 +3026,10 @@ static void virtio_net_del_queue(VirtIONet *n, int index)
|
||||
virtio_del_queue(vdev, index * 2 + 1);
|
||||
}
|
||||
|
||||
static void virtio_net_change_num_queue_pairs(VirtIONet *n, int new_max_queue_pairs)
|
||||
static void virtio_net_change_num_queues(VirtIONet *n, int new_num_queues)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||
int old_num_queues = virtio_get_num_queues(vdev);
|
||||
int new_num_queues = new_max_queue_pairs * 2 + 1;
|
||||
int i;
|
||||
|
||||
assert(old_num_queues >= 3);
|
||||
@@ -3062,16 +3065,14 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue)
|
||||
int max = multiqueue ? n->max_queue_pairs : 1;
|
||||
|
||||
n->multiqueue = multiqueue;
|
||||
virtio_net_change_num_queue_pairs(n, max);
|
||||
virtio_net_change_num_queues(n, max * 2 + 1);
|
||||
|
||||
virtio_net_set_queue_pairs(n);
|
||||
}
|
||||
|
||||
static int virtio_net_pre_load_queues(VirtIODevice *vdev)
|
||||
static int virtio_net_pre_load_queues(VirtIODevice *vdev, uint32_t n)
|
||||
{
|
||||
virtio_net_set_multiqueue(VIRTIO_NET(vdev),
|
||||
virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_RSS) ||
|
||||
virtio_has_feature(vdev->guest_features, VIRTIO_NET_F_MQ));
|
||||
virtio_net_change_num_queues(VIRTIO_NET(vdev), n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+7
-7
@@ -3270,13 +3270,6 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||
config_len--;
|
||||
}
|
||||
|
||||
if (vdc->pre_load_queues) {
|
||||
ret = vdc->pre_load_queues(vdev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
num = qemu_get_be32(f);
|
||||
|
||||
if (num > VIRTIO_QUEUE_MAX) {
|
||||
@@ -3284,6 +3277,13 @@ virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vdc->pre_load_queues) {
|
||||
ret = vdc->pre_load_queues(vdev, num);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
vdev->vq[i].vring.num = qemu_get_be32(f);
|
||||
if (k->has_variable_vring_alignment) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef VHOST_H
|
||||
#define VHOST_H
|
||||
|
||||
#include "net/vhost_net.h"
|
||||
#include "hw/virtio/vhost-backend.h"
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "system/memory.h"
|
||||
@@ -143,6 +144,10 @@ struct vhost_net {
|
||||
struct vhost_dev dev;
|
||||
struct vhost_virtqueue vqs[2];
|
||||
int backend;
|
||||
const int *feature_bits;
|
||||
int max_tx_queue_size;
|
||||
SaveAcketFeatures *save_acked_features;
|
||||
bool is_vhost_user;
|
||||
NetClientState *nc;
|
||||
};
|
||||
|
||||
|
||||
@@ -210,8 +210,14 @@ struct VirtioDeviceClass {
|
||||
void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
|
||||
int (*start_ioeventfd)(VirtIODevice *vdev);
|
||||
void (*stop_ioeventfd)(VirtIODevice *vdev);
|
||||
/* Called before loading queues. Useful to add queues before loading. */
|
||||
int (*pre_load_queues)(VirtIODevice *vdev);
|
||||
/*
|
||||
* Called before loading queues.
|
||||
* If the number of queues change at runtime, use @n to know the
|
||||
* number and add or remove queues accordingly.
|
||||
* Note that this function is called in the middle of loading vmsd;
|
||||
* no assumption should be made on states being loaded from vmsd.
|
||||
*/
|
||||
int (*pre_load_queues)(VirtIODevice *vdev, uint32_t n);
|
||||
/* Saving and loading of a device; trying to deprecate save/load
|
||||
* use vmsd for new devices.
|
||||
*/
|
||||
|
||||
@@ -67,6 +67,7 @@ typedef void (SocketReadStateFinalize)(SocketReadState *rs);
|
||||
typedef void (NetAnnounce)(NetClientState *);
|
||||
typedef bool (SetSteeringEBPF)(NetClientState *, int);
|
||||
typedef bool (NetCheckPeerType)(NetClientState *, ObjectClass *, Error **);
|
||||
typedef struct vhost_net *(GetVHostNet)(NetClientState *nc);
|
||||
|
||||
typedef struct NetClientInfo {
|
||||
NetClientDriver type;
|
||||
@@ -92,6 +93,7 @@ typedef struct NetClientInfo {
|
||||
NetAnnounce *announce;
|
||||
SetSteeringEBPF *set_steering_ebpf;
|
||||
NetCheckPeerType *check_peer_type;
|
||||
GetVHostNet *get_vhost_net;
|
||||
} NetClientInfo;
|
||||
|
||||
struct NetClientState {
|
||||
@@ -298,6 +300,7 @@ void net_client_parse(QemuOptsList *opts_list, const char *optstr);
|
||||
void show_netdevs(void);
|
||||
void net_init_clients(void);
|
||||
void net_check_clients(void);
|
||||
void net_client_set_link(NetClientState **ncs, int queues, bool up);
|
||||
void net_cleanup(void);
|
||||
void hmp_host_net_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_host_net_remove(Monitor *mon, const QDict *qdict);
|
||||
|
||||
@@ -33,7 +33,4 @@ int tap_disable(NetClientState *nc);
|
||||
|
||||
int tap_get_fd(NetClientState *nc);
|
||||
|
||||
struct vhost_net;
|
||||
struct vhost_net *tap_get_vhost_net(NetClientState *nc);
|
||||
|
||||
#endif /* QEMU_NET_TAP_H */
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* vhost-user.h
|
||||
*
|
||||
* Copyright (c) 2013 Virtual Open Systems Sarl.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VHOST_USER_H
|
||||
#define VHOST_USER_H
|
||||
|
||||
struct vhost_net;
|
||||
struct vhost_net *vhost_user_get_vhost_net(NetClientState *nc);
|
||||
uint64_t vhost_user_get_acked_features(NetClientState *nc);
|
||||
void vhost_user_save_acked_features(NetClientState *nc);
|
||||
|
||||
#endif /* VHOST_USER_H */
|
||||
@@ -14,8 +14,4 @@
|
||||
|
||||
#define TYPE_VHOST_VDPA "vhost-vdpa"
|
||||
|
||||
struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
|
||||
|
||||
extern const int vdpa_feature_bits[];
|
||||
|
||||
#endif /* VHOST_VDPA_H */
|
||||
|
||||
@@ -7,11 +7,19 @@
|
||||
struct vhost_net;
|
||||
typedef struct vhost_net VHostNetState;
|
||||
|
||||
typedef uint64_t (GetAckedFeatures)(NetClientState *nc);
|
||||
typedef void (SaveAcketFeatures)(NetClientState *nc);
|
||||
|
||||
typedef struct VhostNetOptions {
|
||||
VhostBackendType backend_type;
|
||||
NetClientState *net_backend;
|
||||
uint32_t busyloop_timeout;
|
||||
unsigned int nvqs;
|
||||
const int *feature_bits;
|
||||
int max_tx_queue_size;
|
||||
bool is_vhost_user;
|
||||
GetAckedFeatures *get_acked_features;
|
||||
SaveAcketFeatures *save_acked_features;
|
||||
void *opaque;
|
||||
} VhostNetOptions;
|
||||
|
||||
@@ -41,7 +49,7 @@ void vhost_net_config_mask(VHostNetState *net, VirtIODevice *dev, bool mask);
|
||||
int vhost_net_notify_migration_done(VHostNetState *net, char* mac_addr);
|
||||
VHostNetState *get_vhost_net(NetClientState *nc);
|
||||
|
||||
int vhost_set_vring_enable(NetClientState * nc, int enable);
|
||||
int vhost_net_set_vring_enable(NetClientState *nc, int enable);
|
||||
|
||||
uint64_t vhost_net_get_acked_features(VHostNetState *net);
|
||||
|
||||
|
||||
@@ -1285,6 +1285,10 @@ if not get_option('slirp').auto() or have_system
|
||||
endif
|
||||
endif
|
||||
|
||||
enable_passt = get_option('passt') \
|
||||
.require(host_os == 'linux', error_message: 'passt is supported only on Linux') \
|
||||
.allowed()
|
||||
|
||||
vde = not_found
|
||||
if not get_option('vde').auto() or have_system or have_tools
|
||||
vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'],
|
||||
@@ -2538,6 +2542,7 @@ if seccomp.found()
|
||||
config_host_data.set('CONFIG_SECCOMP_SYSRAWRC', seccomp_has_sysrawrc)
|
||||
endif
|
||||
config_host_data.set('CONFIG_PIXMAN', pixman.found())
|
||||
config_host_data.set('CONFIG_PASST', enable_passt)
|
||||
config_host_data.set('CONFIG_SLIRP', slirp.found())
|
||||
config_host_data.set('CONFIG_SNAPPY', snappy.found())
|
||||
config_host_data.set('CONFIG_SOLARIS', host_os == 'sunos')
|
||||
@@ -4926,6 +4931,7 @@ if host_os == 'darwin'
|
||||
summary_info += {'vmnet.framework support': vmnet}
|
||||
endif
|
||||
summary_info += {'AF_XDP support': libxdp}
|
||||
summary_info += {'passt support': enable_passt}
|
||||
summary_info += {'slirp support': slirp}
|
||||
summary_info += {'vde support': vde}
|
||||
summary_info += {'netmap support': have_netmap}
|
||||
|
||||
@@ -234,6 +234,8 @@ option('pixman', type : 'feature', value : 'auto',
|
||||
description: 'pixman support')
|
||||
option('slirp', type: 'feature', value: 'auto',
|
||||
description: 'libslirp user mode network backend support')
|
||||
option('passt', type: 'feature', value: 'auto',
|
||||
description: 'passt network backend support')
|
||||
option('vde', type : 'feature', value : 'auto',
|
||||
description: 'vde network backend support')
|
||||
option('vmnet', type : 'feature', value : 'auto',
|
||||
|
||||
+1
-1
@@ -323,7 +323,7 @@ static int af_xdp_umem_create(AFXDPState *s, int sock_fd, Error **errp)
|
||||
|
||||
s->pool = g_new(uint64_t, n_descs);
|
||||
/* Fill the pool in the opposite order, because it's a LIFO queue. */
|
||||
for (i = n_descs; i >= 0; i--) {
|
||||
for (i = n_descs - 1; i >= 0; i--) {
|
||||
s->pool[i] = i * XSK_UMEM__DEFAULT_FRAME_SIZE;
|
||||
}
|
||||
s->n_pool = n_descs;
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
int net_init_dump(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
#ifdef CONFIG_PASST
|
||||
int net_init_passt(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
#endif
|
||||
#ifdef CONFIG_SLIRP
|
||||
int net_init_slirp(const Netdev *netdev, const char *name,
|
||||
NetClientState *peer, Error **errp);
|
||||
|
||||
@@ -285,6 +285,9 @@ void net_hub_check_clients(void)
|
||||
case NET_CLIENT_DRIVER_NIC:
|
||||
has_nic = 1;
|
||||
break;
|
||||
#ifdef CONFIG_PASST
|
||||
case NET_CLIENT_DRIVER_PASST:
|
||||
#endif
|
||||
case NET_CLIENT_DRIVER_USER:
|
||||
case NET_CLIENT_DRIVER_TAP:
|
||||
case NET_CLIENT_DRIVER_SOCKET:
|
||||
|
||||
+5
-1
@@ -1,6 +1,7 @@
|
||||
system_ss.add(files(
|
||||
'announce.c',
|
||||
'checksum.c',
|
||||
'dgram.c',
|
||||
'dump.c',
|
||||
'eth.c',
|
||||
'filter-buffer.c',
|
||||
@@ -12,7 +13,7 @@ system_ss.add(files(
|
||||
'queue.c',
|
||||
'socket.c',
|
||||
'stream.c',
|
||||
'dgram.c',
|
||||
'stream_data.c',
|
||||
'util.c',
|
||||
))
|
||||
|
||||
@@ -33,6 +34,9 @@ system_ss.add(when: 'CONFIG_TCG', if_true: files('filter-replay.c'))
|
||||
if have_l2tpv3
|
||||
system_ss.add(files('l2tpv3.c'))
|
||||
endif
|
||||
if enable_passt
|
||||
system_ss.add(files('passt.c'))
|
||||
endif
|
||||
system_ss.add(when: slirp, if_true: files('slirp.c'))
|
||||
system_ss.add(when: vde, if_true: files('vde.c'))
|
||||
if have_netmap
|
||||
|
||||
@@ -1248,6 +1248,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
|
||||
const char *name,
|
||||
NetClientState *peer, Error **errp) = {
|
||||
[NET_CLIENT_DRIVER_NIC] = net_init_nic,
|
||||
#ifdef CONFIG_PASST
|
||||
[NET_CLIENT_DRIVER_PASST] = net_init_passt,
|
||||
#endif
|
||||
#ifdef CONFIG_SLIRP
|
||||
[NET_CLIENT_DRIVER_USER] = net_init_slirp,
|
||||
#endif
|
||||
@@ -1353,6 +1356,7 @@ void show_netdevs(void)
|
||||
"dgram",
|
||||
"hubport",
|
||||
"tap",
|
||||
"passt",
|
||||
#ifdef CONFIG_SLIRP
|
||||
"user",
|
||||
#endif
|
||||
@@ -1601,21 +1605,11 @@ void colo_notify_filters_event(int event, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_set_link(const char *name, bool up, Error **errp)
|
||||
void net_client_set_link(NetClientState **ncs, int queues, bool up)
|
||||
{
|
||||
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||
NetClientState *nc;
|
||||
int queues, i;
|
||||
int i;
|
||||
|
||||
queues = qemu_find_net_clients_except(name, ncs,
|
||||
NET_CLIENT_DRIVER__MAX,
|
||||
MAX_QUEUE_NUM);
|
||||
|
||||
if (queues == 0) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
"Device '%s' not found", name);
|
||||
return;
|
||||
}
|
||||
nc = ncs[0];
|
||||
|
||||
for (i = 0; i < queues; i++) {
|
||||
@@ -1646,6 +1640,24 @@ void qmp_set_link(const char *name, bool up, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
void qmp_set_link(const char *name, bool up, Error **errp)
|
||||
{
|
||||
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||
int queues;
|
||||
|
||||
queues = qemu_find_net_clients_except(name, ncs,
|
||||
NET_CLIENT_DRIVER__MAX,
|
||||
MAX_QUEUE_NUM);
|
||||
|
||||
if (queues == 0) {
|
||||
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
|
||||
"Device '%s' not found", name);
|
||||
return;
|
||||
}
|
||||
|
||||
net_client_set_link(ncs, queues, up);
|
||||
}
|
||||
|
||||
static void net_vm_change_state_handler(void *opaque, bool running,
|
||||
RunState state)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user