4 * Copyright(c) 2017-2018 Intel Corporation.
5 * Copyright(c) 2020 Red Hat, Inc.
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.
12 #include "qemu/osdep.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>
23 #include "standard-headers/linux/virtio_net.h"
24 #include "monitor/monitor.h"
25 #include "hw/virtio/vhost.h"
27 /* Todo:need to add the multiqueue support here */
28 typedef struct VhostVDPAState
{
30 struct vhost_vdpa vhost_vdpa
;
31 VHostNetState
*vhost_net
;
35 const int vdpa_feature_bits
[] = {
36 VIRTIO_F_NOTIFY_ON_EMPTY
,
37 VIRTIO_RING_F_INDIRECT_DESC
,
38 VIRTIO_RING_F_EVENT_IDX
,
42 VIRTIO_NET_F_GUEST_CSUM
,
44 VIRTIO_NET_F_GUEST_TSO4
,
45 VIRTIO_NET_F_GUEST_TSO6
,
46 VIRTIO_NET_F_GUEST_ECN
,
47 VIRTIO_NET_F_GUEST_UFO
,
48 VIRTIO_NET_F_HOST_TSO4
,
49 VIRTIO_NET_F_HOST_TSO6
,
50 VIRTIO_NET_F_HOST_ECN
,
51 VIRTIO_NET_F_HOST_UFO
,
52 VIRTIO_NET_F_MRG_RXBUF
,
54 VIRTIO_F_IOMMU_PLATFORM
,
57 VIRTIO_NET_F_HASH_REPORT
,
58 VIRTIO_NET_F_GUEST_ANNOUNCE
,
60 VHOST_INVALID_FEATURE_BIT
63 VHostNetState
*vhost_vdpa_get_vhost_net(NetClientState
*nc
)
65 VhostVDPAState
*s
= DO_UPCAST(VhostVDPAState
, nc
, nc
);
66 assert(nc
->info
->type
== NET_CLIENT_DRIVER_VHOST_VDPA
);
70 static int vhost_vdpa_net_check_device_id(struct vhost_net
*net
)
74 struct vhost_dev
*hdev
;
76 hdev
= (struct vhost_dev
*)&net
->dev
;
77 ret
= hdev
->vhost_ops
->vhost_get_device_id(hdev
, &device_id
);
78 if (device_id
!= VIRTIO_ID_NET
) {
84 static int vhost_vdpa_add(NetClientState
*ncs
, void *be
)
86 VhostNetOptions options
;
87 struct vhost_net
*net
= NULL
;
91 options
.backend_type
= VHOST_BACKEND_TYPE_VDPA
;
92 assert(ncs
->info
->type
== NET_CLIENT_DRIVER_VHOST_VDPA
);
93 s
= DO_UPCAST(VhostVDPAState
, nc
, ncs
);
94 options
.net_backend
= ncs
;
96 options
.busyloop_timeout
= 0;
99 net
= vhost_net_init(&options
);
101 error_report("failed to init vhost_net for queue");
105 ret
= vhost_vdpa_net_check_device_id(net
);
111 vhost_net_cleanup(net
);
117 static void vhost_vdpa_cleanup(NetClientState
*nc
)
119 VhostVDPAState
*s
= DO_UPCAST(VhostVDPAState
, nc
, nc
);
122 vhost_net_cleanup(s
->vhost_net
);
123 g_free(s
->vhost_net
);
126 if (s
->vhost_vdpa
.device_fd
>= 0) {
127 qemu_close(s
->vhost_vdpa
.device_fd
);
128 s
->vhost_vdpa
.device_fd
= -1;
132 static bool vhost_vdpa_has_vnet_hdr(NetClientState
*nc
)
134 assert(nc
->info
->type
== NET_CLIENT_DRIVER_VHOST_VDPA
);
139 static bool vhost_vdpa_has_ufo(NetClientState
*nc
)
141 assert(nc
->info
->type
== NET_CLIENT_DRIVER_VHOST_VDPA
);
142 VhostVDPAState
*s
= DO_UPCAST(VhostVDPAState
, nc
, nc
);
143 uint64_t features
= 0;
144 features
|= (1ULL << VIRTIO_NET_F_HOST_UFO
);
145 features
= vhost_net_get_features(s
->vhost_net
, features
);
146 return !!(features
& (1ULL << VIRTIO_NET_F_HOST_UFO
));
150 static bool vhost_vdpa_check_peer_type(NetClientState
*nc
, ObjectClass
*oc
,
153 const char *driver
= object_class_get_name(oc
);
155 if (!g_str_has_prefix(driver
, "virtio-net-")) {
156 error_setg(errp
, "vhost-vdpa requires frontend driver virtio-net-*");
163 static NetClientInfo net_vhost_vdpa_info
= {
164 .type
= NET_CLIENT_DRIVER_VHOST_VDPA
,
165 .size
= sizeof(VhostVDPAState
),
166 .cleanup
= vhost_vdpa_cleanup
,
167 .has_vnet_hdr
= vhost_vdpa_has_vnet_hdr
,
168 .has_ufo
= vhost_vdpa_has_ufo
,
169 .check_peer_type
= vhost_vdpa_check_peer_type
,
172 static int net_vhost_vdpa_init(NetClientState
*peer
, const char *device
,
173 const char *name
, const char *vhostdev
)
175 NetClientState
*nc
= NULL
;
177 int vdpa_device_fd
= -1;
180 nc
= qemu_new_net_client(&net_vhost_vdpa_info
, peer
, device
, name
);
181 snprintf(nc
->info_str
, sizeof(nc
->info_str
), TYPE_VHOST_VDPA
);
182 s
= DO_UPCAST(VhostVDPAState
, nc
, nc
);
183 vdpa_device_fd
= qemu_open_old(vhostdev
, O_RDWR
);
184 if (vdpa_device_fd
== -1) {
187 s
->vhost_vdpa
.device_fd
= vdpa_device_fd
;
188 ret
= vhost_vdpa_add(nc
, (void *)&s
->vhost_vdpa
);
190 qemu_close(vdpa_device_fd
);
191 qemu_del_net_client(nc
);
196 int net_init_vhost_vdpa(const Netdev
*netdev
, const char *name
,
197 NetClientState
*peer
, Error
**errp
)
199 const NetdevVhostVDPAOptions
*opts
;
201 assert(netdev
->type
== NET_CLIENT_DRIVER_VHOST_VDPA
);
202 opts
= &netdev
->u
.vhost_vdpa
;
203 return net_vhost_vdpa_init(peer
, TYPE_VHOST_VDPA
, name
, opts
->vhostdev
);