Skip to content

Commit 1e0a84e

Browse files
lulu-github-namemstsirkin
authored andcommitted
vhost-vdpa: introduce vhost-vdpa net client
This patch set introduces a new net client type: vhost-vdpa. vhost-vdpa net client will set up a vDPA device which is specified by a "vhostdev" parameter. Signed-off-by: Lingshan Zhu <[email protected]> Signed-off-by: Tiwei Bie <[email protected]> Signed-off-by: Cindy Lu <[email protected]> Signed-off-by: Jason Wang <[email protected]> Message-Id: <[email protected]> Reviewed-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]> Acked-by: Jason Wang <[email protected]>
1 parent 108a648 commit 1e0a84e

File tree

6 files changed

+282
-3
lines changed

6 files changed

+282
-3
lines changed

include/net/vhost-vdpa.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* vhost-vdpa.h
3+
*
4+
* Copyright(c) 2017-2018 Intel Corporation.
5+
* Copyright(c) 2020 Red Hat, Inc.
6+
*
7+
* This work is licensed under the terms of the GNU GPL, version 2 or later.
8+
* See the COPYING file in the top-level directory.
9+
*
10+
*/
11+
12+
#ifndef VHOST_VDPA_H
13+
#define VHOST_VDPA_H
14+
15+
#define TYPE_VHOST_VDPA "vhost-vdpa"
16+
17+
struct vhost_net *vhost_vdpa_get_vhost_net(NetClientState *nc);
18+
uint64_t vhost_vdpa_get_acked_features(NetClientState *nc);
19+
20+
extern const int vdpa_feature_bits[];
21+
22+
#endif /* VHOST_VDPA_H */

net/Makefile.objs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ tap-obj-$(CONFIG_SOLARIS) = tap-solaris.o
2626
tap-obj-y ?= tap-stub.o
2727
common-obj-$(CONFIG_POSIX) += tap.o $(tap-obj-y)
2828
common-obj-$(CONFIG_WIN32) += tap-win32.o
29-
29+
common-obj-$(CONFIG_VHOST_NET_VDPA) += vhost-vdpa.o
3030
vde.o-libs = $(VDE_LIBS)
3131

3232
common-obj-$(CONFIG_CAN_BUS) += can/

net/clients.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,6 @@ int net_init_netmap(const Netdev *netdev, const char *name,
6161
int net_init_vhost_user(const Netdev *netdev, const char *name,
6262
NetClientState *peer, Error **errp);
6363

64+
int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
65+
NetClientState *peer, Error **errp);
6466
#endif /* QEMU_NET_CLIENTS_H */

net/net.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,9 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
966966
#ifdef CONFIG_VHOST_NET_USER
967967
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
968968
#endif
969+
#ifdef CONFIG_VHOST_NET_VDPA
970+
[NET_CLIENT_DRIVER_VHOST_VDPA] = net_init_vhost_vdpa,
971+
#endif
969972
#ifdef CONFIG_L2TPV3
970973
[NET_CLIENT_DRIVER_L2TPV3] = net_init_l2tpv3,
971974
#endif

