1 /* 2 * vhost-net support 3 * 4 * Copyright Red Hat, Inc. 2010 5 * 6 * Authors: 7 * Michael S. Tsirkin <mst@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2. See 10 * the COPYING file in the top-level directory. 11 * 12 * Contributions after 2012-01-13 are licensed under the terms of the 13 * GNU GPL, version 2 or (at your option) any later version. 14 */ 15 16 #include "net/net.h" 17 #include "net/tap.h" 18 #include "net/vhost-user.h" 19 20 #include "hw/virtio/virtio-net.h" 21 #include "net/vhost_net.h" 22 #include "qemu/error-report.h" 23 24 #include "config.h" 25 26 #ifdef CONFIG_VHOST_NET 27 #include <linux/vhost.h> 28 #include <sys/socket.h> 29 #include <linux/kvm.h> 30 #include <fcntl.h> 31 #include <netpacket/packet.h> 32 #include <net/ethernet.h> 33 #include <net/if.h> 34 #include <netinet/in.h> 35 36 #include <stdio.h> 37 38 #include "standard-headers/linux/virtio_ring.h" 39 #include "hw/virtio/vhost.h" 40 #include "hw/virtio/virtio-bus.h" 41 42 struct vhost_net { 43 struct vhost_dev dev; 44 struct vhost_virtqueue vqs[2]; 45 int backend; 46 NetClientState *nc; 47 }; 48 49 /* Features supported by host kernel. */ 50 static const int kernel_feature_bits[] = { 51 VIRTIO_F_NOTIFY_ON_EMPTY, 52 VIRTIO_RING_F_INDIRECT_DESC, 53 VIRTIO_RING_F_EVENT_IDX, 54 VIRTIO_NET_F_MRG_RXBUF, 55 VHOST_INVALID_FEATURE_BIT 56 }; 57 58 /* Features supported by others. */ 59 static const int user_feature_bits[] = { 60 VIRTIO_F_NOTIFY_ON_EMPTY, 61 VIRTIO_RING_F_INDIRECT_DESC, 62 VIRTIO_RING_F_EVENT_IDX, 63 64 VIRTIO_F_ANY_LAYOUT, 65 VIRTIO_NET_F_CSUM, 66 VIRTIO_NET_F_GUEST_CSUM, 67 VIRTIO_NET_F_GSO, 68 VIRTIO_NET_F_GUEST_TSO4, 69 VIRTIO_NET_F_GUEST_TSO6, 70 VIRTIO_NET_F_GUEST_ECN, 71 VIRTIO_NET_F_GUEST_UFO, 72 VIRTIO_NET_F_HOST_TSO4, 73 VIRTIO_NET_F_HOST_TSO6, 74 VIRTIO_NET_F_HOST_ECN, 75 VIRTIO_NET_F_HOST_UFO, 76 VIRTIO_NET_F_MRG_RXBUF, 77 VIRTIO_NET_F_STATUS, 78 VIRTIO_NET_F_CTRL_VQ, 79 VIRTIO_NET_F_CTRL_RX, 80 VIRTIO_NET_F_CTRL_VLAN, 81 VIRTIO_NET_F_CTRL_RX_EXTRA, 82 VIRTIO_NET_F_CTRL_MAC_ADDR, 83 VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, 84 85 VIRTIO_NET_F_MQ, 86 87 VHOST_INVALID_FEATURE_BIT 88 }; 89 90 static const int *vhost_net_get_feature_bits(struct vhost_net *net) 91 { 92 const int *feature_bits = 0; 93 94 switch (net->nc->info->type) { 95 case NET_CLIENT_OPTIONS_KIND_TAP: 96 feature_bits = kernel_feature_bits; 97 break; 98 case NET_CLIENT_OPTIONS_KIND_VHOST_USER: 99 feature_bits = user_feature_bits; 100 break; 101 default: 102 error_report("Feature bits not defined for this type: %d", 103 net->nc->info->type); 104 break; 105 } 106 107 return feature_bits; 108 } 109 110 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) 111 { 112 return vhost_get_features(&net->dev, vhost_net_get_feature_bits(net), 113 features); 114 } 115 116 void vhost_net_ack_features(struct vhost_net *net, unsigned features) 117 { 118 net->dev.acked_features = net->dev.backend_features; 119 vhost_ack_features(&net->dev, vhost_net_get_feature_bits(net), features); 120 } 121 122 static int vhost_net_get_fd(NetClientState *backend) 123 { 124 switch (backend->info->type) { 125 case NET_CLIENT_OPTIONS_KIND_TAP: 126 return tap_get_fd(backend); 127 default: 128 fprintf(stderr, "vhost-net requires tap backend\n"); 129 return -EBADFD; 130 } 131 } 132 133 struct vhost_net *vhost_net_init(VhostNetOptions *options) 134 { 135 int r; 136 bool backend_kernel = options->backend_type == VHOST_BACKEND_TYPE_KERNEL; 137 struct vhost_net *net = g_malloc(sizeof *net); 138 139 if (!options->net_backend) { 140 fprintf(stderr, "vhost-net requires net backend to be setup\n"); 141 goto fail; 142 } 143 144 if (backend_kernel) { 145 r = vhost_net_get_fd(options->net_backend); 146 if (r < 0) { 147 goto fail; 148 } 149 net->dev.backend_features = qemu_has_vnet_hdr(options->net_backend) 150 ? 0 : (1 << VHOST_NET_F_VIRTIO_NET_HDR); 151 net->backend = r; 152 } else { 153 net->dev.backend_features = 0; 154 net->backend = -1; 155 } 156 net->nc = options->net_backend; 157 158 net->dev.nvqs = 2; 159 net->dev.vqs = net->vqs; 160 net->dev.vq_index = net->nc->queue_index; 161 162 r = vhost_dev_init(&net->dev, options->opaque, 163 options->backend_type, options->force); 164 if (r < 0) { 165 goto fail; 166 } 167 if (backend_kernel) { 168 if (!qemu_has_vnet_hdr_len(options->net_backend, 169 sizeof(struct virtio_net_hdr_mrg_rxbuf))) { 170 net->dev.features &= ~(1 << VIRTIO_NET_F_MRG_RXBUF); 171 } 172 if (~net->dev.features & net->dev.backend_features) { 173 fprintf(stderr, "vhost lacks feature mask %" PRIu64 174 " for backend\n", 175 (uint64_t)(~net->dev.features & net->dev.backend_features)); 176 vhost_dev_cleanup(&net->dev); 177 goto fail; 178 } 179 } 180 /* Set sane init value. Override when guest acks. */ 181 vhost_net_ack_features(net, 0); 182 return net; 183 fail: 184 g_free(net); 185 return NULL; 186 } 187 188 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev) 189 { 190 return vhost_dev_query(&net->dev, dev); 191 } 192 193 static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index) 194 { 195 net->dev.vq_index = vq_index; 196 } 197 198 static int vhost_net_start_one(struct vhost_net *net, 199 VirtIODevice *dev) 200 { 201 struct vhost_vring_file file = { }; 202 int r; 203 204 net->dev.nvqs = 2; 205 net->dev.vqs = net->vqs; 206 207 r = vhost_dev_enable_notifiers(&net->dev, dev); 208 if (r < 0) { 209 goto fail_notifiers; 210 } 211 212 r = vhost_dev_start(&net->dev, dev); 213 if (r < 0) { 214 goto fail_start; 215 } 216 217 if (net->nc->info->poll) { 218 net->nc->info->poll(net->nc, false); 219 } 220 221 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 222 qemu_set_fd_handler(net->backend, NULL, NULL, NULL); 223 file.fd = net->backend; 224 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 225 const VhostOps *vhost_ops = net->dev.vhost_ops; 226 r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 227 &file); 228 if (r < 0) { 229 r = -errno; 230 goto fail; 231 } 232 } 233 } 234 return 0; 235 fail: 236 file.fd = -1; 237 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 238 while (file.index-- > 0) { 239 const VhostOps *vhost_ops = net->dev.vhost_ops; 240 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 241 &file); 242 assert(r >= 0); 243 } 244 } 245 if (net->nc->info->poll) { 246 net->nc->info->poll(net->nc, true); 247 } 248 vhost_dev_stop(&net->dev, dev); 249 fail_start: 250 vhost_dev_disable_notifiers(&net->dev, dev); 251 fail_notifiers: 252 return r; 253 } 254 255 static void vhost_net_stop_one(struct vhost_net *net, 256 VirtIODevice *dev) 257 { 258 struct vhost_vring_file file = { .fd = -1 }; 259 260 if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP) { 261 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 262 const VhostOps *vhost_ops = net->dev.vhost_ops; 263 int r = vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND, 264 &file); 265 assert(r >= 0); 266 } 267 } else if (net->nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) { 268 for (file.index = 0; file.index < net->dev.nvqs; ++file.index) { 269 const VhostOps *vhost_ops = net->dev.vhost_ops; 270 int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER, 271 &file); 272 assert(r >= 0); 273 } 274 } 275 if (net->nc->info->poll) { 276 net->nc->info->poll(net->nc, true); 277 } 278 vhost_dev_stop(&net->dev, dev); 279 vhost_dev_disable_notifiers(&net->dev, dev); 280 } 281 282 static bool vhost_net_device_endian_ok(VirtIODevice *vdev) 283 { 284 #ifdef TARGET_IS_BIENDIAN 285 #ifdef HOST_WORDS_BIGENDIAN 286 return virtio_is_big_endian(vdev); 287 #else 288 return !virtio_is_big_endian(vdev); 289 #endif 290 #else 291 return true; 292 #endif 293 } 294 295 int vhost_net_start(VirtIODevice *dev, NetClientState *ncs, 296 int total_queues) 297 { 298 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); 299 VirtioBusState *vbus = VIRTIO_BUS(qbus); 300 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); 301 int r, e, i; 302 303 if (!vhost_net_device_endian_ok(dev)) { 304 error_report("vhost-net does not support cross-endian"); 305 r = -ENOSYS; 306 goto err; 307 } 308 309 if (!k->set_guest_notifiers) { 310 error_report("binding does not support guest notifiers"); 311 r = -ENOSYS; 312 goto err; 313 } 314 315 for (i = 0; i < total_queues; i++) { 316 vhost_net_set_vq_index(get_vhost_net(ncs[i].peer), i * 2); 317 } 318 319 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, true); 320 if (r < 0) { 321 error_report("Error binding guest notifier: %d", -r); 322 goto err; 323 } 324 325 for (i = 0; i < total_queues; i++) { 326 r = vhost_net_start_one(get_vhost_net(ncs[i].peer), dev); 327 328 if (r < 0) { 329 goto err_start; 330 } 331 } 332 333 return 0; 334 335 err_start: 336 while (--i >= 0) { 337 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); 338 } 339 e = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); 340 if (e < 0) { 341 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", e); 342 fflush(stderr); 343 } 344 err: 345 return r; 346 } 347 348 void vhost_net_stop(VirtIODevice *dev, NetClientState *ncs, 349 int total_queues) 350 { 351 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(dev))); 352 VirtioBusState *vbus = VIRTIO_BUS(qbus); 353 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); 354 int i, r; 355 356 for (i = 0; i < total_queues; i++) { 357 vhost_net_stop_one(get_vhost_net(ncs[i].peer), dev); 358 } 359 360 r = k->set_guest_notifiers(qbus->parent, total_queues * 2, false); 361 if (r < 0) { 362 fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); 363 fflush(stderr); 364 } 365 assert(r >= 0); 366 } 367 368 void vhost_net_cleanup(struct vhost_net *net) 369 { 370 vhost_dev_cleanup(&net->dev); 371 g_free(net); 372 } 373 374 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx) 375 { 376 return vhost_virtqueue_pending(&net->dev, idx); 377 } 378 379 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, 380 int idx, bool mask) 381 { 382 vhost_virtqueue_mask(&net->dev, dev, idx, mask); 383 } 384 385 VHostNetState *get_vhost_net(NetClientState *nc) 386 { 387 VHostNetState *vhost_net = 0; 388 389 if (!nc) { 390 return 0; 391 } 392 393 switch (nc->info->type) { 394 case NET_CLIENT_OPTIONS_KIND_TAP: 395 vhost_net = tap_get_vhost_net(nc); 396 break; 397 case NET_CLIENT_OPTIONS_KIND_VHOST_USER: 398 vhost_net = vhost_user_get_vhost_net(nc); 399 break; 400 default: 401 break; 402 } 403 404 return vhost_net; 405 } 406 #else 407 struct vhost_net *vhost_net_init(VhostNetOptions *options) 408 { 409 error_report("vhost-net support is not compiled in"); 410 return NULL; 411 } 412 413 bool vhost_net_query(VHostNetState *net, VirtIODevice *dev) 414 { 415 return false; 416 } 417 418 int vhost_net_start(VirtIODevice *dev, 419 NetClientState *ncs, 420 int total_queues) 421 { 422 return -ENOSYS; 423 } 424 void vhost_net_stop(VirtIODevice *dev, 425 NetClientState *ncs, 426 int total_queues) 427 { 428 } 429 430 void vhost_net_cleanup(struct vhost_net *net) 431 { 432 } 433 434 unsigned vhost_net_get_features(struct vhost_net *net, unsigned features) 435 { 436 return features; 437 } 438 void vhost_net_ack_features(struct vhost_net *net, unsigned features) 439 { 440 } 441 442 bool vhost_net_virtqueue_pending(VHostNetState *net, int idx) 443 { 444 return false; 445 } 446 447 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev, 448 int idx, bool mask) 449 { 450 } 451 452 VHostNetState *get_vhost_net(NetClientState *nc) 453 { 454 return 0; 455 } 456 #endif 457