net/vhost-vdpa.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* vhost-vdpa.c
3+
*
4+
* Copyright(c) 2017-2018 Intel Corporation.
5+
* Copyright(c) 2020 Red Hat, Inc.
6+
*
7+
* This work is licensed under the terms of the GNU GPL, version 2 or later.
8+
* See the COPYING file in the top-level directory.
9+
*
10+
*/
11+
12+
#include "qemu/osdep.h"
13+
#include "clients.h"
14+
#include "net/vhost_net.h"
15+
#include "net/vhost-vdpa.h"
16+
#include "hw/virtio/vhost-vdpa.h"
17+
#include "qemu/config-file.h"
18+
#include "qemu/error-report.h"
19+
#include "qemu/option.h"
20+
#include "qapi/error.h"
21+
#include <sys/ioctl.h>
22+
#include <err.h>
23+
#include "standard-headers/linux/virtio_net.h"
24+
#include "monitor/monitor.h"
25+
#include "hw/virtio/vhost.h"
26+
27+
/* Todo:need to add the multiqueue support here */
28+
typedef struct VhostVDPAState {
29+
NetClientState nc;
30+
struct vhost_vdpa vhost_vdpa;
31+
VHostNetState *vhost_net;
32+
uint64_t acked_features;
33+
bool started;
34+
} VhostVDPAState;
35+
36+
const int vdpa_feature_bits[] = {
37+
VIRTIO_F_NOTIFY_ON_EMPTY,
38+
VIRTIO_RING_F_INDIRECT_DESC,
39+
VIRTIO_RING_F_EVENT_IDX,
40+
VIRTIO_F_ANY_LAYOUT,
41+
VIRTIO_F_VERSION_1,
42+
VIRTIO_NET_F_CSUM,
43+
VIRTIO_NET_F_GUEST_CSUM,
44+
VIRTIO_NET_F_GSO,
45+
VIRTIO_NET_F_GUEST_TSO4,
46+
VIRTIO_NET_F_GUEST_TSO6,
47+
VIRTIO_NET_F_GUEST_ECN,
48+
VIRTIO_NET_F_GUEST_UFO,
49+
VIRTIO_NET_F_HOST_TSO4,
50+
VIRTIO_NET_F_HOST_TSO6,
51+
VIRTIO_NET_F_HOST_ECN,
52+
VIRTIO_NET_F_HOST_UFO,
53+
VIRTIO_NET_F_MRG_RXBUF,
54+
VIRTIO_NET_F_MTU,
55+
VIRTIO_F_IOMMU_PLATFORM,
56+
VIRTIO_F_RING_PACKED,
57+
VIRTIO_NET_F_GUEST_ANNOUNCE,
58+
VHOST_INVALID_FEATURE_BIT
59+
};
60+
61+
VHostNetState *vhost_vdpa_get_vhost_net(NetClientState *nc)
62+
{
63+
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
64+
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
65+
return s->vhost_net;
66+
}
67+
68+
uint64_t vhost_vdpa_get_acked_features(NetClientState *nc)
69+
{
70+
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
71+
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
72+
s->acked_features = vhost_net_get_acked_features(s->vhost_net);
73+
74+
return s->acked_features;
75+
}
76+
77+
static int vhost_vdpa_net_check_device_id(struct vhost_net *net)
78+
{
79+
uint32_t device_id;
80+
int ret;
81+
struct vhost_dev *hdev;
82+
83+
hdev = (struct vhost_dev *)&net->dev;
84+
ret = hdev->vhost_ops->vhost_get_device_id(hdev, &device_id);
85+
if (device_id != VIRTIO_ID_NET) {
86+
return -ENOTSUP;
87+
}
88+
return ret;
89+
}
90+
91+
static void vhost_vdpa_del(NetClientState *ncs)
92+
{
93+
VhostVDPAState *s;
94+
assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
95+
s = DO_UPCAST(VhostVDPAState, nc, ncs);
96+
if (s->vhost_net) {
97+
vhost_net_cleanup(s->vhost_net);
98+
}
99+
}
100+
101+
static int vhost_vdpa_add(NetClientState *ncs, void *be)
102+
{
103+
VhostNetOptions options;
104+
struct vhost_net *net = NULL;
105+
VhostVDPAState *s;
106+
int ret;
107+
108+
options.backend_type = VHOST_BACKEND_TYPE_VDPA;
109+
assert(ncs->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
110+
s = DO_UPCAST(VhostVDPAState, nc, ncs);
111+
options.net_backend = ncs;
112+
options.opaque = be;
113+
options.busyloop_timeout = 0;
114+
115+
net = vhost_net_init(&options);
116+
if (!net) {
117+
error_report("failed to init vhost_net for queue");
118+
goto err;
119+
}
120+
if (s->vhost_net) {
121+
vhost_net_cleanup(s->vhost_net);
122+
g_free(s->vhost_net);
123+
}
124+
s->vhost_net = net;
125+
ret = vhost_vdpa_net_check_device_id(net);
126+
if (ret) {
127+
goto err;
128+
}
129+
return 0;
130+
err:
131+
if (net) {
132+
vhost_net_cleanup(net);
133+
}
134+
vhost_vdpa_del(ncs);
135+
return -1;
136+
}
137+
138+
static void vhost_vdpa_cleanup(NetClientState *nc)
139+
{
140+
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
141+
142+
if (s->vhost_net) {
143+
vhost_net_cleanup(s->vhost_net);
144+
g_free(s->vhost_net);
145+
s->vhost_net = NULL;
146+
}
147+
}
148+
149+
static bool vhost_vdpa_has_vnet_hdr(NetClientState *nc)
150+
{
151+
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
152+
153+
return true;
154+
}
155+
156+
static bool vhost_vdpa_has_ufo(NetClientState *nc)
157+
{
158+
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA);
159+
VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc);
160+
uint64_t features = 0;
161+
features |= (1ULL << VIRTIO_NET_F_HOST_UFO);
162+
features = vhost_net_get_features(s->vhost_net, features);
163+
return !!(features & (1ULL << VIRTIO_NET_F_HOST_UFO));
164+
165+
}
166+
167+
static NetClientInfo net_vhost_vdpa_info = {
168+
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
169+
.size = sizeof(VhostVDPAState),
170+
.cleanup = vhost_vdpa_cleanup,
171+
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
172+
.has_ufo = vhost_vdpa_has_ufo,
173+
};
174+
175+
static int net_vhost_vdpa_init(NetClientState *peer, const char *device,
176+
const char *name, const char *vhostdev)
177+
{
178+
NetClientState *nc = NULL;
179+
VhostVDPAState *s;
180+
int vdpa_device_fd = -1;
181+
int ret = 0;
182+
assert(name);
183+
nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name);
184+
snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA);
185+
nc->queue_index = 0;
186+
s = DO_UPCAST(VhostVDPAState, nc, nc);
187+
vdpa_device_fd = qemu_open(vhostdev, O_RDWR);
188+
if (vdpa_device_fd == -1) {
189+
return -errno;
190+
}
191+
s->vhost_vdpa.device_fd = vdpa_device_fd;
192+
ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa);
193+
assert(s->vhost_net);
194+
return ret;
195+
}
196+
197+
static int net_vhost_check_net(void *opaque, QemuOpts *opts, Error **errp)
198+
{
199+
const char *name = opaque;
200+
const char *driver, *netdev;
201+
202+
driver = qemu_opt_get(opts, "driver");
203+
netdev = qemu_opt_get(opts, "netdev");
204+
if (!driver || !netdev) {
205+
return 0;
206+
}
207+
if (strcmp(netdev, name) == 0 &&
208+
!g_str_has_prefix(driver, "virtio-net-")) {
209+
error_setg(errp, "vhost-vdpa requires frontend driver virtio-net-*");
210+
return -1;
211+
}
212+
return 0;
213+
}
214+
215+
int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
216+
NetClientState *peer, Error **errp)
217+
{
218+
const NetdevVhostVDPAOptions *opts;
219+
220+
assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
221+
opts = &netdev->u.vhost_vdpa;
222+
/* verify net frontend */
223+
if (qemu_opts_foreach(qemu_find_opts("device"), net_vhost_check_net,
224+
(char *)name, errp)) {
225+
return -1;
226+
}
227+
return net_vhost_vdpa_init(peer, TYPE_VHOST_VDPA, name, opts->vhostdev);
228+
}

qapi/net.json

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,16 +428,39 @@
428428
'*vhostforce': 'bool',
429429
'*queues': 'int' } }
430430

431+
##
432+
# @NetdevVhostVDPAOptions:
433+
#
434+
# Vhost-vdpa network backend
435+
#
436+
# vDPA device is a device that uses a datapath which complies with the virtio
437+
# specifications with a vendor specific control path.
438+
#
439+
# @vhostdev: path of vhost-vdpa device
440+
# (default:'/dev/vhost-vdpa-0')
441+
#
442+
# @queues: number of queues to be created for multiqueue vhost-vdpa
443+
# (default: 1)
444+
#
445+
# Since: 5.1
446+
##
447+
{ 'struct': 'NetdevVhostVDPAOptions',
448+
'data': {
449+
'*vhostdev': 'str',
450+
'*queues': 'int' } }
451+
431452
##
432453
# @NetClientDriver:
433454
#
434455
# Available netdev drivers.
435456
#
436457
# Since: 2.7
458+
#
459+
# @vhost-vdpa since 5.1
437460
##
438461
{ 'enum': 'NetClientDriver',
439462
'data': [ 'none', 'nic', 'user', 'tap', 'l2tpv3', 'socket', 'vde',
440-
'bridge', 'hubport', 'netmap', 'vhost-user' ] }
463+
'bridge', 'hubport', 'netmap', 'vhost-user', 'vhost-vdpa' ] }
441464

442465
##
443466
# @Netdev:
@@ -465,7 +488,8 @@
465488
'bridge': 'NetdevBridgeOptions',
466489
'hubport': 'NetdevHubPortOptions',
467490
'netmap': 'NetdevNetmapOptions',
468-
'vhost-user': 'NetdevVhostUserOptions' } }
491+
'vhost-user': 'NetdevVhostUserOptions',
492+
'vhost-vdpa': 'NetdevVhostVDPAOptions' } }
469493

470494
##
471495
# @NetFilterDirection:

0 commit comments

Comments
 (0)